1 /*
2 * Copyright 2012-present Facebook, Inc.
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 * http://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
17 #ifndef FOLLY_FORMAT_H_
18 #error This file may only be included from Format.h.
19 #endif
20
21 #include <array>
22 #include <cinttypes>
23 #include <deque>
24 #include <map>
25 #include <unordered_map>
26 #include <vector>
27
28 #include <folly/Exception.h>
29 #include <folly/FormatTraits.h>
30 #include <folly/MapUtil.h>
31 #include <folly/Traits.h>
32 #include <folly/lang/Exception.h>
33 #include <folly/portability/Windows.h>
34
35 // Ignore -Wformat-nonliteral warnings within this file
36 FOLLY_PUSH_WARNING
37 FOLLY_GNU_DISABLE_WARNING("-Wformat-nonliteral")
38
39 namespace folly {
40
41 namespace detail {
42
43 // Updates the end of the buffer after the comma separators have been added.
44 void insertThousandsGroupingUnsafe(char* start_buffer, char** end_buffer);
45
46 extern const std::array<std::array<char, 2>, 256> formatHexUpper;
47 extern const std::array<std::array<char, 2>, 256> formatHexLower;
48 extern const std::array<std::array<char, 3>, 512> formatOctal;
49 extern const std::array<std::array<char, 8>, 256> formatBinary;
50
51 const size_t kMaxHexLength = 2 * sizeof(uintmax_t);
52 const size_t kMaxOctalLength = 3 * sizeof(uintmax_t);
53 const size_t kMaxBinaryLength = 8 * sizeof(uintmax_t);
54
55 /**
56 * Convert an unsigned to hex, using repr (which maps from each possible
57 * 2-hex-bytes value to the 2-character representation).
58 *
59 * Just like folly::detail::uintToBuffer in Conv.h, writes at the *end* of
60 * the supplied buffer and returns the offset of the beginning of the string
61 * from the start of the buffer. The formatted string will be in range
62 * [buf+begin, buf+bufLen).
63 */
64 template <class Uint>
uintToHex(char * buffer,size_t bufLen,Uint v,std::array<std::array<char,2>,256> const & repr)65 size_t uintToHex(
66 char* buffer,
67 size_t bufLen,
68 Uint v,
69 std::array<std::array<char, 2>, 256> const& repr) {
70 // 'v >>= 7, v >>= 1' is no more than a work around to get rid of shift size
71 // warning when Uint = uint8_t (it's false as v >= 256 implies sizeof(v) > 1).
72 for (; !less_than<unsigned, 256>(v); v >>= 7, v >>= 1) {
73 auto b = v & 0xff;
74 bufLen -= 2;
75 buffer[bufLen] = repr[b][0];
76 buffer[bufLen + 1] = repr[b][1];
77 }
78 buffer[--bufLen] = repr[v][1];
79 if (v >= 16) {
80 buffer[--bufLen] = repr[v][0];
81 }
82 return bufLen;
83 }
84
85 /**
86 * Convert an unsigned to hex, using lower-case letters for the digits
87 * above 9. See the comments for uintToHex.
88 */
89 template <class Uint>
uintToHexLower(char * buffer,size_t bufLen,Uint v)90 inline size_t uintToHexLower(char* buffer, size_t bufLen, Uint v) {
91 return uintToHex(buffer, bufLen, v, formatHexLower);
92 }
93
94 /**
95 * Convert an unsigned to hex, using upper-case letters for the digits
96 * above 9. See the comments for uintToHex.
97 */
98 template <class Uint>
uintToHexUpper(char * buffer,size_t bufLen,Uint v)99 inline size_t uintToHexUpper(char* buffer, size_t bufLen, Uint v) {
100 return uintToHex(buffer, bufLen, v, formatHexUpper);
101 }
102
103 /**
104 * Convert an unsigned to octal.
105 *
106 * Just like folly::detail::uintToBuffer in Conv.h, writes at the *end* of
107 * the supplied buffer and returns the offset of the beginning of the string
108 * from the start of the buffer. The formatted string will be in range
109 * [buf+begin, buf+bufLen).
110 */
111 template <class Uint>
uintToOctal(char * buffer,size_t bufLen,Uint v)112 size_t uintToOctal(char* buffer, size_t bufLen, Uint v) {
113 auto& repr = formatOctal;
114 // 'v >>= 7, v >>= 2' is no more than a work around to get rid of shift size
115 // warning when Uint = uint8_t (it's false as v >= 512 implies sizeof(v) > 1).
116 for (; !less_than<unsigned, 512>(v); v >>= 7, v >>= 2) {
117 auto b = v & 0x1ff;
118 bufLen -= 3;
119 buffer[bufLen] = repr[b][0];
120 buffer[bufLen + 1] = repr[b][1];
121 buffer[bufLen + 2] = repr[b][2];
122 }
123 buffer[--bufLen] = repr[v][2];
124 if (v >= 8) {
125 buffer[--bufLen] = repr[v][1];
126 }
127 if (v >= 64) {
128 buffer[--bufLen] = repr[v][0];
129 }
130 return bufLen;
131 }
132
133 /**
134 * Convert an unsigned to binary.
135 *
136 * Just like folly::detail::uintToBuffer in Conv.h, writes at the *end* of
137 * the supplied buffer and returns the offset of the beginning of the string
138 * from the start of the buffer. The formatted string will be in range
139 * [buf+begin, buf+bufLen).
140 */
141 template <class Uint>
uintToBinary(char * buffer,size_t bufLen,Uint v)142 size_t uintToBinary(char* buffer, size_t bufLen, Uint v) {
143 auto& repr = formatBinary;
144 if (v == 0) {
145 buffer[--bufLen] = '0';
146 return bufLen;
147 }
148 for (; v; v >>= 7, v >>= 1) {
149 auto b = v & 0xff;
150 bufLen -= 8;
151 memcpy(buffer + bufLen, &(repr[b][0]), 8);
152 }
153 while (buffer[bufLen] == '0') {
154 ++bufLen;
155 }
156 return bufLen;
157 }
158
159 } // namespace detail
160
161 template <class Derived, bool containerMode, class... Args>
BaseFormatter(StringPiece str,Args &&...args)162 BaseFormatter<Derived, containerMode, Args...>::BaseFormatter(
163 StringPiece str,
164 Args&&... args)
165 : str_(str), values_(std::forward<Args>(args)...) {}
166
167 template <class Derived, bool containerMode, class... Args>
168 template <class Output>
operator()169 void BaseFormatter<Derived, containerMode, Args...>::operator()(
170 Output& out) const {
171 // Copy raw string (without format specifiers) to output;
172 // not as simple as we'd like, as we still need to translate "}}" to "}"
173 // and throw if we see any lone "}"
174 auto outputString = [&out](StringPiece s) {
175 auto p = s.begin();
176 auto end = s.end();
177 while (p != end) {
178 auto q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
179 if (!q) {
180 out(StringPiece(p, end));
181 break;
182 }
183 ++q;
184 out(StringPiece(p, q));
185 p = q;
186
187 if (p == end || *p != '}') {
188 throw_exception<BadFormatArg>(
189 "folly::format: single '}' in format string");
190 }
191 ++p;
192 }
193 };
194
195 auto p = str_.begin();
196 auto end = str_.end();
197
198 int nextArg = 0;
199 bool hasDefaultArgIndex = false;
200 bool hasExplicitArgIndex = false;
201 while (p != end) {
202 auto q = static_cast<const char*>(memchr(p, '{', size_t(end - p)));
203 if (!q) {
204 outputString(StringPiece(p, end));
205 break;
206 }
207 outputString(StringPiece(p, q));
208 p = q + 1;
209
210 if (p == end) {
211 throw_exception<BadFormatArg>(
212 "folly::format: '}' at end of format string");
213 }
214
215 // "{{" -> "{"
216 if (*p == '{') {
217 out(StringPiece(p, 1));
218 ++p;
219 continue;
220 }
221
222 // Format string
223 q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
224 if (q == nullptr) {
225 throw_exception<BadFormatArg>("folly::format: missing ending '}'");
226 }
227 FormatArg arg(StringPiece(p, q));
228 p = q + 1;
229
230 int argIndex = 0;
231 auto piece = arg.splitKey<true>(); // empty key component is okay
232 if (containerMode) { // static
233 arg.enforce(
234 arg.width != FormatArg::kDynamicWidth,
235 "dynamic field width not supported in vformat()");
236 if (piece.empty()) {
237 arg.setNextIntKey(nextArg++);
238 hasDefaultArgIndex = true;
239 } else {
240 arg.setNextKey(piece);
241 hasExplicitArgIndex = true;
242 }
243 } else {
244 if (piece.empty()) {
245 if (arg.width == FormatArg::kDynamicWidth) {
246 arg.enforce(
247 arg.widthIndex == FormatArg::kNoIndex,
248 "cannot provide width arg index without value arg index");
249 int sizeArg = nextArg++;
250 arg.width = asDerived().getSizeArg(size_t(sizeArg), arg);
251 }
252
253 argIndex = nextArg++;
254 hasDefaultArgIndex = true;
255 } else {
256 if (arg.width == FormatArg::kDynamicWidth) {
257 arg.enforce(
258 arg.widthIndex != FormatArg::kNoIndex,
259 "cannot provide value arg index without width arg index");
260 arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg);
261 }
262
263 try {
264 argIndex = to<int>(piece);
265 } catch (const std::out_of_range&) {
266 arg.error("argument index must be integer");
267 }
268 arg.enforce(argIndex >= 0, "argument index must be non-negative");
269 hasExplicitArgIndex = true;
270 }
271 }
272
273 if (hasDefaultArgIndex && hasExplicitArgIndex) {
274 throw_exception<BadFormatArg>(
275 "folly::format: may not have both default and explicit arg indexes");
276 }
277
278 asDerived().doFormat(size_t(argIndex), arg, out);
279 }
280 }
281
282 template <class Derived, bool containerMode, class... Args>
writeTo(FILE * fp,const BaseFormatter<Derived,containerMode,Args...> & formatter)283 void writeTo(
284 FILE* fp,
285 const BaseFormatter<Derived, containerMode, Args...>& formatter) {
286 auto writer = [fp](StringPiece sp) {
287 size_t n = fwrite(sp.data(), 1, sp.size(), fp);
288 if (n < sp.size()) {
289 throwSystemError("Formatter writeTo", "fwrite failed");
290 }
291 };
292 formatter(writer);
293 }
294
295 namespace format_value {
296
297 template <class FormatCallback>
formatString(StringPiece val,FormatArg & arg,FormatCallback & cb)298 void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) {
299 if (arg.width != FormatArg::kDefaultWidth && arg.width < 0) {
300 throw_exception<BadFormatArg>("folly::format: invalid width");
301 }
302 if (arg.precision != FormatArg::kDefaultPrecision && arg.precision < 0) {
303 throw_exception<BadFormatArg>("folly::format: invalid precision");
304 }
305
306 if (arg.precision != FormatArg::kDefaultPrecision &&
307 val.size() > static_cast<size_t>(arg.precision)) {
308 val.reset(val.data(), static_cast<size_t>(arg.precision));
309 }
310
311 constexpr int padBufSize = 128;
312 char padBuf[padBufSize];
313
314 // Output padding, no more than padBufSize at once
315 auto pad = [&padBuf, &cb, padBufSize](int chars) {
316 while (chars) {
317 int n = std::min(chars, padBufSize);
318 cb(StringPiece(padBuf, size_t(n)));
319 chars -= n;
320 }
321 };
322
323 int padRemaining = 0;
324 if (arg.width != FormatArg::kDefaultWidth &&
325 val.size() < static_cast<size_t>(arg.width)) {
326 char fill = arg.fill == FormatArg::kDefaultFill ? ' ' : arg.fill;
327 int padChars = static_cast<int>(arg.width - val.size());
328 memset(padBuf, fill, size_t(std::min(padBufSize, padChars)));
329
330 switch (arg.align) {
331 case FormatArg::Align::DEFAULT:
332 case FormatArg::Align::LEFT:
333 padRemaining = padChars;
334 break;
335 case FormatArg::Align::CENTER:
336 pad(padChars / 2);
337 padRemaining = padChars - padChars / 2;
338 break;
339 case FormatArg::Align::RIGHT:
340 case FormatArg::Align::PAD_AFTER_SIGN:
341 pad(padChars);
342 break;
343 default:
344 abort();
345 break;
346 }
347 }
348
349 cb(val);
350
351 if (padRemaining) {
352 pad(padRemaining);
353 }
354 }
355
356 template <class FormatCallback>
formatNumber(StringPiece val,int prefixLen,FormatArg & arg,FormatCallback & cb)357 void formatNumber(
358 StringPiece val,
359 int prefixLen,
360 FormatArg& arg,
361 FormatCallback& cb) {
362 // precision means something different for numbers
363 arg.precision = FormatArg::kDefaultPrecision;
364 if (arg.align == FormatArg::Align::DEFAULT) {
365 arg.align = FormatArg::Align::RIGHT;
366 } else if (prefixLen && arg.align == FormatArg::Align::PAD_AFTER_SIGN) {
367 // Split off the prefix, then do any padding if necessary
368 cb(val.subpiece(0, size_t(prefixLen)));
369 val.advance(size_t(prefixLen));
370 arg.width = std::max(arg.width - prefixLen, 0);
371 }
372 format_value::formatString(val, arg, cb);
373 }
374
375 template <
376 class FormatCallback,
377 class Derived,
378 bool containerMode,
379 class... Args>
formatFormatter(const BaseFormatter<Derived,containerMode,Args...> & formatter,FormatArg & arg,FormatCallback & cb)380 void formatFormatter(
381 const BaseFormatter<Derived, containerMode, Args...>& formatter,
382 FormatArg& arg,
383 FormatCallback& cb) {
384 if (arg.width == FormatArg::kDefaultWidth &&
385 arg.precision == FormatArg::kDefaultPrecision) {
386 // nothing to do
387 formatter(cb);
388 } else if (
389 arg.align != FormatArg::Align::LEFT &&
390 arg.align != FormatArg::Align::DEFAULT) {
391 // We can only avoid creating a temporary string if we align left,
392 // as we'd need to know the size beforehand otherwise
393 format_value::formatString(formatter.fbstr(), arg, cb);
394 } else {
395 auto fn = [&arg, &cb](StringPiece sp) mutable {
396 int sz = static_cast<int>(sp.size());
397 if (arg.precision != FormatArg::kDefaultPrecision) {
398 sz = std::min(arg.precision, sz);
399 sp.reset(sp.data(), size_t(sz));
400 arg.precision -= sz;
401 }
402 if (!sp.empty()) {
403 cb(sp);
404 if (arg.width != FormatArg::kDefaultWidth) {
405 arg.width = std::max(arg.width - sz, 0);
406 }
407 }
408 };
409 formatter(fn);
410 if (arg.width != FormatArg::kDefaultWidth && arg.width != 0) {
411 // Rely on formatString to do appropriate padding
412 format_value::formatString(StringPiece(), arg, cb);
413 }
414 }
415 }
416
417 } // namespace format_value
418
419 // Definitions for default FormatValue classes
420
421 // Integral types (except bool)
422 template <class T>
423 class FormatValue<
424 T,
425 typename std::enable_if<
426 std::is_integral<T>::value && !std::is_same<T, bool>::value>::type> {
427 public:
FormatValue(T val)428 explicit FormatValue(T val) : val_(val) {}
429
getValue()430 T getValue() const {
431 return val_;
432 }
433
434 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)435 void format(FormatArg& arg, FormatCallback& cb) const {
436 arg.validate(FormatArg::Type::INTEGER);
437 doFormat(arg, cb);
438 }
439
440 template <class FormatCallback>
doFormat(FormatArg & arg,FormatCallback & cb)441 void doFormat(FormatArg& arg, FormatCallback& cb) const {
442 char presentation = arg.presentation;
443 if (presentation == FormatArg::kDefaultPresentation) {
444 presentation = std::is_same<T, char>::value ? 'c' : 'd';
445 }
446
447 // Do all work as unsigned, we'll add the prefix ('0' or '0x' if necessary)
448 // and sign ourselves.
449 typedef typename std::make_unsigned<T>::type UT;
450 UT uval;
451 char sign;
452 if (std::is_signed<T>::value) {
453 if (folly::is_negative(val_)) {
454 uval = UT(-static_cast<UT>(val_));
455 sign = '-';
456 } else {
457 uval = static_cast<UT>(val_);
458 switch (arg.sign) {
459 case FormatArg::Sign::PLUS_OR_MINUS:
460 sign = '+';
461 break;
462 case FormatArg::Sign::SPACE_OR_MINUS:
463 sign = ' ';
464 break;
465 default:
466 sign = '\0';
467 break;
468 }
469 }
470 } else {
471 uval = static_cast<UT>(val_);
472 sign = '\0';
473
474 arg.enforce(
475 arg.sign == FormatArg::Sign::DEFAULT,
476 "sign specifications not allowed for unsigned values");
477 }
478
479 // max of:
480 // #x: 0x prefix + 16 bytes = 18 bytes
481 // #o: 0 prefix + 22 bytes = 23 bytes
482 // #b: 0b prefix + 64 bytes = 65 bytes
483 // ,d: 26 bytes (including thousands separators!)
484 // + nul terminator
485 // + 3 for sign and prefix shenanigans (see below)
486 constexpr size_t valBufSize = 69;
487 char valBuf[valBufSize];
488 char* valBufBegin = nullptr;
489 char* valBufEnd = nullptr;
490
491 int prefixLen = 0;
492 switch (presentation) {
493 case 'n': {
494 arg.enforce(
495 !arg.basePrefix,
496 "base prefix not allowed with '",
497 presentation,
498 "' specifier");
499
500 arg.enforce(
501 !arg.thousandsSeparator,
502 "cannot use ',' with the '",
503 presentation,
504 "' specifier");
505
506 valBufBegin = valBuf + 3; // room for sign and base prefix
507 #if defined(__ANDROID__)
508 int len = snprintf(
509 valBufBegin,
510 (valBuf + valBufSize) - valBufBegin,
511 "%" PRIuMAX,
512 static_cast<uintmax_t>(uval));
513 #else
514 int len = snprintf(
515 valBufBegin,
516 size_t((valBuf + valBufSize) - valBufBegin),
517 "%ju",
518 static_cast<uintmax_t>(uval));
519 #endif
520 // valBufSize should always be big enough, so this should never
521 // happen.
522 assert(len < valBuf + valBufSize - valBufBegin);
523 valBufEnd = valBufBegin + len;
524 break;
525 }
526 case 'd':
527 arg.enforce(
528 !arg.basePrefix,
529 "base prefix not allowed with '",
530 presentation,
531 "' specifier");
532 valBufBegin = valBuf + 3; // room for sign and base prefix
533
534 // Use uintToBuffer, faster than sprintf
535 valBufEnd = valBufBegin + uint64ToBufferUnsafe(uval, valBufBegin);
536 if (arg.thousandsSeparator) {
537 detail::insertThousandsGroupingUnsafe(valBufBegin, &valBufEnd);
538 }
539 break;
540 case 'c':
541 arg.enforce(
542 !arg.basePrefix,
543 "base prefix not allowed with '",
544 presentation,
545 "' specifier");
546 arg.enforce(
547 !arg.thousandsSeparator,
548 "thousands separator (',') not allowed with '",
549 presentation,
550 "' specifier");
551 valBufBegin = valBuf + 3;
552 *valBufBegin = static_cast<char>(uval);
553 valBufEnd = valBufBegin + 1;
554 break;
555 case 'o':
556 case 'O':
557 arg.enforce(
558 !arg.thousandsSeparator,
559 "thousands separator (',') not allowed with '",
560 presentation,
561 "' specifier");
562 valBufEnd = valBuf + valBufSize - 1;
563 valBufBegin =
564 valBuf + detail::uintToOctal(valBuf, valBufSize - 1, uval);
565 if (arg.basePrefix) {
566 *--valBufBegin = '0';
567 prefixLen = 1;
568 }
569 break;
570 case 'x':
571 arg.enforce(
572 !arg.thousandsSeparator,
573 "thousands separator (',') not allowed with '",
574 presentation,
575 "' specifier");
576 valBufEnd = valBuf + valBufSize - 1;
577 valBufBegin =
578 valBuf + detail::uintToHexLower(valBuf, valBufSize - 1, uval);
579 if (arg.basePrefix) {
580 *--valBufBegin = 'x';
581 *--valBufBegin = '0';
582 prefixLen = 2;
583 }
584 break;
585 case 'X':
586 arg.enforce(
587 !arg.thousandsSeparator,
588 "thousands separator (',') not allowed with '",
589 presentation,
590 "' specifier");
591 valBufEnd = valBuf + valBufSize - 1;
592 valBufBegin =
593 valBuf + detail::uintToHexUpper(valBuf, valBufSize - 1, uval);
594 if (arg.basePrefix) {
595 *--valBufBegin = 'X';
596 *--valBufBegin = '0';
597 prefixLen = 2;
598 }
599 break;
600 case 'b':
601 case 'B':
602 arg.enforce(
603 !arg.thousandsSeparator,
604 "thousands separator (',') not allowed with '",
605 presentation,
606 "' specifier");
607 valBufEnd = valBuf + valBufSize - 1;
608 valBufBegin =
609 valBuf + detail::uintToBinary(valBuf, valBufSize - 1, uval);
610 if (arg.basePrefix) {
611 *--valBufBegin = presentation; // 0b or 0B
612 *--valBufBegin = '0';
613 prefixLen = 2;
614 }
615 break;
616 default:
617 arg.error("invalid specifier '", presentation, "'");
618 }
619
620 if (sign) {
621 *--valBufBegin = sign;
622 ++prefixLen;
623 }
624
625 format_value::formatNumber(
626 StringPiece(valBufBegin, valBufEnd), prefixLen, arg, cb);
627 }
628
629 private:
630 T val_;
631 };
632
633 // Bool
634 template <>
635 class FormatValue<bool> {
636 public:
FormatValue(bool val)637 explicit FormatValue(bool val) : val_(val) {}
638
639 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)640 void format(FormatArg& arg, FormatCallback& cb) const {
641 if (arg.presentation == FormatArg::kDefaultPresentation) {
642 arg.validate(FormatArg::Type::OTHER);
643 format_value::formatString(val_ ? "true" : "false", arg, cb);
644 } else { // number
645 FormatValue<int>(val_).format(arg, cb);
646 }
647 }
648
649 private:
650 bool val_;
651 };
652
653 // double
654 template <>
655 class FormatValue<double> {
656 public:
FormatValue(double val)657 explicit FormatValue(double val) : val_(val) {}
658
659 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)660 void format(FormatArg& arg, FormatCallback& cb) const {
661 fbstring piece;
662 int prefixLen;
663 formatHelper(piece, prefixLen, arg);
664 format_value::formatNumber(piece, prefixLen, arg, cb);
665 }
666
667 private:
668 void formatHelper(fbstring& piece, int& prefixLen, FormatArg& arg) const;
669
670 double val_;
671 };
672
673 // float (defer to double)
674 template <>
675 class FormatValue<float> {
676 public:
FormatValue(float val)677 explicit FormatValue(float val) : val_(val) {}
678
679 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)680 void format(FormatArg& arg, FormatCallback& cb) const {
681 FormatValue<double>(val_).format(arg, cb);
682 }
683
684 private:
685 float val_;
686 };
687
688 // String-y types (implicitly convertible to StringPiece, except char*)
689 template <class T>
690 class FormatValue<
691 T,
692 typename std::enable_if<
693 (!std::is_pointer<T>::value ||
694 !std::is_same<
695 char,
696 typename std::decay<typename std::remove_pointer<T>::type>::type>::
697 value) &&
698 std::is_convertible<T, StringPiece>::value>::type> {
699 public:
FormatValue(StringPiece val)700 explicit FormatValue(StringPiece val) : val_(val) {}
701
702 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)703 void format(FormatArg& arg, FormatCallback& cb) const {
704 if (arg.keyEmpty()) {
705 arg.validate(FormatArg::Type::OTHER);
706 arg.enforce(
707 arg.presentation == FormatArg::kDefaultPresentation ||
708 arg.presentation == 's',
709 "invalid specifier '",
710 arg.presentation,
711 "'");
712 format_value::formatString(val_, arg, cb);
713 } else {
714 FormatValue<char>(val_.at(size_t(arg.splitIntKey()))).format(arg, cb);
715 }
716 }
717
718 private:
719 StringPiece val_;
720 };
721
722 // Null
723 template <>
724 class FormatValue<std::nullptr_t> {
725 public:
FormatValue(std::nullptr_t)726 explicit FormatValue(std::nullptr_t) {}
727
728 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)729 void format(FormatArg& arg, FormatCallback& cb) const {
730 arg.validate(FormatArg::Type::OTHER);
731 arg.enforce(
732 arg.presentation == FormatArg::kDefaultPresentation,
733 "invalid specifier '",
734 arg.presentation,
735 "'");
736 format_value::formatString("(null)", arg, cb);
737 }
738 };
739
740 // Partial specialization of FormatValue for char*
741 template <class T>
742 class FormatValue<
743 T*,
744 typename std::enable_if<
745 std::is_same<char, typename std::decay<T>::type>::value>::type> {
746 public:
FormatValue(T * val)747 explicit FormatValue(T* val) : val_(val) {}
748
749 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)750 void format(FormatArg& arg, FormatCallback& cb) const {
751 if (arg.keyEmpty()) {
752 if (!val_) {
753 FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
754 } else {
755 FormatValue<StringPiece>(val_).format(arg, cb);
756 }
757 } else {
758 FormatValue<typename std::decay<T>::type>(val_[arg.splitIntKey()])
759 .format(arg, cb);
760 }
761 }
762
763 private:
764 T* val_;
765 };
766
767 // Partial specialization of FormatValue for void*
768 template <class T>
769 class FormatValue<
770 T*,
771 typename std::enable_if<
772 std::is_same<void, typename std::decay<T>::type>::value>::type> {
773 public:
FormatValue(T * val)774 explicit FormatValue(T* val) : val_(val) {}
775
776 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)777 void format(FormatArg& arg, FormatCallback& cb) const {
778 if (!val_) {
779 FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
780 } else {
781 // Print as a pointer, in hex.
782 arg.validate(FormatArg::Type::OTHER);
783 arg.enforce(
784 arg.presentation == FormatArg::kDefaultPresentation,
785 "invalid specifier '",
786 arg.presentation,
787 "'");
788 arg.basePrefix = true;
789 arg.presentation = 'x';
790 if (arg.align == FormatArg::Align::DEFAULT) {
791 arg.align = FormatArg::Align::LEFT;
792 }
793 FormatValue<uintptr_t>(reinterpret_cast<uintptr_t>(val_))
794 .doFormat(arg, cb);
795 }
796 }
797
798 private:
799 T* val_;
800 };
801
802 template <class T, class = void>
803 class TryFormatValue {
804 public:
805 template <class FormatCallback>
806 static void
formatOrFail(T &,FormatArg & arg,FormatCallback &)807 formatOrFail(T& /* value */, FormatArg& arg, FormatCallback& /* cb */) {
808 arg.error("No formatter available for this type");
809 }
810 };
811
812 template <class T>
813 class TryFormatValue<
814 T,
815 typename std::enable_if<
816 0 < sizeof(FormatValue<typename std::decay<T>::type>)>::type> {
817 public:
818 template <class FormatCallback>
formatOrFail(T & value,FormatArg & arg,FormatCallback & cb)819 static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
820 FormatValue<typename std::decay<T>::type>(value).format(arg, cb);
821 }
822 };
823
824 // Partial specialization of FormatValue for other pointers
825 template <class T>
826 class FormatValue<
827 T*,
828 typename std::enable_if<
829 !std::is_same<char, typename std::decay<T>::type>::value &&
830 !std::is_same<void, typename std::decay<T>::type>::value>::type> {
831 public:
FormatValue(T * val)832 explicit FormatValue(T* val) : val_(val) {}
833
834 template <class FormatCallback>
format(FormatArg & arg,FormatCallback & cb)835 void format(FormatArg& arg, FormatCallback& cb) const {
836 if (arg.keyEmpty()) {
837 FormatValue<void*>((void*)val_).format(arg, cb);
838 } else {
839 TryFormatValue<T>::formatOrFail(val_[arg.splitIntKey()], arg, cb);
840 }
841 }
842
843 private:
844 T* val_;
845 };
846
847 namespace detail {
848
849 // std::array
850 template <class T, size_t N>
851 struct IndexableTraits<std::array<T, N>>
852 : public IndexableTraitsSeq<std::array<T, N>> {};
853
854 // std::vector
855 template <class T, class A>
856 struct IndexableTraits<std::vector<T, A>>
857 : public IndexableTraitsSeq<std::vector<T, A>> {};
858
859 // std::deque
860 template <class T, class A>
861 struct IndexableTraits<std::deque<T, A>>
862 : public IndexableTraitsSeq<std::deque<T, A>> {};
863
864 // std::map with integral keys
865 template <class K, class T, class C, class A>
866 struct IndexableTraits<
867 std::map<K, T, C, A>,
868 typename std::enable_if<std::is_integral<K>::value>::type>
869 : public IndexableTraitsAssoc<std::map<K, T, C, A>> {};
870
871 // std::unordered_map with integral keys
872 template <class K, class T, class H, class E, class A>
873 struct IndexableTraits<
874 std::unordered_map<K, T, H, E, A>,
875 typename std::enable_if<std::is_integral<K>::value>::type>
876 : public IndexableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {};
877
878 } // namespace detail
879
880 // Partial specialization of FormatValue for integer-indexable containers
881 template <class T>
882 class FormatValue<T, typename detail::IndexableTraits<T>::enabled> {
883 public:
884 explicit FormatValue(const T& val) : val_(val) {}
885
886 template <class FormatCallback>
887 void format(FormatArg& arg, FormatCallback& cb) const {
888 FormatValue<typename std::decay<
889 typename detail::IndexableTraits<T>::value_type>::type>(
890 detail::IndexableTraits<T>::at(val_, arg.splitIntKey()))
891 .format(arg, cb);
892 }
893
894 private:
895 const T& val_;
896 };
897
898 template <class Container, class Value>
899 class FormatValue<
900 detail::DefaultValueWrapper<Container, Value>,
901 typename detail::IndexableTraits<Container>::enabled> {
902 public:
903 explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
904 : val_(val) {}
905
906 template <class FormatCallback>
907 void format(FormatArg& arg, FormatCallback& cb) const {
908 FormatValue<typename std::decay<
909 typename detail::IndexableTraits<Container>::value_type>::type>(
910 detail::IndexableTraits<Container>::at(
911 val_.container, arg.splitIntKey(), val_.defaultValue))
912 .format(arg, cb);
913 }
914
915 private:
916 const detail::DefaultValueWrapper<Container, Value>& val_;
917 };
918
919 namespace detail {
920
921 // Define enabled, key_type, convert from StringPiece to the key types
922 // that we support
923 template <class T>
924 struct KeyFromStringPiece;
925
926 // std::string
927 template <>
928 struct KeyFromStringPiece<std::string> : public FormatTraitsBase {
929 typedef std::string key_type;
930 static std::string convert(StringPiece s) {
931 return s.toString();
932 }
933 typedef void enabled;
934 };
935
936 // fbstring
937 template <>
938 struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
939 typedef fbstring key_type;
940 static fbstring convert(StringPiece s) {
941 return s.to<fbstring>();
942 }
943 };
944
945 // StringPiece
946 template <>
947 struct KeyFromStringPiece<StringPiece> : public FormatTraitsBase {
948 typedef StringPiece key_type;
949 static StringPiece convert(StringPiece s) {
950 return s;
951 }
952 };
953
954 // Base class for associative types keyed by strings
955 template <class T>
956 struct KeyableTraitsAssoc : public FormatTraitsBase {
957 typedef typename T::key_type key_type;
958 typedef typename T::value_type::second_type value_type;
959 static const value_type& at(const T& map, StringPiece key) {
960 if (auto ptr = get_ptr(map, KeyFromStringPiece<key_type>::convert(key))) {
961 return *ptr;
962 }
963 throw_exception<FormatKeyNotFoundException>(key);
964 }
965 static const value_type&
966 at(const T& map, StringPiece key, const value_type& dflt) {
967 auto pos = map.find(KeyFromStringPiece<key_type>::convert(key));
968 return pos != map.end() ? pos->second : dflt;
969 }
970 };
971
972 // Define enabled, key_type, value_type, at() for supported string-keyed
973 // types
974 template <class T, class Enabled = void>
975 struct KeyableTraits;
976
977 // std::map with string key
978 template <class K, class T, class C, class A>
979 struct KeyableTraits<
980 std::map<K, T, C, A>,
981 typename KeyFromStringPiece<K>::enabled>
982 : public KeyableTraitsAssoc<std::map<K, T, C, A>> {};
983
984 // std::unordered_map with string key
985 template <class K, class T, class H, class E, class A>
986 struct KeyableTraits<
987 std::unordered_map<K, T, H, E, A>,
988 typename KeyFromStringPiece<K>::enabled>
989 : public KeyableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {};
990
991 } // namespace detail
992
993 // Partial specialization of FormatValue for string-keyed containers
994 template <class T>
995 class FormatValue<T, typename detail::KeyableTraits<T>::enabled> {
996 public:
997 explicit FormatValue(const T& val) : val_(val) {}
998
999 template <class FormatCallback>
1000 void format(FormatArg& arg, FormatCallback& cb) const {
1001 FormatValue<typename std::decay<
1002 typename detail::KeyableTraits<T>::value_type>::type>(
1003 detail::KeyableTraits<T>::at(val_, arg.splitKey()))
1004 .format(arg, cb);
1005 }
1006
1007 private:
1008 const T& val_;
1009 };
1010
1011 template <class Container, class Value>
1012 class FormatValue<
1013 detail::DefaultValueWrapper<Container, Value>,
1014 typename detail::KeyableTraits<Container>::enabled> {
1015 public:
1016 explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
1017 : val_(val) {}
1018
1019 template <class FormatCallback>
1020 void format(FormatArg& arg, FormatCallback& cb) const {
1021 FormatValue<typename std::decay<
1022 typename detail::KeyableTraits<Container>::value_type>::type>(
1023 detail::KeyableTraits<Container>::at(
1024 val_.container, arg.splitKey(), val_.defaultValue))
1025 .format(arg, cb);
1026 }
1027
1028 private:
1029 const detail::DefaultValueWrapper<Container, Value>& val_;
1030 };
1031
1032 // Partial specialization of FormatValue for pairs
1033 template <class A, class B>
1034 class FormatValue<std::pair<A, B>> {
1035 public:
1036 explicit FormatValue(const std::pair<A, B>& val) : val_(val) {}
1037
1038 template <class FormatCallback>
1039 void format(FormatArg& arg, FormatCallback& cb) const {
1040 int key = arg.splitIntKey();
1041 switch (key) {
1042 case 0:
1043 FormatValue<typename std::decay<A>::type>(val_.first).format(arg, cb);
1044 break;
1045 case 1:
1046 FormatValue<typename std::decay<B>::type>(val_.second).format(arg, cb);
1047 break;
1048 default:
1049 arg.error("invalid index for pair");
1050 }
1051 }
1052
1053 private:
1054 const std::pair<A, B>& val_;
1055 };
1056
1057 // Partial specialization of FormatValue for tuples
1058 template <class... Args>
1059 class FormatValue<std::tuple<Args...>> {
1060 typedef std::tuple<Args...> Tuple;
1061
1062 public:
1063 explicit FormatValue(const Tuple& val) : val_(val) {}
1064
1065 template <class FormatCallback>
1066 void format(FormatArg& arg, FormatCallback& cb) const {
1067 int key = arg.splitIntKey();
1068 arg.enforce(key >= 0, "tuple index must be non-negative");
1069 doFormat(size_t(key), arg, cb);
1070 }
1071
1072 private:
1073 static constexpr size_t valueCount = std::tuple_size<Tuple>::value;
1074
1075 template <size_t K, class Callback>
1076 typename std::enable_if<K == valueCount>::type
1077 doFormatFrom(size_t i, FormatArg& arg, Callback& /* cb */) const {
1078 arg.error("tuple index out of range, max=", i);
1079 }
1080
1081 template <size_t K, class Callback>
1082 typename std::enable_if<(K < valueCount)>::type
1083 doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
1084 if (i == K) {
1085 FormatValue<typename std::decay<
1086 typename std::tuple_element<K, Tuple>::type>::type>(std::get<K>(val_))
1087 .format(arg, cb);
1088 } else {
1089 doFormatFrom<K + 1>(i, arg, cb);
1090 }
1091 }
1092
1093 template <class Callback>
1094 void doFormat(size_t i, FormatArg& arg, Callback& cb) const {
1095 return doFormatFrom<0>(i, arg, cb);
1096 }
1097
1098 const Tuple& val_;
1099 };
1100
1101 // Partial specialization of FormatValue for nested Formatters
1102 template <bool containerMode, class... Args, template <bool, class...> class F>
1103 class FormatValue<
1104 F<containerMode, Args...>,
1105 typename std::enable_if<
1106 detail::IsFormatter<F<containerMode, Args...>>::value>::type> {
1107 typedef typename F<containerMode, Args...>::BaseType FormatterValue;
1108
1109 public:
1110 explicit FormatValue(const FormatterValue& f) : f_(f) {}
1111
1112 template <class FormatCallback>
1113 void format(FormatArg& arg, FormatCallback& cb) const {
1114 format_value::formatFormatter(f_, arg, cb);
1115 }
1116
1117 private:
1118 const FormatterValue& f_;
1119 };
1120
1121 /**
1122 * Formatter objects can be appended to strings, and therefore they're
1123 * compatible with folly::toAppend and folly::to.
1124 */
1125 template <class Tgt, class Derived, bool containerMode, class... Args>
1126 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
1127 const BaseFormatter<Derived, containerMode, Args...>& value,
1128 Tgt* result) {
1129 value.appendTo(*result);
1130 }
1131
1132 } // namespace folly
1133
1134 FOLLY_POP_WARNING
1135