]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/fmt/include/fmt/ostream.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / fmt / include / fmt / ostream.h
index 5f70fed6180f713aa16af7ab2e86f043ed69c0e1..72ba1da064d9b7f42d8ec2600c165f3eca64f5cb 100644 (file)
@@ -9,20 +9,25 @@
 #define FMT_OSTREAM_H_
 
 #include <ostream>
+
 #include "format.h"
 
 FMT_BEGIN_NAMESPACE
-namespace internal {
+
+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:
-  typedef typename std::basic_streambuf<Char>::int_type int_type;
-  typedef typename std::basic_streambuf<Char>::traits_type traits_type;
+  using int_type = typename std::basic_streambuf<Char>::int_type;
+  using traits_type = typename std::basic_streambuf<Char>::traits_type;
 
-  basic_buffer<Char>& buffer_;
+  buffer<Char>& buffer_;
 
  public:
-  formatbuf(basic_buffer<Char>& buffer) : buffer_(buffer) {}
+  formatbuf(buffer<Char>& buf) : buffer_(buf) {}
 
  protected:
   // The put-area is actually always empty. This makes the implementation
@@ -46,9 +51,13 @@ template <class Char> class formatbuf : public std::basic_streambuf<Char> {
 
 template <typename Char> struct test_stream : std::basic_ostream<Char> {
  private:
-  struct null;
   // Hide all operator<< from std::basic_ostream<Char>.
-  void operator<<(null);
+  void_t<> operator<<(null<>);
+  void_t<> operator<<(const Char*);
+
+  template <typename T, FMT_ENABLE_IF(std::is_convertible<T, int>::value &&
+                                      !std::is_enum<T>::value)>
+  void_t<> operator<<(T);
 };
 
 // Checks if T has a user-defined operator<< (e.g. not a member of
@@ -56,14 +65,14 @@ template <typename Char> struct test_stream : std::basic_ostream<Char> {
 template <typename T, typename Char> class is_streamable {
  private:
   template <typename U>
-  static decltype((void)(internal::declval<test_stream<Char>&>()
-                         << internal::declval<U>()),
-                  std::true_type())
+  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(...);
 
-  typedef decltype(test<T>(0)) result;
+  using result = decltype(test<T>(0));
 
  public:
   static const bool value = result::value;
@@ -71,60 +80,73 @@ template <typename T, typename Char> class is_streamable {
 
 // Write the content of buf to os.
 template <typename Char>
-void write(std::basic_ostream<Char>& os, basic_buffer<Char>& buf) {
-  const Char* data = buf.data();
-  typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize;
-  UnsignedStreamSize size = buf.size();
-  UnsignedStreamSize max_size =
-      internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
+void write(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 {
-    UnsignedStreamSize n = size <= max_size ? size : max_size;
-    os.write(data, static_cast<std::streamsize>(n));
-    data += n;
+    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(basic_buffer<Char>& buffer, const T& value) {
-  internal::formatbuf<Char> format_buf(buffer);
+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);
-  output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
+  if (loc) output.imbue(loc.get<std::locale>());
+#endif
   output << value;
-  buffer.resize(buffer.size());
+  output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+  buf.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,
-    typename std::enable_if<internal::is_streamable<T, Char>::value>::type>
-    : formatter<basic_string_view<Char>, Char> {
-  template <typename Context>
-  auto format(const T& value, Context& ctx) -> decltype(ctx.out()) {
+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;
-    internal::format_value(buffer, value);
+    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 internal
-
-// Disable conversion to int if T has an overloaded operator<< which is a free
-// function (not a member of std::ostream).
-template <typename T, typename Char> struct convert_to_int<T, Char, void> {
-  static const bool value = convert_to_int<T, Char, int>::value &&
-                            !internal::is_streamable<T, Char>::value;
-};
+}  // namespace detail
 
 template <typename Char>
-inline void vprint(
-    std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
-    basic_format_args<typename buffer_context<Char>::type> args) {
+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;
-  internal::vformat_to(buffer, format_str, args);
-  internal::write(os, buffer);
+  detail::vformat_to(buffer, format_str, args);
+  detail::write(os, buffer);
 }
+
 /**
   \rst
   Prints formatted data to the stream *os*.
@@ -135,11 +157,10 @@ inline void vprint(
   \endrst
  */
 template <typename S, typename... Args,
-          FMT_ENABLE_IF(internal::is_string<S>::value)>
-inline void print(std::basic_ostream<FMT_CHAR(S)>& os, const S& format_str,
-                  const Args&... 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),
-         {internal::make_args_checked(format_str, args...)});
+         detail::make_args_checked<Args...>(format_str, args...));
 }
 FMT_END_NAMESPACE