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