IOutputStream.cc 3.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// (C) Copyright 2016 by Autodesk, Inc.

#include "Base/Security/Mandatory.hh"
#include "IOutputStream.hh"
#include "Base/Code/CodeLink.hh"
#include "Base/Utils/ThrowError.hh"

#include <boost/filesystem.hpp>
#include <string>

namespace Base {

13
IOutputStream& operator<<(IOutputStream& _os, const int _i)
14
{
15
  return _os.print(_i);
16 17
}

18
IOutputStream& operator<<(IOutputStream& _os, const double _d)
19
{
20
  return _os.print(_d);
21 22
}

23
IOutputStream& operator<<(IOutputStream& _os, const char* const _s)
24
{
25
  return _os.print(_s);
26 27
}

28
IOutputStream& operator<<(IOutputStream& _os, const char _c)
29
{
30
  return _os.print(_c);
31 32
}

33
IOutputStream& operator<<(IOutputStream& _os, const size_t _i)
34
{
35
  return _os.print(_i);
36 37
}

38
IOutputStream& operator<<(IOutputStream& _os, const unsigned int _i)
39
{
40
  return _os.print(size_t(_i));
41 42
}

43
IOutputStream& operator<<(IOutputStream& _os, const float _f)
44
{
45
  return _os.print((double)_f);
46 47
}

48
IOutputStream& operator<<(IOutputStream& _os, const std::string& _s)
49
{
50
  return _os.print(_s.c_str());
51 52
}

53
IOutputStream& operator<<(IOutputStream& _os, const Command& _co)
54
{
55
  return _os.print(_co);
56 57
}

58 59 60 61 62 63
IOutputStream& operator<<(IOutputStream& _os, const Command::Type _cmd_type)
{
  return _os.print(Command(_cmd_type));
}


64
IOutputStream& operator<<(IOutputStream& _os, const boost::filesystem::path& _path)
65
{
66 67 68
  return _os << '\"' << _path.string().c_str() << '\"';
}

69 70 71 72 73 74 75 76
// Represent this as an object in the stream, to preserve the streaming order
struct FunctionNameFilter
{
  FunctionNameFilter(const char* _fnct) : fnct_(_fnct) {}
  const char* fnct_;
};

IOutputStream& operator<<(IOutputStream& _os, const FunctionNameFilter& _fnf)
77 78 79 80 81 82
{
  // The goal is to filter unstable text from the function name, e.g., lambdas.
  // MSVC Lambda function name: <lambda_136f4d101172d40b57aea5f0078ce711>
  // Multiple lambdas could be in the same function?
  // TODO: this naming pattern is compiler/platform dependent
  // gcc lambda name is <lambdaX>
83
  
84
  const char lmbd[] = "<lambda";
85
  const char* fnct = _fnf.fnct_;
86 87 88
  for(;;)
  {
    const char* lmbd_pos = strstr(fnct, lmbd);
89
    if (lmbd_pos == NULL)
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
    {// print the rest of the function name
      _os << fnct;
      break;
    }
    // print everything until here (char by char, not optimal, but easy)
    for (; fnct != lmbd_pos; ++fnct)
      _os << *fnct;
    _os << lmbd; // now print lambda
    // and skip until > or end of string
    for (; *fnct != '>' && *fnct != '\0'; ++fnct)
      ;
  } 
  return _os;
}

105 106 107 108 109 110 111 112
IOutputStream& operator<<(IOutputStream& _os, const CodeLink& _lnk)
{
#ifdef WIN32
  const char path_sep = '\\';
#else//!WIN32
  const char path_sep = '/';
#endif//WIN32
  
113 114
  const char* flnm_pntr = strrchr(_lnk.file, path_sep);
  if (flnm_pntr == NULL)
115 116 117 118
    flnm_pntr = _lnk.file;
  else
    ++flnm_pntr;

119
  return _os << "@ [" << FunctionNameFilter(_lnk.fnct) << "() in " 
120 121 122 123 124 125 126 127
    << flnm_pntr << ":" << _lnk.line << "]";
}

}//namespace Base

#ifdef DEB_ON
namespace Debug {

128
Base::IOutputStream& operator<<(Base::IOutputStream& _os, 
129 130
  const ThrowInfo& _thrw_info)
{
131
  return _os << "thrown in " << _thrw_info.modl << " " << _thrw_info.lnk;
132 133 134 135
}

}//namespace Debug
#endif//DEB_ON