Photon 1.0.0
Loading...
Searching...
No Matches
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
17namespace spdlog
18{
19 namespace details
20 {
21 namespace fmt_helper
22 {
23
25 {
26 auto* buf_ptr = view.data();
27 dest.append(buf_ptr, buf_ptr + view.size());
28 }
29
30#ifdef SPDLOG_USE_STD_FORMAT
31 template <typename T>
32 inline void append_int(T n, memory_buf_t& dest)
33 {
34 // Buffer should be large enough to hold all digits (digits10 + 1) and a sign
35 SPDLOG_CONSTEXPR const auto BUF_SIZE = std::numeric_limits<T>::digits10 + 2;
36 char buf[BUF_SIZE];
37
38 auto [ptr, ec] = std::to_chars(buf, buf + BUF_SIZE, n, 10);
39 if (ec == std::errc())
40 {
41 dest.append(buf, ptr);
42 }
43 else
44 {
45 throw_spdlog_ex("Failed to format int", static_cast<int>(ec));
46 }
47 }
48#else
49 template <typename T>
50 inline void append_int(T n, memory_buf_t& dest)
51 {
52 fmt::format_int i(n);
53 dest.append(i.data(), i.data() + i.size());
54 }
55#endif
56
57 template <typename T>
59 {
60 // taken from fmt: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/format.h#L899-L912
61 unsigned int count = 1;
62 for (;;)
63 {
64 // Integer division is slow so do it for a group of four digits instead
65 // of for every digit. The idea comes from the talk by Alexandrescu
66 // "Three Optimization Tips for C++". See speed-test for a comparison.
67 if (n < 10)
68 return count;
69 if (n < 100)
70 return count + 1;
71 if (n < 1000)
72 return count + 2;
73 if (n < 10000)
74 return count + 3;
75 n /= 10000u;
76 count += 4;
77 }
78 }
79
80 template <typename T>
81 inline unsigned int count_digits(T n)
82 {
83 using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
84#ifdef SPDLOG_USE_STD_FORMAT
85 return count_digits_fallback(static_cast<count_type>(n));
86#else
87 return static_cast<unsigned int>(fmt::
88// fmt 7.0.0 renamed the internal namespace to detail.
89// See: https://github.com/fmtlib/fmt/issues/1538
90#if FMT_VERSION < 70000
91 internal
92#else
93 detail
94#endif
95 ::count_digits(static_cast<count_type>(n)));
96#endif
97 }
98
99 inline void pad2(int n, memory_buf_t& dest)
100 {
101 if (n >= 0 && n < 100) // 0-99
102 {
103 dest.push_back(static_cast<char>('0' + n / 10));
104 dest.push_back(static_cast<char>('0' + n % 10));
105 }
106 else // unlikely, but just in case, let fmt deal with it
107 {
108 fmt_lib::format_to(std::back_inserter(dest), SPDLOG_FMT_STRING("{:02}"), n);
109 }
110 }
111
112 template <typename T>
113 inline void pad_uint(T n, unsigned int width, memory_buf_t& dest)
114 {
115 static_assert(std::is_unsigned<T>::value, "pad_uint must get unsigned T");
116 for (auto digits = count_digits(n); digits < width; digits++)
117 {
118 dest.push_back('0');
119 }
120 append_int(n, dest);
121 }
122
123 template <typename T>
124 inline void pad3(T n, memory_buf_t& dest)
125 {
126 static_assert(std::is_unsigned<T>::value, "pad3 must get unsigned T");
127 if (n < 1000)
128 {
129 dest.push_back(static_cast<char>(n / 100 + '0'));
130 n = n % 100;
131 dest.push_back(static_cast<char>((n / 10) + '0'));
132 dest.push_back(static_cast<char>((n % 10) + '0'));
133 }
134 else
135 {
136 append_int(n, dest);
137 }
138 }
139
140 template <typename T>
141 inline void pad6(T n, memory_buf_t& dest)
142 {
143 pad_uint(n, 6, dest);
144 }
145
146 template <typename T>
147 inline void pad9(T n, memory_buf_t& dest)
148 {
149 pad_uint(n, 9, dest);
150 }
151
152 // return fraction of a second of the given time_point.
153 // e.g.
154 // fraction<std::milliseconds>(tp) -> will return the millis part of the second
155 template <typename ToDuration>
156 inline ToDuration time_fraction(log_clock::time_point tp)
157 {
158 using std::chrono::duration_cast;
159 using std::chrono::seconds;
160 auto duration = tp.time_since_epoch();
161 auto secs = duration_cast<seconds>(duration);
162 return duration_cast<ToDuration>(duration) - duration_cast<ToDuration>(secs);
163 }
164
165 } // namespace fmt_helper
166 } // namespace details
167} // namespace spdlog
#define SPDLOG_CONSTEXPR_FUNC
Definition common.h:74
#define SPDLOG_FMT_STRING(format_string)
Definition common.h:60
#define SPDLOG_CONSTEXPR
Definition common.h:70
constexpr auto count() -> size_t
Definition core.h:1538
type
Definition core.h:681
auto ptr(T p) -> const void *
Definition format.h:4568
Definition args.h:20
Definition format.h:3057
Definition bin_to_hex.h:111
void pad6(T n, memory_buf_t &dest)
Definition fmt_helper.h:141
unsigned int count_digits(T n)
Definition fmt_helper.h:81
void pad_uint(T n, unsigned int width, memory_buf_t &dest)
Definition fmt_helper.h:113
void pad3(T n, memory_buf_t &dest)
Definition fmt_helper.h:124
void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)
Definition fmt_helper.h:24
SPDLOG_CONSTEXPR_FUNC unsigned int count_digits_fallback(T n)
Definition fmt_helper.h:58
ToDuration time_fraction(log_clock::time_point tp)
Definition fmt_helper.h:156
void pad9(T n, memory_buf_t &dest)
Definition fmt_helper.h:147
void pad2(int n, memory_buf_t &dest)
Definition fmt_helper.h:99
void append_int(T n, memory_buf_t &dest)
Definition fmt_helper.h:50
Definition async.h:26
fmt::basic_string_view< char > string_view_t
Definition common.h:172
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
Definition common-inl.h:75
fmt::basic_memory_buffer< char, 250 > memory_buf_t
Definition common.h:173
Definition core.h:1434
annotation details
Definition tag_strings.h:125
i
Definition tag_strings.h:60