diff options
Diffstat (limited to 'include/spdlog/fmt/bundled/ostream.h')
-rw-r--r-- | include/spdlog/fmt/bundled/ostream.h | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/include/spdlog/fmt/bundled/ostream.h b/include/spdlog/fmt/bundled/ostream.h new file mode 100644 index 00000000..29c58ec1 --- /dev/null +++ b/include/spdlog/fmt/bundled/ostream.h @@ -0,0 +1,177 @@ +// Formatting library for C++ - std::ostream support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_OSTREAM_H_ +#define FMT_OSTREAM_H_ + +#include <ostream> + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +template <typename Char> class basic_printf_parse_context; +template <typename OutputIt, typename Char> class basic_printf_context; + +namespace detail { + +template <class Char> class formatbuf : public std::basic_streambuf<Char> { + private: + using int_type = typename std::basic_streambuf<Char>::int_type; + using traits_type = typename std::basic_streambuf<Char>::traits_type; + + buffer<Char>& buffer_; + + public: + formatbuf(buffer<Char>& buf) : buffer_(buf) {} + + protected: + // The put-area is actually always empty. This makes the implementation + // simpler and has the advantage that the streambuf and the buffer are always + // in sync and sputc never writes into uninitialized memory. The obvious + // disadvantage is that each call to sputc always results in a (virtual) call + // to overflow. There is no disadvantage here for sputn since this always + // results in a call to xsputn. + + int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast<Char>(ch)); + return ch; + } + + std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE { + buffer_.append(s, s + count); + return count; + } +}; + +struct converter { + template <typename T, FMT_ENABLE_IF(is_integral<T>::value)> converter(T); +}; + +template <typename Char> struct test_stream : std::basic_ostream<Char> { + private: + void_t<> operator<<(converter); +}; + +// Hide insertion operators for built-in types. +template <typename Char, typename Traits> +void_t<> operator<<(std::basic_ostream<Char, Traits>&, Char); +template <typename Char, typename Traits> +void_t<> operator<<(std::basic_ostream<Char, Traits>&, char); +template <typename Traits> +void_t<> operator<<(std::basic_ostream<char, Traits>&, char); +template <typename Traits> +void_t<> operator<<(std::basic_ostream<char, Traits>&, signed char); +template <typename Traits> +void_t<> operator<<(std::basic_ostream<char, Traits>&, unsigned char); + +// Checks if T has a user-defined operator<< (e.g. not a member of +// std::ostream). +template <typename T, typename Char> class is_streamable { + private: + template <typename U> + static bool_constant<!std::is_same<decltype(std::declval<test_stream<Char>&>() + << std::declval<U>()), + void_t<>>::value> + test(int); + + template <typename> static std::false_type test(...); + + using result = decltype(test<T>(0)); + + public: + static const bool value = result::value; +}; + +// Write the content of buf to os. +template <typename Char> +void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) { + const Char* buf_data = buf.data(); + using unsigned_streamsize = std::make_unsigned<std::streamsize>::type; + unsigned_streamsize size = buf.size(); + unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>()); + do { + unsigned_streamsize n = size <= max_size ? size : max_size; + os.write(buf_data, static_cast<std::streamsize>(n)); + buf_data += n; + size -= n; + } while (size != 0); +} + +template <typename Char, typename T> +void format_value(buffer<Char>& buf, const T& value, + locale_ref loc = locale_ref()) { + formatbuf<Char> format_buf(buf); + std::basic_ostream<Char> output(&format_buf); +#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) + if (loc) output.imbue(loc.get<std::locale>()); +#endif + output << value; + output.exceptions(std::ios_base::failbit | std::ios_base::badbit); + buf.try_resize(buf.size()); +} + +// Formats an object of type T that has an overloaded ostream operator<<. +template <typename T, typename Char> +struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>> + : private formatter<basic_string_view<Char>, Char> { + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) + -> decltype(ctx.begin()) { + return formatter<basic_string_view<Char>, Char>::parse(ctx); + } + template <typename ParseCtx, + FMT_ENABLE_IF(std::is_same< + ParseCtx, basic_printf_parse_context<Char>>::value)> + auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template <typename OutputIt> + auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) + -> OutputIt { + basic_memory_buffer<Char> buffer; + format_value(buffer, value, ctx.locale()); + basic_string_view<Char> str(buffer.data(), buffer.size()); + return formatter<basic_string_view<Char>, Char>::format(str, ctx); + } + template <typename OutputIt> + auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx) + -> OutputIt { + basic_memory_buffer<Char> buffer; + format_value(buffer, value, ctx.locale()); + return std::copy(buffer.begin(), buffer.end(), ctx.out()); + } +}; +} // namespace detail + +template <typename Char> +void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) { + basic_memory_buffer<Char> buffer; + detail::vformat_to(buffer, format_str, args); + detail::write_buffer(os, buffer); +} + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + fmt::print(cerr, "Don't {}!", "panic"); + \endrst + */ +template <typename S, typename... Args, + typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>> +void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) { + vprint(os, to_string_view(format_str), + fmt::make_args_checked<Args...>(format_str, args...)); +} +FMT_END_NAMESPACE + +#endif // FMT_OSTREAM_H_ |