IOutputStream.hh 6.94 KB
Newer Older
1 2 3 4 5 6 7
// (C) Copyright 2016 by Autodesk, Inc.

#ifndef BASE_IOUTPUTSTREAM_HH_INCLUDE
#define BASE_IOUTPUTSTREAM_HH_INCLUDE

#include <string>
#include <vector>
8
#include <stdint.h>
9
#include <inttypes.h>
10 11 12 13
#include <limits.h>
// Find out if we need separate streaming operators for uint and size_t
#if ((UINT_MAX) != (SIZE_MAX))
#define UINT_SIZET_DIFFER
14
#endif
15

Max Lyon's avatar
Max Lyon committed
16 17
#include <Base/Config/BaseDefines.hh>

Martin Heistermann's avatar
Martin Heistermann committed
18 19
#include <CoMISo/Config/config.hh>

20 21 22 23
#ifdef STD_ARRAY_AVAILABLE
#include <array>
#endif//STD_ARRAY_AVAILABLE

24 25 26 27 28 29 30 31
namespace boost {
namespace filesystem {
class path;
}
}

namespace Base {

32 33
typedef unsigned int uint;

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
struct Command
{
  enum Type
  {
    END     = 0x01,
    END_LF  = 0x03,
    END_ERR = 0x07
  };

  Type cmd;

  Command(Type _cmd) : cmd(_cmd) {}
};

// use Base::ENDL to stream endline to IOutputStream (same as std::endl)
const Command ENDL = Command::END_LF;
const Command LF = Command::END_LF;

52
class BASEDLLEXPORT IOutputStream
53 54 55
{
public:
  virtual ~IOutputStream() {}
56 57 58 59 60 61
  virtual IOutputStream& print(const char) = 0;
  virtual IOutputStream& print(const int) = 0;
  virtual IOutputStream& print(const size_t) = 0;
  virtual IOutputStream& print(const double) = 0;
  virtual IOutputStream& print(const char* const) = 0;
  virtual IOutputStream& print(const Command&) = 0;
62 63 64

  /*! Print an array of ElementT */
  template <typename ElementT> 
65
  inline IOutputStream& print(const size_t _nmbr, const ElementT* const _elems)
66
  {
67
    print("[ ");
68
    for (size_t i = 0; i < _nmbr; ++i)
69 70 71 72 73
    {
      *this << _elems[i];
      print(' ');
    }
    print(']');
74 75
    return *this;
  }
76 77
};

78
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const int _i);
79

80
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const double _d);
81

82
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const char* const _s);
83

84
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const char _c);
85

86
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const size_t _i);
87

88
#ifdef UINT_SIZET_DIFFER
89
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const unsigned int _i);
90
#endif//UINT_SIZET_DIFFER
91

92
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const float _f);
93

94
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const std::string& _s);
95

96
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const Command& _co);
97

98
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const Command::Type _cmd_type);
99

Martin Heistermann's avatar
Martin Heistermann committed
100
#if COMISO_BOOST_AVAILABLE
101
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os,
102
  const boost::filesystem::path& _path);
Martin Heistermann's avatar
Martin Heistermann committed
103
#endif // COMISO_BOOST_AVAILABLE
104

105
//! IStream operator for std::vector<>
106 107
template <typename ElementT>
IOutputStream& operator<<(IOutputStream& _os, const std::vector<ElementT>& _vec)
108
{
109 110
  return _vec.empty() ? _os.print(0, (ElementT*)NULL) :
    _os.print(_vec.size(), &_vec[0]);
111 112
}

113 114
#ifdef STD_ARRAY_AVAILABLE
//! IStream operator for std::array<>
115 116 117
template <typename ElementT, size_t _nmbr>
IOutputStream& operator<<(IOutputStream& _os, 
  const std::array<ElementT, _nmbr>& _vec)
118
{
119
  return _os.print(_nmbr, &_vec[0]);
120
}
121 122 123 124 125 126

//! Partial specialization for an empty std::array<>
template <typename ElementT>
IOutputStream& operator<<(IOutputStream& _os, 
  const std::array<ElementT, 0>& /*_vec*/)
{
Max Lyon's avatar
Max Lyon committed
127
  return _os.print(0, (ElementT*)NULL);
128 129 130
}

#endif// STD_ARRAY_AVAILABLE
131 132

// IStream operator for fixed size arrays
133 134
template <typename ElementT, size_t _nmbr>
IOutputStream& operator<<(IOutputStream& _os, const ElementT(&_vec)[_nmbr])
135
{
136
  return _os.print(_nmbr, &_vec[0]);
137 138 139 140
}

