ostream.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Formatting library for C++ - std::ostream support
  2. //
  3. // Copyright (c) 2012 - present, Victor Zverovich
  4. // All rights reserved.
  5. //
  6. // For the license information refer to format.h.
  7. #ifndef FMT_OSTREAM_H_
  8. #define FMT_OSTREAM_H_
  9. #include <fstream> // std::filebuf
  10. #ifdef _WIN32
  11. # ifdef __GLIBCXX__
  12. # include <ext/stdio_filebuf.h>
  13. # include <ext/stdio_sync_filebuf.h>
  14. # endif
  15. # include <io.h>
  16. #endif
  17. #include "format.h"
  18. FMT_BEGIN_NAMESPACE
  19. namespace detail {
  20. template <typename Streambuf> class formatbuf : public Streambuf {
  21. private:
  22. using char_type = typename Streambuf::char_type;
  23. using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));
  24. using int_type = typename Streambuf::int_type;
  25. using traits_type = typename Streambuf::traits_type;
  26. buffer<char_type>& buffer_;
  27. public:
  28. explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}
  29. protected:
  30. // The put area is always empty. This makes the implementation simpler and has
  31. // the advantage that the streambuf and the buffer are always in sync and
  32. // sputc never writes into uninitialized memory. A disadvantage is that each
  33. // call to sputc always results in a (virtual) call to overflow. There is no
  34. // disadvantage here for sputn since this always results in a call to xsputn.
  35. auto overflow(int_type ch) -> int_type override {
  36. if (!traits_type::eq_int_type(ch, traits_type::eof()))
  37. buffer_.push_back(static_cast<char_type>(ch));
  38. return ch;
  39. }
  40. auto xsputn(const char_type* s, streamsize count) -> streamsize override {
  41. buffer_.append(s, s + count);
  42. return count;
  43. }
  44. };
  45. // Generate a unique explicit instantion in every translation unit using a tag
  46. // type in an anonymous namespace.
  47. namespace {
  48. struct file_access_tag {};
  49. } // namespace
  50. template <typename Tag, typename BufType, FILE* BufType::*FileMemberPtr>
  51. class file_access {
  52. friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
  53. };
  54. #if FMT_MSC_VERSION
  55. template class file_access<file_access_tag, std::filebuf,
  56. &std::filebuf::_Myfile>;
  57. auto get_file(std::filebuf&) -> FILE*;
  58. #endif
  59. inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data)
  60. -> bool {
  61. FILE* f = nullptr;
  62. #if FMT_MSC_VERSION
  63. if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
  64. f = get_file(*buf);
  65. else
  66. return false;
  67. #elif defined(_WIN32) && defined(__GLIBCXX__)
  68. auto* rdbuf = os.rdbuf();
  69. if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
  70. f = sfbuf->file();
  71. else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
  72. f = fbuf->file();
  73. else
  74. return false;
  75. #else
  76. ignore_unused(os, data, f);
  77. #endif
  78. #ifdef _WIN32
  79. if (f) {
  80. int fd = _fileno(f);
  81. if (_isatty(fd)) {
  82. os.flush();
  83. return write_console(fd, data);
  84. }
  85. }
  86. #endif
  87. return false;
  88. }
  89. inline auto write_ostream_unicode(std::wostream&,
  90. fmt::basic_string_view<wchar_t>) -> bool {
  91. return false;
  92. }
  93. // Write the content of buf to os.
  94. // It is a separate function rather than a part of vprint to simplify testing.
  95. template <typename Char>
  96. void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
  97. const Char* buf_data = buf.data();
  98. using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
  99. unsigned_streamsize size = buf.size();
  100. unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
  101. do {
  102. unsigned_streamsize n = size <= max_size ? size : max_size;
  103. os.write(buf_data, static_cast<std::streamsize>(n));
  104. buf_data += n;
  105. size -= n;
  106. } while (size != 0);
  107. }
  108. template <typename Char, typename T>
  109. void format_value(buffer<Char>& buf, const T& value) {
  110. auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
  111. auto&& output = std::basic_ostream<Char>(&format_buf);
  112. #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
  113. output.imbue(std::locale::classic()); // The default is always unlocalized.
  114. #endif
  115. output << value;
  116. output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
  117. }
  118. template <typename T> struct streamed_view {
  119. const T& value;
  120. };
  121. } // namespace detail
  122. // Formats an object of type T that has an overloaded ostream operator<<.
  123. template <typename Char>
  124. struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
  125. void set_debug_format() = delete;
  126. template <typename T, typename OutputIt>
  127. auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
  128. -> OutputIt {
  129. auto buffer = basic_memory_buffer<Char>();
  130. detail::format_value(buffer, value);
  131. return formatter<basic_string_view<Char>, Char>::format(
  132. {buffer.data(), buffer.size()}, ctx);
  133. }
  134. };
  135. using ostream_formatter = basic_ostream_formatter<char>;
  136. template <typename T, typename Char>
  137. struct formatter<detail::streamed_view<T>, Char>
  138. : basic_ostream_formatter<Char> {
  139. template <typename OutputIt>
  140. auto format(detail::streamed_view<T> view,
  141. basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
  142. return basic_ostream_formatter<Char>::format(view.value, ctx);
  143. }
  144. };
  145. /**
  146. \rst
  147. Returns a view that formats `value` via an ostream ``operator<<``.
  148. **Example**::
  149. fmt::print("Current thread id: {}\n",
  150. fmt::streamed(std::this_thread::get_id()));
  151. \endrst
  152. */
  153. template <typename T>
  154. constexpr auto streamed(const T& value) -> detail::streamed_view<T> {
  155. return {value};
  156. }
  157. namespace detail {
  158. inline void vprint_directly(std::ostream& os, string_view format_str,
  159. format_args args) {
  160. auto buffer = memory_buffer();
  161. detail::vformat_to(buffer, format_str, args);
  162. detail::write_buffer(os, buffer);
  163. }
  164. } // namespace detail
  165. FMT_EXPORT template <typename Char>
  166. void vprint(std::basic_ostream<Char>& os,
  167. basic_string_view<type_identity_t<Char>> format_str,
  168. basic_format_args<buffer_context<type_identity_t<Char>>> args) {
  169. auto buffer = basic_memory_buffer<Char>();
  170. detail::vformat_to(buffer, format_str, args);
  171. if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return;
  172. detail::write_buffer(os, buffer);
  173. }
  174. /**
  175. \rst
  176. Prints formatted data to the stream *os*.
  177. **Example**::
  178. fmt::print(cerr, "Don't {}!", "panic");
  179. \endrst
  180. */
  181. FMT_EXPORT template <typename... T>
  182. void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
  183. const auto& vargs = fmt::make_format_args(args...);
  184. if (detail::is_utf8())
  185. vprint(os, fmt, vargs);
  186. else
  187. detail::vprint_directly(os, fmt, vargs);
  188. }
  189. FMT_EXPORT
  190. template <typename... Args>
  191. void print(std::wostream& os,
  192. basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
  193. Args&&... args) {
  194. vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
  195. }
  196. FMT_EXPORT template <typename... T>
  197. void println(std::ostream& os, format_string<T...> fmt, T&&... args) {
  198. fmt::print(os, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
  199. }
  200. FMT_EXPORT
  201. template <typename... Args>
  202. void println(std::wostream& os,
  203. basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
  204. Args&&... args) {
  205. print(os, L"{}\n", fmt::format(fmt, std::forward<Args>(args)...));
  206. }
  207. FMT_END_NAMESPACE
  208. #endif // FMT_OSTREAM_H_