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