/proc/self/cwd/external/com_google_absl/absl/strings/internal/str_format/extension.h
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright 2017 The Abseil Authors. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | // |
16 | | #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ |
17 | | #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ |
18 | | |
19 | | |
20 | | #include <cstddef> |
21 | | #include <cstdint> |
22 | | #include <cstring> |
23 | | #include <ostream> |
24 | | #include <string> |
25 | | |
26 | | #include "absl/base/config.h" |
27 | | #include "absl/strings/internal/str_format/output.h" |
28 | | #include "absl/strings/string_view.h" |
29 | | |
30 | | namespace absl { |
31 | | ABSL_NAMESPACE_BEGIN |
32 | | |
33 | | enum class FormatConversionChar : uint8_t; |
34 | | enum class FormatConversionCharSet : uint64_t; |
35 | | enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none }; |
36 | | |
37 | | namespace str_format_internal { |
38 | | |
39 | | class FormatRawSinkImpl { |
40 | | public: |
41 | | // Implicitly convert from any type that provides the hook function as |
42 | | // described above. |
43 | | template <typename T, decltype(str_format_internal::InvokeFlush( |
44 | | std::declval<T*>(), string_view()))* = nullptr> |
45 | | FormatRawSinkImpl(T* raw) // NOLINT |
46 | 4.96k | : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {} absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, (void*)0>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) Line | Count | Source | 46 | 4.96k | : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {} |
Unexecuted instantiation: absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<std::__1::basic_ostream<char, std::__1::char_traits<char> >, (void*)0>(std::__1::basic_ostream<char, std::__1::char_traits<char> >*) Unexecuted instantiation: absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<absl::str_format_internal::FILERawSink, (void*)0>(absl::str_format_internal::FILERawSink*) Unexecuted instantiation: absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<absl::str_format_internal::BufferRawSink, (void*)0>(absl::str_format_internal::BufferRawSink*) |
47 | | |
48 | 4.96k | void Write(string_view s) { write_(sink_, s); } |
49 | | |
50 | | template <typename T> |
51 | 0 | static FormatRawSinkImpl Extract(T s) { |
52 | 0 | return s.sink_; |
53 | 0 | } |
54 | | |
55 | | private: |
56 | | template <typename T> |
57 | 4.96k | static void Flush(void* r, string_view s) { |
58 | 4.96k | str_format_internal::InvokeFlush(static_cast<T*>(r), s); |
59 | 4.96k | } void absl::str_format_internal::FormatRawSinkImpl::Flush<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(void*, absl::string_view) Line | Count | Source | 57 | 4.96k | static void Flush(void* r, string_view s) { | 58 | 4.96k | str_format_internal::InvokeFlush(static_cast<T*>(r), s); | 59 | 4.96k | } |
Unexecuted instantiation: void absl::str_format_internal::FormatRawSinkImpl::Flush<std::__1::basic_ostream<char, std::__1::char_traits<char> > >(void*, absl::string_view) Unexecuted instantiation: void absl::str_format_internal::FormatRawSinkImpl::Flush<absl::str_format_internal::FILERawSink>(void*, absl::string_view) Unexecuted instantiation: void absl::str_format_internal::FormatRawSinkImpl::Flush<absl::str_format_internal::BufferRawSink>(void*, absl::string_view) |
60 | | |
61 | | void* sink_; |
62 | | void (*write_)(void*, string_view); |
63 | | }; |
64 | | |
65 | | // An abstraction to which conversions write their string data. |
66 | | class FormatSinkImpl { |
67 | | public: |
68 | 4.96k | explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {} |
69 | | |
70 | 4.96k | ~FormatSinkImpl() { Flush(); } |
71 | | |
72 | 4.96k | void Flush() { |
73 | 4.96k | raw_.Write(string_view(buf_, static_cast<size_t>(pos_ - buf_))); |
74 | 4.96k | pos_ = buf_; |
75 | 4.96k | } |
76 | | |
77 | 4.48k | void Append(size_t n, char c) { |
78 | 4.48k | if (n == 0) return; |
79 | 722 | size_ += n; |
80 | 722 | auto raw_append = [&](size_t count) { |
81 | 722 | memset(pos_, c, count); |
82 | 722 | pos_ += count; |
83 | 722 | }; |
84 | 722 | while (n > Avail()) { |
85 | 0 | n -= Avail(); |
86 | 0 | if (Avail() > 0) { |
87 | 0 | raw_append(Avail()); |
88 | 0 | } |
89 | 0 | Flush(); |
90 | 0 | } |
91 | 722 | raw_append(n); |
92 | 722 | } |
93 | | |
94 | 9.92k | void Append(string_view v) { |
95 | 9.92k | size_t n = v.size(); |
96 | 9.92k | if (n == 0) return; |
97 | 4.96k | size_ += n; |
98 | 4.96k | if (n >= Avail()) { |
99 | 0 | Flush(); |
100 | 0 | raw_.Write(v); |
101 | 0 | return; |
102 | 0 | } |
103 | 4.96k | memcpy(pos_, v.data(), n); |
104 | 4.96k | pos_ += n; |
105 | 4.96k | } |
106 | | |
107 | 0 | size_t size() const { return size_; } |
108 | | |
109 | | // Put 'v' to 'sink' with specified width, precision, and left flag. |
110 | | bool PutPaddedString(string_view v, int width, int precision, bool left); |
111 | | |
112 | | template <typename T> |
113 | | T Wrap() { |
114 | | return T(this); |
115 | | } |
116 | | |
117 | | template <typename T> |
118 | | static FormatSinkImpl* Extract(T* s) { |
119 | | return s->sink_; |
120 | | } |
121 | | |
122 | | private: |
123 | 5.68k | size_t Avail() const { |
124 | 5.68k | return static_cast<size_t>(buf_ + sizeof(buf_) - pos_); |
125 | 5.68k | } |
126 | | |
127 | | FormatRawSinkImpl raw_; |
128 | | size_t size_ = 0; |
129 | | char* pos_ = buf_; |
130 | | char buf_[1024]; |
131 | | }; |
132 | | |
133 | | enum class Flags : uint8_t { |
134 | | kBasic = 0, |
135 | | kLeft = 1 << 0, |
136 | | kShowPos = 1 << 1, |
137 | | kSignCol = 1 << 2, |
138 | | kAlt = 1 << 3, |
139 | | kZero = 1 << 4, |
140 | | // This is not a real flag. It just exists to turn off kBasic when no other |
141 | | // flags are set. This is for when width/precision are specified, or a length |
142 | | // modifier affects the behavior ("%lc"). |
143 | | kNonBasic = 1 << 5, |
144 | | }; |
145 | | |
146 | 0 | constexpr Flags operator|(Flags a, Flags b) { |
147 | 0 | return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b)); |
148 | 0 | } |
149 | | |
150 | 11.7k | constexpr bool FlagsContains(Flags haystack, Flags needle) { |
151 | 11.7k | return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) == |
152 | 11.7k | static_cast<uint8_t>(needle); |
153 | 11.7k | } |
154 | | |
155 | | std::string FlagsToString(Flags v); |
156 | | |
157 | 0 | inline std::ostream& operator<<(std::ostream& os, Flags v) { |
158 | 0 | return os << FlagsToString(v); |
159 | 0 | } |
160 | | |
161 | | // clang-format off |
162 | | #define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \ |
163 | | /* text */ \ |
164 | 0 | X_VAL(c) X_SEP X_VAL(s) X_SEP \ |
165 | 0 | /* ints */ \ |
166 | 0 | X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \ |
167 | 0 | X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \ |
168 | 0 | /* floats */ \ |
169 | 0 | X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \ |
170 | 1.22k | X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \ |
171 | 0 | /* misc */ \ |
172 | 0 | X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v) |
173 | | // clang-format on |
174 | | |
175 | | // This type should not be referenced, it exists only to provide labels |
176 | | // internally that match the values declared in FormatConversionChar in |
177 | | // str_format.h. This is meant to allow internal libraries to use the same |
178 | | // declared interface type as the public interface |
179 | | // (absl::StrFormatConversionChar) while keeping the definition in a public |
180 | | // header. |
181 | | // Internal libraries should use the form |
182 | | // `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for |
183 | | // comparisons. Use in switch statements is not recommended due to a bug in how |
184 | | // gcc 4.9 -Wswitch handles declared but undefined enums. |
185 | | struct FormatConversionCharInternal { |
186 | | FormatConversionCharInternal() = delete; |
187 | | |
188 | | private: |
189 | | // clang-format off |
190 | | enum class Enum : uint8_t { |
191 | | c, s, // text |
192 | | d, i, o, u, x, X, // int |
193 | | f, F, e, E, g, G, a, A, // float |
194 | | n, p, v, // misc |
195 | | kNone |
196 | | }; |
197 | | // clang-format on |
198 | | public: |
199 | | #define ABSL_INTERNAL_X_VAL(id) \ |
200 | | static constexpr FormatConversionChar id = \ |
201 | | static_cast<FormatConversionChar>(Enum::id); |
202 | | ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, ) |
203 | | #undef ABSL_INTERNAL_X_VAL |
204 | | static constexpr FormatConversionChar kNone = |
205 | | static_cast<FormatConversionChar>(Enum::kNone); |
206 | | }; |
207 | | // clang-format on |
208 | | |
209 | 0 | inline FormatConversionChar FormatConversionCharFromChar(char c) { |
210 | 0 | switch (c) { |
211 | 0 | #define ABSL_INTERNAL_X_VAL(id) \ |
212 | 0 | case #id[0]: \ |
213 | 0 | return FormatConversionCharInternal::id; |
214 | 0 | ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, ) |
215 | 0 | #undef ABSL_INTERNAL_X_VAL |
216 | 0 | } |
217 | 0 | return FormatConversionCharInternal::kNone; |
218 | 0 | } |
219 | | |
220 | 1.21k | inline bool FormatConversionCharIsUpper(FormatConversionChar c) { |
221 | 1.21k | if (c == FormatConversionCharInternal::X || |
222 | 1.21k | c == FormatConversionCharInternal::F || |
223 | 1.21k | c == FormatConversionCharInternal::E || |
224 | 1.21k | c == FormatConversionCharInternal::G || |
225 | 1.21k | c == FormatConversionCharInternal::A) { |
226 | 0 | return true; |
227 | 1.21k | } else { |
228 | 1.21k | return false; |
229 | 1.21k | } |
230 | 1.21k | } |
231 | | |
232 | 2.48k | inline bool FormatConversionCharIsFloat(FormatConversionChar c) { |
233 | 2.48k | if (c == FormatConversionCharInternal::a || |
234 | 2.48k | c == FormatConversionCharInternal::e || |
235 | 2.48k | c == FormatConversionCharInternal::f || |
236 | 2.48k | c == FormatConversionCharInternal::g || |
237 | 2.48k | c == FormatConversionCharInternal::A || |
238 | 2.48k | c == FormatConversionCharInternal::E || |
239 | 2.48k | c == FormatConversionCharInternal::F || |
240 | 2.48k | c == FormatConversionCharInternal::G) { |
241 | 2.48k | return true; |
242 | 2.48k | } else { |
243 | 0 | return false; |
244 | 0 | } |
245 | 2.48k | } |
246 | | |
247 | 1.22k | inline char FormatConversionCharToChar(FormatConversionChar c) { |
248 | 1.22k | if (c == FormatConversionCharInternal::kNone) { |
249 | 0 | return '\0'; |
250 | |
|
251 | 0 | #define ABSL_INTERNAL_X_VAL(e) \ |
252 | 15.9k | } else if (c == FormatConversionCharInternal::e) { \ |
253 | 1.22k | return #e[0]; |
254 | 0 | #define ABSL_INTERNAL_X_SEP |
255 | 1.22k | ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, |
256 | 0 | ABSL_INTERNAL_X_SEP) |
257 | 0 | } else { |
258 | 0 | return '\0'; |
259 | 0 | } |
260 | | |
261 | 1.22k | #undef ABSL_INTERNAL_X_VAL |
262 | 1.22k | #undef ABSL_INTERNAL_X_SEP |
263 | 1.22k | } |
264 | | |
265 | | // The associated char. |
266 | 0 | inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) { |
267 | 0 | char c = FormatConversionCharToChar(v); |
268 | 0 | if (!c) c = '?'; |
269 | 0 | return os << c; |
270 | 0 | } |
271 | | |
272 | | struct FormatConversionSpecImplFriend; |
273 | | |
274 | | class FormatConversionSpecImpl { |
275 | | public: |
276 | | // Width and precision are not specified, no flags are set. |
277 | 2.48k | bool is_basic() const { return flags_ == Flags::kBasic; } |
278 | 1.25k | bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); } |
279 | 910 | bool has_show_pos_flag() const { |
280 | 910 | return FlagsContains(flags_, Flags::kShowPos); |
281 | 910 | } |
282 | 910 | bool has_sign_col_flag() const { |
283 | 910 | return FlagsContains(flags_, Flags::kSignCol); |
284 | 910 | } |
285 | 1.25k | bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); } |
286 | 1.25k | bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); } |
287 | | |
288 | 0 | LengthMod length_mod() const { return length_mod_; } |
289 | | |
290 | 23.5k | FormatConversionChar conversion_char() const { |
291 | | // Keep this field first in the struct . It generates better code when |
292 | | // accessing it when ConversionSpec is passed by value in registers. |
293 | 23.5k | static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, ""); |
294 | 23.5k | return conv_; |
295 | 23.5k | } |
296 | | |
297 | 0 | void set_conversion_char(FormatConversionChar c) { conv_ = c; } |
298 | | |
299 | | // Returns the specified width. If width is unspecfied, it returns a negative |
300 | | // value. |
301 | 2.48k | int width() const { return width_; } |
302 | | // Returns the specified precision. If precision is unspecfied, it returns a |
303 | | // negative value. |
304 | 3.70k | int precision() const { return precision_; } |
305 | | |
306 | | template <typename T> |
307 | | T Wrap() { |
308 | | return T(*this); |
309 | | } |
310 | | |
311 | | private: |
312 | | friend struct str_format_internal::FormatConversionSpecImplFriend; |
313 | | FormatConversionChar conv_ = FormatConversionCharInternal::kNone; |
314 | | Flags flags_; |
315 | | LengthMod length_mod_ = LengthMod::none; |
316 | | int width_; |
317 | | int precision_; |
318 | | }; |
319 | | |
320 | | struct FormatConversionSpecImplFriend final { |
321 | 4.96k | static void SetFlags(Flags f, FormatConversionSpecImpl* conv) { |
322 | 4.96k | conv->flags_ = f; |
323 | 4.96k | } |
324 | 0 | static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) { |
325 | 0 | conv->length_mod_ = l; |
326 | 0 | } |
327 | | static void SetConversionChar(FormatConversionChar c, |
328 | 4.96k | FormatConversionSpecImpl* conv) { |
329 | 4.96k | conv->conv_ = c; |
330 | 4.96k | } |
331 | 4.96k | static void SetWidth(int w, FormatConversionSpecImpl* conv) { |
332 | 4.96k | conv->width_ = w; |
333 | 4.96k | } |
334 | 4.96k | static void SetPrecision(int p, FormatConversionSpecImpl* conv) { |
335 | 4.96k | conv->precision_ = p; |
336 | 4.96k | } |
337 | 1.22k | static std::string FlagsToString(const FormatConversionSpecImpl& spec) { |
338 | 1.22k | return str_format_internal::FlagsToString(spec.flags_); |
339 | 1.22k | } |
340 | | }; |
341 | | |
342 | | // Type safe OR operator. |
343 | | // We need this for two reasons: |
344 | | // 1. operator| on enums makes them decay to integers and the result is an |
345 | | // integer. We need the result to stay as an enum. |
346 | | // 2. We use "enum class" which would not work even if we accepted the decay. |
347 | | constexpr FormatConversionCharSet FormatConversionCharSetUnion( |
348 | 0 | FormatConversionCharSet a) { |
349 | 0 | return a; |
350 | 0 | } |
351 | | |
352 | | template <typename... CharSet> |
353 | | constexpr FormatConversionCharSet FormatConversionCharSetUnion( |
354 | 0 | FormatConversionCharSet a, CharSet... rest) { |
355 | 0 | return static_cast<FormatConversionCharSet>( |
356 | 0 | static_cast<uint64_t>(a) | |
357 | 0 | static_cast<uint64_t>(FormatConversionCharSetUnion(rest...))); |
358 | 0 | } Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet) Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet) Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet) Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet) Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet) Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet) Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet) |
359 | | |
360 | 4.96k | constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) { |
361 | 4.96k | return uint64_t{1} << (1 + static_cast<uint8_t>(c)); |
362 | 4.96k | } |
363 | | |
364 | 0 | constexpr uint64_t FormatConversionCharToConvInt(char conv) { |
365 | 0 | return |
366 | 0 | #define ABSL_INTERNAL_CHAR_SET_CASE(c) \ |
367 | 0 | conv == #c[0] \ |
368 | 0 | ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \ |
369 | 0 | : |
370 | 0 | ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, ) |
371 | 0 | #undef ABSL_INTERNAL_CHAR_SET_CASE |
372 | 0 | conv == '*' |
373 | 0 | ? 1 |
374 | 0 | : 0; |
375 | 0 | } |
376 | | |
377 | 0 | constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) { |
378 | 0 | return static_cast<FormatConversionCharSet>( |
379 | 0 | FormatConversionCharToConvInt(conv)); |
380 | 0 | } |
381 | | |
382 | | struct FormatConversionCharSetInternal { |
383 | | #define ABSL_INTERNAL_CHAR_SET_CASE(c) \ |
384 | | static constexpr FormatConversionCharSet c = \ |
385 | | FormatConversionCharToConvValue(#c[0]); |
386 | | ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, ) |
387 | | #undef ABSL_INTERNAL_CHAR_SET_CASE |
388 | | |
389 | | // Used for width/precision '*' specification. |
390 | | static constexpr FormatConversionCharSet kStar = |
391 | | FormatConversionCharToConvValue('*'); |
392 | | |
393 | | static constexpr FormatConversionCharSet kIntegral = |
394 | | FormatConversionCharSetUnion(d, i, u, o, x, X); |
395 | | static constexpr FormatConversionCharSet kFloating = |
396 | | FormatConversionCharSetUnion(a, e, f, g, A, E, F, G); |
397 | | static constexpr FormatConversionCharSet kNumeric = |
398 | | FormatConversionCharSetUnion(kIntegral, kFloating); |
399 | | static constexpr FormatConversionCharSet kPointer = p; |
400 | | }; |
401 | | |
402 | | // Type safe OR operator. |
403 | | // We need this for two reasons: |
404 | | // 1. operator| on enums makes them decay to integers and the result is an |
405 | | // integer. We need the result to stay as an enum. |
406 | | // 2. We use "enum class" which would not work even if we accepted the decay. |
407 | | constexpr FormatConversionCharSet operator|(FormatConversionCharSet a, |
408 | 0 | FormatConversionCharSet b) { |
409 | 0 | return FormatConversionCharSetUnion(a, b); |
410 | 0 | } |
411 | | |
412 | | // Overloaded conversion functions to support absl::ParsedFormat. |
413 | | // Get a conversion with a single character in it. |
414 | 0 | constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) { |
415 | 0 | return static_cast<FormatConversionCharSet>( |
416 | 0 | FormatConversionCharToConvValue(c)); |
417 | 0 | } |
418 | | |
419 | | // Get a conversion with a single character in it. |
420 | | constexpr FormatConversionCharSet ToFormatConversionCharSet( |
421 | 0 | FormatConversionCharSet c) { |
422 | 0 | return c; |
423 | 0 | } |
424 | | |
425 | | template <typename T> |
426 | | void ToFormatConversionCharSet(T) = delete; |
427 | | |
428 | | // Checks whether `c` exists in `set`. |
429 | 0 | constexpr bool Contains(FormatConversionCharSet set, char c) { |
430 | 0 | return (static_cast<uint64_t>(set) & |
431 | 0 | static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0; |
432 | 0 | } |
433 | | |
434 | | // Checks whether all the characters in `c` are contained in `set` |
435 | | constexpr bool Contains(FormatConversionCharSet set, |
436 | 0 | FormatConversionCharSet c) { |
437 | 0 | return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) == |
438 | 0 | static_cast<uint64_t>(c); |
439 | 0 | } |
440 | | |
441 | | // Checks whether all the characters in `c` are contained in `set` |
442 | 4.96k | constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) { |
443 | 4.96k | return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0; |
444 | 4.96k | } |
445 | | |
446 | | // Return capacity - used, clipped to a minimum of 0. |
447 | 0 | inline size_t Excess(size_t used, size_t capacity) { |
448 | 0 | return used < capacity ? capacity - used : 0; |
449 | 0 | } |
450 | | |
451 | | } // namespace str_format_internal |
452 | | |
453 | | ABSL_NAMESPACE_END |
454 | | } // namespace absl |
455 | | |
456 | | #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ |