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

#ifndef BASE_IOUTPUTSTREAM_HH_INCLUDE
#define BASE_IOUTPUTSTREAM_HH_INCLUDE

#include <string>
#include <vector>
8
#include <stdint.h>
9
#include <cinttypes>
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>

18
19
20
21
#ifdef STD_ARRAY_AVAILABLE
#include <array>
#endif//STD_ARRAY_AVAILABLE

22
23
namespace Base {

24
25
typedef unsigned int uint;

26
// use Base::ENDL to stream endline to IOutputStream (same as std::endl)
27
const char ENDL = '\n'; 
28

29
class BASEDLLEXPORT IOutputStream
30
31
32
{
public:
  virtual ~IOutputStream() {}
33
34
35
  virtual IOutputStream& print(const char) = 0;
  virtual IOutputStream& print(const int) = 0;
  virtual IOutputStream& print(const size_t) = 0;
36
  virtual IOutputStream& print(const float) = 0;
37
38
  virtual IOutputStream& print(const double) = 0;
  virtual IOutputStream& print(const char* const) = 0;
39
40

  /*! Print an array of ElementT */
41
42
  template <typename IteratorT> 
  inline IOutputStream& print(const IteratorT _bgn_it, const IteratorT _end_it)
43
  {
44
    print("[ ");
45
    for (auto it = _bgn_it; it != _end_it; ++it)
46
    {
47
      *this << *it;
48
49
50
      print(' ');
    }
    print(']');
51
52
    return *this;
  }
53
54
55
56
57
58

  template <typename ElementT> 
  inline IOutputStream& print(const size_t _nmbr, const ElementT* const _elems)
  {
    return print(_elems, _elems + _nmbr);
  }
59
60
};

61
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const int _i);
62

63
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const double _d);
64

65
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const char* const _s);
66

67
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const char _c);
68

69
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const size_t _i);
70

71
#ifdef UINT_SIZET_DIFFER
72
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const unsigned int _i);
73
#endif//UINT_SIZET_DIFFER
74

75
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const float _f);
76

77
BASEDLLEXPORT IOutputStream& operator<<(IOutputStream& _os, const std::string& _s);
78

79
//! IStream operator for std::vector<>
80
81
82
83
84
85
86
87
#define BASE_STREAM_CONTAINER(CONTAINER) \
  template <typename ElementT> \
  Base::IOutputStream& operator<<( \
      Base::IOutputStream& _os, const CONTAINER<ElementT>& _cntr) \
  { \
    return _os.print(_cntr.begin(), _cntr.end()); \
  }

Max Lyon's avatar
Max Lyon committed
88
BASE_STREAM_CONTAINER(std::vector)
89

90
91
#ifdef STD_ARRAY_AVAILABLE
//! IStream operator for std::array<>
92
93
94
template <typename ElementT, size_t _nmbr>
IOutputStream& operator<<(IOutputStream& _os, 
  const std::array<ElementT, _nmbr>& _vec)
95
{
96
  return _os.print(_nmbr, &_vec[0]);
97
}
98
99
100
101
102
103

//! Partial specialization for an empty std::array<>
template <typename ElementT>
IOutputStream& operator<<(IOutputStream& _os, 
  const std::array<ElementT, 0>& /*_vec*/)
{
104
  return _os.print(0, (ElementT*)nullptr);
105
106
107
}

#endif// STD_ARRAY_AVAILABLE
108
109

// IStream operator for fixed size arrays
110
111
template <typename ElementT, size_t _nmbr>
IOutputStream& operator<<(IOutputStream& _os, const ElementT(&_vec)[_nmbr])
112
{
113
  return _os.print(_nmbr, &_vec[0]);
114
115
116
117
}

// IStream std::pair<>
template <typename T0, typename T1>
118
IOutputStream& operator<<(IOutputStream& _os, const std::pair<T0, T1>& _pair)
119
{
120
121
  _os << "(" << _pair.first << ", " << _pair.second << ")";
  return _os;
122
123
124
125
126
127
128
129
130
131
132
133
134
135
}

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() {}

136
137
138
//  //TODO: get rid of move constructor, cannot submit C++11 code in Base for now
//  OutputStreamAdaptT(OutputStreamAdaptT&& _oth) : strm_(std::move(_oth.strm_))
//  {}
139
140
141
142
143

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

144
145
146
147
  IOutputStream& print(const char _c) override
  {
    strm_ << _c;
    return *this;
148
149
  }

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  IOutputStream& print(const int _i) override
  {
    strm_ << _i;
    return *this;
  }

  IOutputStream& print(const size_t _i) override
  {
    strm_ << _i;
    return *this;
  }

  IOutputStream& print(const float _f) override
  {
    strm_ << _f;
    return *this;
  }

  IOutputStream& print(const double _d) override
  {
    strm_ << _d;
    return *this;
  }

  IOutputStream& print(const char* const _str) override
  {
    strm_ << _str;
    return *this;
  }

180
181
182
183
184
  StreamT& stream() { return strm_; }
  const StreamT& stream() const { return strm_; }

protected:
  StreamT strm_;
185

186
187
188
189
190
private:
  OutputStreamAdaptT(const OutputStreamAdaptT& _oth);
  OutputStreamAdaptT& operator=(const OutputStreamAdaptT&);
};

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

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

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

211
212
213
214
215
216
217
218
219
220
221
222

#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

223
224
225
226
227
  friend IOutputStream& operator<<(IOutputStream& _os, const Self& _frmt)
  {
    return _os << _frmt.bffr_;
  }

228
229
  const char* buffer() const { return bffr_; }

230
231
232
233
234
235
private:
  char bffr_[_bffr_size];
};

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

241
242
243
244
245
namespace FormatHex {

template <int byte_nmbr> struct CastT;
template <> struct CastT<4> { typedef uint32_t Type; };
template <> struct CastT<8> { typedef uint64_t Type; };
246
247
248
const char* const PREFIX_VOID = "";
const char* const PREFIX_0x = "0x";
const char* const PREFIX_0X = "0X";
249
250
251

}//FormatHex

252
253
254
255
//! Format an unsigned int variable for streaming in hex (e.g. for hash)
template <typename T> //!< 32 or 64 bit type
inline FormatT<> format_hex(
    const T _vrbl, const char* const _prfx = FormatHex::PREFIX_VOID)
256
{
257
  return format_hex(typename FormatHex::CastT<sizeof(T)>::Type(_vrbl), _prfx);
258
259
}

260
//! Format a 32-bit unsigned int variable for streaming in hex (e.g. for hash)
261
template <>
262
inline FormatT<> format_hex(const uint32_t _vrbl, const char* const _prfx)
263
{
264
  return FormatT<>("%s%" PRIx32, _prfx, _vrbl);
265
266
}

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

274
275
}//namespace Base
#endif//BASE_IOUTPUTSTREAM_HH_INCLUDE