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