// (C) Copyright 2016 by Autodesk, Inc. #ifndef BASE_IOUTPUTSTREAM_HH_INCLUDE #define BASE_IOUTPUTSTREAM_HH_INCLUDE #include #include #if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) #include #endif namespace boost { namespace filesystem { class path; } } namespace Base { typedef unsigned int uint; 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; class IOutputStream { public: virtual ~IOutputStream() {} 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; }; IOutputStream& operator<<(IOutputStream& _ds, const int _i); IOutputStream& operator<<(IOutputStream& _ds, const double _d); IOutputStream& operator<<(IOutputStream& _ds, const char* const _s); IOutputStream& operator<<(IOutputStream& _ds, const char _c); IOutputStream& operator<<(IOutputStream& _ds, const size_t _i); IOutputStream& operator<<(IOutputStream& _ds, const unsigned int _i); IOutputStream& operator<<(IOutputStream& _ds, const float _f); IOutputStream& operator<<(IOutputStream& _ds, const std::string& _s); IOutputStream& operator<<(IOutputStream& _ds, const Command& _co); IOutputStream& operator<<(IOutputStream& _ds, const Command::Type _cmd_type); IOutputStream& operator<<(IOutputStream& _ds, const boost::filesystem::path& _path); // IStream operator for std::vector<> template< typename ElementT> IOutputStream& operator<<(IOutputStream& _ds, const std::vector& _vec) { _ds << "[ "; for (typename std::vector::const_iterator el_it = _vec.begin(); el_it != _vec.end(); ++el_it) { const ElementT el = *el_it; _ds << el << " "; } _ds << "]"; return _ds; } #if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) // IStream operator for std::array<> template< typename ElementT, size_t _el_nmbr> IOutputStream& operator<<(IOutputStream& _ds, const std::array& _vec) { _ds << "[ "; for (const auto el : _vec) _ds << el << " "; _ds << "]"; return _ds; } #endif // IStream operator for fixed size arrays template IOutputStream& operator<<(IOutputStream& _ds, const ElementT(&_arr)[_el_nmbr]) { _ds << "[ "; for (size_t i = 0; i < _el_nmbr; ++i) _ds << _arr[i] << " "; _ds << "]"; return _ds; } // IStream std::pair<> template IOutputStream& operator<<(IOutputStream& _ds, const std::pair& _pair) { _ds << "(" << _pair.first << ", " << _pair.second << ")"; return _ds; } template class OutputStreamAdaptT : public IOutputStream { public: #if 0 // This can pass any variable number of arguments, not available in VC2012 template OutputStreamAdaptT(const ArgsT&... _args) : strm_(_args...) {} #else OutputStreamAdaptT() {} // //TODO: get rid of move constructor, cannot submit C++11 code in Base for now // OutputStreamAdaptT(OutputStreamAdaptT&& _oth) : strm_(std::move(_oth.strm_)) // {} template 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&); }; /*! Old Style secure print function, should be used directly only in exceptional cases. Note: Defined in OStringStream.cc. */ extern int print(char* _bffr, const size_t _bffr_size, const char* _frmt, ...); //! Format a variable for streaming template struct FormatT { public: typedef FormatT Self; FormatT(const char* _frmt, const T& _vrbl) { print(bffr_, _bffr_size, _frmt, _vrbl); } friend IOutputStream& operator<<(IOutputStream& _os, const Self& _frmt) { return _os << _frmt.bffr_; } private: char bffr_[_bffr_size]; }; //! Convenient access to format a variable for streaming template inline FormatT format(const char* _frmt, const T& _vrbl) { return FormatT(_frmt, _vrbl); } //! Format a 64bit size_t variable for streaming in hex (e.g. for hash) inline FormatT format_hex(const size_t _vrbl) { return FormatT("%I64x", _vrbl); } //! Format a 32bit uint variable for streaming in hex (e.g. for hash) inline FormatT format_hex(const uint _vrbl) { return FormatT("%x", _vrbl); } }//namespace Base #endif//BASE_IOUTPUTSTREAM_HH_INCLUDE