Agora  1.2.0
Agora project
fmt_helper.h
Go to the documentation of this file.
1 // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
2 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
3 #pragma once
4 
5 #include <chrono>
6 #include <type_traits>
7 #include <iterator>
8 #include <spdlog/fmt/fmt.h>
9 #include <spdlog/common.h>
10 
11 #ifdef SPDLOG_USE_STD_FORMAT
12 # include <charconv>
13 # include <limits>
14 #endif
15 
16 // Some fmt helpers to efficiently format and pad ints and strings
17 namespace spdlog {
18 namespace details {
19 namespace fmt_helper {
20 
22 {
23  return spdlog::string_view_t{buf.data(), buf.size()};
24 }
25 
27 {
28  auto *buf_ptr = view.data();
29  dest.append(buf_ptr, buf_ptr + view.size());
30 }
31 
32 #ifdef SPDLOG_USE_STD_FORMAT
33 template<typename T>
34 inline void append_int(T n, memory_buf_t &dest)
35 {
36  // Buffer should be large enough to hold all digits (digits10 + 1) and a sign
37  SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits<T>::digits10 + 2;
38  char buf[BUF_SIZE];
39 
40  auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10);
41  if (ec == std::errc())
42  {
43  dest.append(buf, ptr);
44  }
45  else
46  {
47  throw_spdlog_ex("Failed to format int", static_cast<int>(ec));
48  }
49 }
50 #else
51 template<typename T>
52 inline void append_int(T n, memory_buf_t &dest)
53 {
55  dest.append(i.data(), i.data() + i.size());
56 }
57 #endif
58 
59 template<typename T>
61 {
62  // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912
63  unsigned int count = 1;
64  for (;;)
65  {
66  // Integer division is slow so do it for a group of four digits instead
67  // of for every digit. The idea comes from the talk by Alexandrescu
68  // "Three Optimization Tips for C++". See speed-test for a comparison.
69  if (n < 10)
70  return count;
71  if (n < 100)
72  return count + 1;
73  if (n < 1000)
74  return count + 2;
75  if (n < 10000)
76  return count + 3;
77  n /= 10000u;
78  count += 4;
79  }
80 }
81 
82 template<typename T>
83 inline unsigned int count_digits(T n)
84 {
85  using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
86 #ifdef SPDLOG_USE_STD_FORMAT
87  return count_digits_fallback(static_cast<count_type>(n));
88 #else
89  return static_cast<unsigned int>(fmt::
90 // fmt 7.0.0 renamed the internal namespace to detail.
91 // See: https://github.com/fmtlib/fmt/issues/1538
92 # if FMT_VERSION < 70000
93  internal
94 # else
95  detail
96 # endif
97  ::count_digits(static_cast<count_type>(n)));
98 #endif
99 }
100 
101 inline void pad2(int n, memory_buf_t &dest)
102 {
103  if (n >= 0 && n < 100) // 0-99
104  {
105  dest.push_back(static_cast<char>('0' + n / 10));
106  dest.push_back(static_cast<char>('0' + n % 10));
107  }
108  else // unlikely, but just in case, let fmt deal with it
109  {
110  fmt_lib::format_to(std::back_inserter(dest), "{:02}", n);
111  }
112 }
113 
114 template<typename T>
115 inline void pad_uint(T n, unsigned int width, memory_buf_t &dest)
116 {
117  static_assert(std::is_unsigned<T>::value, "pad_uint must get unsigned T");
118  for (auto digits = count_digits(n); digits < width; digits++)
119  {
120  dest.push_back('0');
121  }
122  append_int(n, dest);
123 }
124 
125 template<typename T>
126 inline void pad3(T n, memory_buf_t &dest)
127 {
128  static_assert(std::is_unsigned<T>::value, "pad3 must get unsigned T");
129  if (n < 1000)
130  {
131  dest.push_back(static_cast<char>(n / 100 + '0'));
132  n = n % 100;
133  dest.push_back(static_cast<char>((n / 10) + '0'));
134  dest.push_back(static_cast<char>((n % 10) + '0'));
135  }
136  else
137  {
138  append_int(n, dest);
139  }
140 }
141 
142 template<typename T>
143 inline void pad6(T n, memory_buf_t &dest)
144 {
145  pad_uint(n, 6, dest);
146 }
147 
148 template<typename T>
149 inline void pad9(T n, memory_buf_t &dest)
150 {
151  pad_uint(n, 9, dest);
152 }
153 
154 // return fraction of a second of the given time_point.
155 // e.g.
156 // fraction<std::milliseconds>(tp) -> will return the millis part of the second
157 template<typename ToDuration>
158 inline ToDuration time_fraction(log_clock::time_point tp)
159 {
160  using std::chrono::duration_cast;
161  using std::chrono::seconds;
162  auto duration = tp.time_since_epoch();
163  auto secs = duration_cast<seconds>(duration);
164  return duration_cast<ToDuration>(duration) - duration_cast<ToDuration>(secs);
165 }
166 
167 } // namespace fmt_helper
168 } // namespace details
169 } // namespace spdlog
fmt::v8::format_to
auto format_to(OutputIt out, const text_style &ts, const S &format_str, Args &&... args) -> typename std::enable_if< enable, OutputIt >::type
Definition: color.h:628
SPDLOG_NOEXCEPT
#define SPDLOG_NOEXCEPT
Definition: common.h:64
fmt::v8::detail::buffer::push_back
void push_back(const T &value)
Definition: core.h:849
spdlog::details::fmt_helper::count_digits_fallback
SPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n)
Definition: fmt_helper.h:60
Catch::Generators::value
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:3999
fmt::v8::basic_string_view
Definition: core.h:448
detail
Definition: fmt.cpp:13
fmt::v8::basic_string_view::size
constexpr auto size() const -> size_t
Definition: core.h:495
count
count
Definition: inspect_agora_results.m:96
nlohmann::json_v3_11_1NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON::detail::to_chars
char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition: json.hpp:17639
T
T
Definition: simulate_performance.m:4
fmt::v8::basic_memory_buffer
Definition: format.h:677
spdlog
Definition: async.h:25
spdlog::throw_spdlog_ex
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
Definition: common-inl.h:72
fmt::v8::ptr
auto ptr(T p) -> const void *
Definition: format.h:2680
i
for i
Definition: generate_data.m:107
u
Plot Rx waveform for u
Definition: inspect_single_frame.m:108
SPDLOG_CONSTEXPR_FUNC
#define SPDLOG_CONSTEXPR_FUNC
Definition: common.h:69
spdlog::details::fmt_helper::to_string_view
spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT
Definition: fmt_helper.h:21
spdlog::details::fmt_helper::pad3
void pad3(T n, memory_buf_t &dest)
Definition: fmt_helper.h:126
fmt::v8::basic_memory_buffer::append
void append(const ContiguousRange &range)
Definition: format.h:771
fmt::v8::detail::digits10
constexpr auto digits10() -> int
Definition: format.h:1042
n
n
Definition: simulate_performance.m:1
fmt::v8::basic_string_view::data
constexpr auto data() const -> const Char *
Definition: core.h:492
common.h
fmt::v8::format_int
Definition: format.h:2501
spdlog::details::fmt_helper::pad_uint
void pad_uint(T n, unsigned int width, memory_buf_t &dest)
Definition: fmt_helper.h:115
spdlog::details::fmt_helper::count_digits
unsigned int count_digits(T n)
Definition: fmt_helper.h:83
spdlog::details::fmt_helper::append_string_view
void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)
Definition: fmt_helper.h:26
spdlog::details::fmt_helper::time_fraction
ToDuration time_fraction(log_clock::time_point tp)
Definition: fmt_helper.h:158
fmt
Definition: bin_to_hex.h:102
spdlog::details::fmt_helper::pad6
void pad6(T n, memory_buf_t &dest)
Definition: fmt_helper.h:143
spdlog::details::fmt_helper::append_int
void append_int(T n, memory_buf_t &dest)
Definition: fmt_helper.h:52
spdlog::details::fmt_helper::pad2
void pad2(int n, memory_buf_t &dest)
Definition: fmt_helper.h:101
fmt.h
SPDLOG_CONSTEXPR
#define SPDLOG_CONSTEXPR
Definition: common.h:65
fmt::v8::detail::type
type
Definition: core.h:1131
spdlog::details::fmt_helper::pad9
void pad9(T n, memory_buf_t &dest)
Definition: fmt_helper.h:149