// IStream std::pair<>
template <typename T0, typename T1>
141
IOutputStream& operator<<(IOutputStream& _os, const std::pair<T0, T1>& _pair)
142
{
143 144
  _os << "(" << _pair.first << ", " << _pair.second << ")";
  return _os;
145 146 147 148 149 150 151 152 153 154 155 156 157 158
}

template <class StreamT> 
class OutputStreamAdaptT : public IOutputStream
{
public:
#if 0
  // This can pass any variable number of arguments, not available in VC2012
  template <typename... ArgsT> OutputStreamAdaptT(const ArgsT&... _args)
    : strm_(_args...) {}

#else
  OutputStreamAdaptT() {}

159 160 161
//  //TODO: get rid of move constructor, cannot submit C++11 code in Base for now
//  OutputStreamAdaptT(OutputStreamAdaptT&& _oth) : strm_(std::move(_oth.strm_))
//  {}
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

  template <typename ArgT> 
  OutputStreamAdaptT(const ArgT& _arg) : strm_(_arg) {}
#endif

  virtual IOutputStream& print(const char _c) { strm_ << _c; return *this; }
  virtual IOutputStream& print(const int _i) { strm_ << _i; return *this;  }
  virtual IOutputStream& print(const size_t _i) { strm_ << _i; return *this;  }
  virtual IOutputStream& print(const double _d) { strm_ << _d; return *this;  }
  virtual IOutputStream& print(const char* const _str) 
  { 
    strm_ << _str; 
    return *this; 
  }

  virtual IOutputStream& print(const Command& _cmd)
  {
    if ((_cmd.cmd & Command::END_LF) == (int)Command::END_LF)
      strm_ << '\n'; // end line on both END_LF and END_ERR
    return *this;
  }

  StreamT& stream() { return strm_; }
  const StreamT& stream() const { return strm_; }

protected:
  StreamT strm_;
private:
  OutputStreamAdaptT(const OutputStreamAdaptT& _oth);
  OutputStreamAdaptT& operator=(const OutputStreamAdaptT&);
};

194 195 196 197
/*! 
Old Style secure print function, should be used directly only in exceptional
cases. Note: Defined in OStringStream.cc.
*/
198 199
extern int print(char* _bffr, const size_t _bffr_size, const char* const _frmt, 
  ...);
200 201

//! Format a variable for streaming
202
template <const size_t _bffr_size = 128>
203 204 205
struct FormatT
{
public:
206
  typedef FormatT<_bffr_size> Self;
207

208 209
  template <typename T>
  FormatT(const char* const _frmt, const T& _vrbl)
210 211 212 213
  {
    print(bffr_, _bffr_size, _frmt, _vrbl);
  }

214 215 216 217 218 219 220 221 222 223 224 225

#if __cplusplus >= 201103L || _MSC_VER >= 1900 //C++11 support
  
  // Variadic template constructor
  template <typename... ArgT> 
  FormatT(const char* const _frmt, const ArgT&... _args)
  {
    print(bffr_, _bffr_size, _frmt, _args...);
  }

#endif//C++11 support

226 227 228 229 230
  friend IOutputStream& operator<<(IOutputStream& _os, const Self& _frmt)
  {
    return _os << _frmt.bffr_;
  }

231 232
  const char* buffer() const { return bffr_; }

233 234 235 236 237 238
private:
  char bffr_[_bffr_size];
};

//! Convenient access to format a variable for streaming
template <typename T>
239
inline FormatT<> format(const char* const _frmt, const T& _vrbl) 
240
{ 
241
  return FormatT<>(_frmt, _vrbl); 
242 243
}

244

245 246 247 248 249 250 251 252
namespace FormatHex {

template <int byte_nmbr> struct CastT;
template <> struct CastT<4> { typedef uint32_t Type; };
template <> struct CastT<8> { typedef uint64_t Type; };

}//FormatHex

253
//! Format a 32bit uint variable for streaming in hex (e.g. for hash)
254 255 256
template <typename T> //!< 32 or 64 bit type 
inline FormatT<> format_hex(const T _vrbl)
{
257
  return format_hex(typename FormatHex::CastT<sizeof(T)>::Type(_vrbl));
258 259 260
}

template <>
261 262
inline FormatT<> format_hex(const uint32_t _vrbl)
{
263
  return FormatT<>("%" PRIx32, _vrbl);
264 265
}

266
//! Format a 64bit size_t variable for streaming in hex (e.g. for hash)
267
template <>
268
inline FormatT<> format_hex(const uint64_t _vrbl) 
269
{ 
270
  return FormatT<>("%" PRIx64, _vrbl);
271 272
}

273

274
}//namespace Base
Martin Heistermann's avatar
Martin Heistermann committed
275 276


277
#endif//BASE_IOUTPUTSTREAM_HH_INCLUDE