/* Formatting library for C++ - std::ostream support Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. For the license information refer to format.h. */ #ifndef FMT_OSTREAM_H_ #define FMT_OSTREAM_H_ #include "format.h" #include <ostream> namespace fmt { namespace internal { template <class Char> class FormatBuf : public std::basic_streambuf<Char> { private: typedef typename std::basic_streambuf<Char>::int_type int_type; typedef typename std::basic_streambuf<Char>::traits_type traits_type; Buffer<Char> &buffer_; Char *start_; public: FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) { this->setp(start_, start_ + buffer_.capacity()); } FormatBuf(Buffer<Char> &buffer, Char *start) : buffer_(buffer) , start_(start) { this->setp(start_, start_ + buffer_.capacity()); } int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE { if (!traits_type::eq_int_type(ch, traits_type::eof())) { size_t buf_size = size(); buffer_.resize(buf_size); buffer_.reserve(buf_size * 2); start_ = &buffer_[0]; start_[buf_size] = traits_type::to_char_type(ch); this->setp(start_+ buf_size + 1, start_ + buf_size * 2); } return ch; } size_t size() const { return to_unsigned(this->pptr() - start_); } }; Yes &convert(std::ostream &); struct DummyStream : std::ostream { DummyStream(); // Suppress a bogus warning in MSVC. // Hide all operator<< overloads from std::ostream. void operator<<(Null<>); }; No &operator<<(std::ostream &, int); template<typename T> struct ConvertToIntImpl<T, true> { // Convert to int only if T doesn't have an overloaded operator<<. enum { value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No) }; }; // Write the content of w to os. void write(std::ostream &os, Writer &w); #if FMT_HAS_DECLTYPE_INCOMPLETE_RETURN_TYPES template<typename T> class is_streamable { template<typename U> static auto test(int) -> decltype(std::declval<std::ostream &>() << std::declval<U>(), std::true_type()); template<typename> static auto test(...) -> std::false_type; public: static constexpr bool value = decltype(test<T>(0))::value; }; #endif } // namespace internal // Formats a value. template <typename Char, typename ArgFormatter_, typename T> void format_arg(BasicFormatter<Char, ArgFormatter_> &f, const Char *&format_str, const T &value) { internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; internal::FormatBuf<Char> format_buf(buffer); std::basic_ostream<Char> output(&format_buf); output << value; BasicStringRef<Char> str(&buffer[0], format_buf.size()); typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; format_str = f.format(format_str, MakeArg(str)); } /** \rst Prints formatted data to the stream *os*. **Example**:: print(cerr, "Don't {}!", "panic"); \endrst */ FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); FMT_VARIADIC(void, print, std::ostream &, CStringRef) #if __cplusplus >= 201103L template<typename T, typename Char> typename std::enable_if< !std::is_same< typename std::remove_cv<typename std::decay<T>::type>::type, char * >::value, BasicWriter<Char>& >::type operator<<(BasicWriter<Char> &writer, const T &value) { FMT_STATIC_ASSERT(internal::is_streamable<T>::value, "T must be Streamable"); auto &buffer = writer.buffer(); Char *start = &buffer[0] + buffer.size(); internal::FormatBuf<Char> format_buf(buffer, start); std::basic_ostream<Char> output(&format_buf); output << value; buffer.resize(buffer.size() + format_buf.size()); return writer; } #endif } // namespace fmt #ifdef FMT_HEADER_ONLY # include "ostream.cc" #endif #endif // FMT_OSTREAM_H_