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