A few fixes for clang support
[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     bool done = false;
566
567     // 2+: for null terminator and optional sign shenanigans.
568     char buf[2 + std::max({
569         (2 + DoubleToStringConverter::kMaxFixedDigitsBeforePoint +
570          DoubleToStringConverter::kMaxFixedDigitsAfterPoint),
571         (8 + DoubleToStringConverter::kMaxExponentialDigits),
572         (7 + DoubleToStringConverter::kMaxPrecisionDigits)})];
573     StringBuilder builder(buf + 1, sizeof(buf) - 1);
574
575     char plusSign;
576     switch (arg.sign) {
577     case FormatArg::Sign::PLUS_OR_MINUS:
578       plusSign = '+';
579       break;
580     case FormatArg::Sign::SPACE_OR_MINUS:
581       plusSign = ' ';
582       break;
583     default:
584       plusSign = '\0';
585       break;
586     };
587
588     double val = val_;
589     switch (arg.presentation) {
590     case '%':
591       val *= 100;
592     case 'f':
593     case 'F':
594       {
595         if (arg.precision >
596             DoubleToStringConverter::kMaxFixedDigitsAfterPoint) {
597           arg.precision = DoubleToStringConverter::kMaxFixedDigitsAfterPoint;
598         }
599         DoubleToStringConverter conv(
600             DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN,
601             infinitySymbol,
602             nanSymbol,
603             exponentSymbol,
604             -4, arg.precision,
605             0, 0);
606         arg.enforce(conv.ToFixed(val, arg.precision, &builder),
607                     "fixed double conversion failed");
608       }
609       break;
610     case 'e':
611     case 'E':
612       {
613         if (arg.precision > DoubleToStringConverter::kMaxExponentialDigits) {
614           arg.precision = DoubleToStringConverter::kMaxExponentialDigits;
615         }
616
617         DoubleToStringConverter conv(
618             DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN,
619             infinitySymbol,
620             nanSymbol,
621             exponentSymbol,
622             -4, arg.precision,
623             0, 0);
624         CHECK(conv.ToExponential(val, arg.precision, &builder));
625       }
626       break;
627     case 'n':  // should be locale-aware, but isn't
628     case 'g':
629     case 'G':
630       {
631         if (arg.precision < DoubleToStringConverter::kMinPrecisionDigits) {
632           arg.precision = DoubleToStringConverter::kMinPrecisionDigits;
633         } else if (arg.precision >
634                    DoubleToStringConverter::kMaxPrecisionDigits) {
635           arg.precision = DoubleToStringConverter::kMaxPrecisionDigits;
636         }
637         DoubleToStringConverter conv(
638             DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN,
639             infinitySymbol,
640             nanSymbol,
641             exponentSymbol,
642             -4, arg.precision,
643             0, 0);
644         CHECK(conv.ToShortest(val, &builder));
645       }
646       break;
647     default:
648       arg.error("invalid specifier '", arg.presentation, "'");
649     }
650
651     int len = builder.position();
652     builder.Finalize();
653     DCHECK_GT(len, 0);
654
655     // Add '+' or ' ' sign if needed
656     char* p = buf + 1;
657     // anything that's neither negative nor nan
658     int prefixLen = 0;
659     if (plusSign && (*p != '-' && *p != 'n' && *p != 'N')) {
660       *--p = plusSign;
661       ++len;
662       prefixLen = 1;
663     } else if (*p == '-') {
664       prefixLen = 1;
665     }
666
667     format_value::formatNumber(StringPiece(p, len), prefixLen, arg, cb);
668   }
669
670  private:
671   double val_;
672 };
673
674 // float (defer to double)
675 template <>
676 class FormatValue<float> {
677  public:
678   explicit FormatValue(float val) : val_(val) { }
679
680   template <class FormatCallback>
681   void format(FormatArg& arg, FormatCallback& cb) const {
682     FormatValue<double>(val_).format(arg, cb);
683   }
684
685  private:
686   float val_;
687 };
688
689 // Sring-y types (implicitly convertible to StringPiece, except char*)
690 template <class T>
691 class FormatValue<
692   T, typename std::enable_if<
693       (!std::is_pointer<T>::value ||
694        !std::is_same<char, typename std::decay<
695           typename std::remove_pointer<T>::type>::type>::value) &&
696       std::is_convertible<T, StringPiece>::value>::type>
697   {
698  public:
699   explicit FormatValue(StringPiece val) : val_(val) { }
700
701   template <class FormatCallback>
702   void format(FormatArg& arg, FormatCallback& cb) const {
703     if (arg.keyEmpty()) {
704       arg.validate(FormatArg::Type::OTHER);
705       arg.enforce(arg.presentation == FormatArg::kDefaultPresentation ||
706                   arg.presentation == 's',
707                   "invalid specifier '", arg.presentation, "'");
708       format_value::formatString(val_, arg, cb);
709     } else {
710       FormatValue<char>(val_.at(arg.splitIntKey())).format(arg, cb);
711     }
712   }
713
714  private:
715   StringPiece val_;
716 };
717
718 // Null
719 template <>
720 class FormatValue<std::nullptr_t> {
721  public:
722   explicit FormatValue(std::nullptr_t) { }
723
724   template <class FormatCallback>
725   void format(FormatArg& arg, FormatCallback& cb) const {
726     arg.validate(FormatArg::Type::OTHER);
727     arg.enforce(arg.presentation == FormatArg::kDefaultPresentation,
728                 "invalid specifier '", arg.presentation, "'");
729     format_value::formatString("(null)", arg, cb);
730   }
731 };
732
733 // Partial specialization of FormatValue for char*
734 template <class T>
735 class FormatValue<
736   T*,
737   typename std::enable_if<
738       std::is_same<char, typename std::decay<T>::type>::value>::type>
739   {
740  public:
741   explicit FormatValue(T* val) : val_(val) { }
742
743   template <class FormatCallback>
744   void format(FormatArg& arg, FormatCallback& cb) const {
745     if (arg.keyEmpty()) {
746       if (!val_) {
747         FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
748       } else {
749         FormatValue<StringPiece>(val_).format(arg, cb);
750       }
751     } else {
752       FormatValue<typename std::decay<T>::type>(
753           val_[arg.splitIntKey()]).format(arg, cb);
754     }
755   }
756
757  private:
758   T* val_;
759 };
760
761 // Partial specialization of FormatValue for void*
762 template <class T>
763 class FormatValue<
764   T*,
765   typename std::enable_if<
766       std::is_same<void, typename std::decay<T>::type>::value>::type>
767   {
768  public:
769   explicit FormatValue(T* val) : val_(val) { }
770
771   template <class FormatCallback>
772   void format(FormatArg& arg, FormatCallback& cb) const {
773     if (!val_) {
774       FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
775     } else {
776       // Print as a pointer, in hex.
777       arg.validate(FormatArg::Type::OTHER);
778       arg.enforce(arg.presentation == FormatArg::kDefaultPresentation,
779                   "invalid specifier '", arg.presentation, "'");
780       arg.basePrefix = true;
781       arg.presentation = 'x';
782       if (arg.align == FormatArg::Align::DEFAULT) {
783         arg.align = FormatArg::Align::LEFT;
784       }
785       FormatValue<uintptr_t>(
786           reinterpret_cast<uintptr_t>(val_)).doFormat(arg, cb);
787     }
788   }
789
790  private:
791   T* val_;
792 };
793
794 template <class T, class = void>
795 class TryFormatValue {
796  public:
797   template <class FormatCallback>
798   static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
799     arg.error("No formatter available for this type");
800   }
801 };
802
803 template <class T>
804 class TryFormatValue<
805   T,
806   typename std::enable_if<
807       0 < sizeof(FormatValue<typename std::decay<T>::type>)>::type>
808   {
809  public:
810   template <class FormatCallback>
811   static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
812     FormatValue<typename std::decay<T>::type>(value).format(arg, cb);
813   }
814 };
815
816 // Partial specialization of FormatValue for other pointers
817 template <class T>
818 class FormatValue<
819   T*,
820   typename std::enable_if<
821       !std::is_same<char, typename std::decay<T>::type>::value &&
822       !std::is_same<void, typename std::decay<T>::type>::value>::type>
823   {
824  public:
825   explicit FormatValue(T* val) : val_(val) { }
826
827   template <class FormatCallback>
828   void format(FormatArg& arg, FormatCallback& cb) const {
829     if (arg.keyEmpty()) {
830       FormatValue<void*>((void*)val_).format(arg, cb);
831     } else {
832       TryFormatValue<T>::formatOrFail(val_[arg.splitIntKey()], arg, cb);
833     }
834   }
835  private:
836   T* val_;
837 };
838
839 namespace detail {
840
841 // Shortcut, so we don't have to use enable_if everywhere
842 struct FormatTraitsBase {
843   typedef void enabled;
844 };
845
846 // Traits that define enabled, value_type, and at() for anything
847 // indexable with integral keys: pointers, arrays, vectors, and maps
848 // with integral keys
849 template <class T, class Enable=void> struct IndexableTraits;
850
851 // Base class for sequences (vectors, deques)
852 template <class C>
853 struct IndexableTraitsSeq : public FormatTraitsBase {
854   typedef C container_type;
855   typedef typename C::value_type value_type;
856   static const value_type& at(const C& c, int idx) {
857     return c.at(idx);
858   }
859 };
860
861 // Base class for associative types (maps)
862 template <class C>
863 struct IndexableTraitsAssoc : public FormatTraitsBase {
864   typedef typename C::value_type::second_type value_type;
865   static const value_type& at(const C& c, int idx) {
866     return c.at(static_cast<typename C::key_type>(idx));
867   }
868 };
869
870 // std::array
871 template <class T, size_t N>
872 struct IndexableTraits<std::array<T, N>>
873   : public IndexableTraitsSeq<std::array<T, N>> {
874 };
875
876 // std::vector
877 template <class T, class A>
878 struct IndexableTraits<std::vector<T, A>>
879   : public IndexableTraitsSeq<std::vector<T, A>> {
880 };
881
882 // std::deque
883 template <class T, class A>
884 struct IndexableTraits<std::deque<T, A>>
885   : public IndexableTraitsSeq<std::deque<T, A>> {
886 };
887
888 // fbvector
889 template <class T, class A>
890 struct IndexableTraits<fbvector<T, A>>
891   : public IndexableTraitsSeq<fbvector<T, A>> {
892 };
893
894 // small_vector
895 template <class T, size_t M, class A, class B, class C>
896 struct IndexableTraits<small_vector<T, M, A, B, C>>
897   : public IndexableTraitsSeq<small_vector<T, M, A, B, C>> {
898 };
899
900 // std::map with integral keys
901 template <class K, class T, class C, class A>
902 struct IndexableTraits<
903   std::map<K, T, C, A>,
904   typename std::enable_if<std::is_integral<K>::value>::type>
905   : public IndexableTraitsAssoc<std::map<K, T, C, A>> {
906 };
907
908 // std::unordered_map with integral keys
909 template <class K, class T, class H, class E, class A>
910 struct IndexableTraits<
911   std::unordered_map<K, T, H, E, A>,
912   typename std::enable_if<std::is_integral<K>::value>::type>
913   : public IndexableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {
914 };
915
916 }  // namespace detail
917
918 // Partial specialization of FormatValue for integer-indexable containers
919 template <class T>
920 class FormatValue<
921   T,
922   typename detail::IndexableTraits<T>::enabled> {
923  public:
924   explicit FormatValue(const T& val) : val_(val) { }
925
926   template <class FormatCallback>
927   void format(FormatArg& arg, FormatCallback& cb) const {
928     FormatValue<typename std::decay<
929       typename detail::IndexableTraits<T>::value_type>::type>(
930         detail::IndexableTraits<T>::at(
931             val_, arg.splitIntKey())).format(arg, cb);
932   }
933
934  private:
935   const T& val_;
936 };
937
938 namespace detail {
939
940 // Define enabled, key_type, convert from StringPiece to the key types
941 // that we support
942 template <class T> struct KeyFromStringPiece;
943
944 // std::string
945 template <>
946 struct KeyFromStringPiece<std::string> : public FormatTraitsBase {
947   typedef std::string key_type;
948   static std::string convert(StringPiece s) {
949     return s.toString();
950   }
951   typedef void enabled;
952 };
953
954 // fbstring
955 template <>
956 struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
957   typedef fbstring key_type;
958   static fbstring convert(StringPiece s) {
959     return s.toFbstring();
960   }
961 };
962
963 // StringPiece
964 template <>
965 struct KeyFromStringPiece<StringPiece> : public FormatTraitsBase {
966   typedef StringPiece key_type;
967   static StringPiece convert(StringPiece s) {
968     return s;
969   }
970 };
971
972 // Base class for associative types keyed by strings
973 template <class T> struct KeyableTraitsAssoc : public FormatTraitsBase {
974   typedef typename T::key_type key_type;
975   typedef typename T::value_type::second_type value_type;
976   static const value_type& at(const T& map, StringPiece key) {
977     return map.at(KeyFromStringPiece<key_type>::convert(key));
978   }
979 };
980
981 // Define enabled, key_type, value_type, at() for supported string-keyed
982 // types
983 template <class T, class Enabled=void> struct KeyableTraits;
984
985 // std::map with string key
986 template <class K, class T, class C, class A>
987 struct KeyableTraits<
988   std::map<K, T, C, A>,
989   typename KeyFromStringPiece<K>::enabled>
990   : public KeyableTraitsAssoc<std::map<K, T, C, A>> {
991 };
992
993 // std::unordered_map with string key
994 template <class K, class T, class H, class E, class A>
995 struct KeyableTraits<
996   std::unordered_map<K, T, H, E, A>,
997   typename KeyFromStringPiece<K>::enabled>
998   : public KeyableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {
999 };
1000
1001 }  // namespace detail
1002
1003 // Partial specialization of FormatValue for string-keyed containers
1004 template <class T>
1005 class FormatValue<
1006   T,
1007   typename detail::KeyableTraits<T>::enabled> {
1008  public:
1009   explicit FormatValue(const T& val) : val_(val) { }
1010
1011   template <class FormatCallback>
1012   void format(FormatArg& arg, FormatCallback& cb) const {
1013     FormatValue<typename std::decay<
1014       typename detail::KeyableTraits<T>::value_type>::type>(
1015         detail::KeyableTraits<T>::at(
1016             val_, arg.splitKey())).format(arg, cb);
1017   }
1018
1019  private:
1020   const T& val_;
1021 };
1022
1023 // Partial specialization of FormatValue for pairs
1024 template <class A, class B>
1025 class FormatValue<std::pair<A, B>> {
1026  public:
1027   explicit FormatValue(const std::pair<A, B>& val) : val_(val) { }
1028
1029   template <class FormatCallback>
1030   void format(FormatArg& arg, FormatCallback& cb) const {
1031     int key = arg.splitIntKey();
1032     switch (key) {
1033     case 0:
1034       FormatValue<typename std::decay<A>::type>(val_.first).format(arg, cb);
1035       break;
1036     case 1:
1037       FormatValue<typename std::decay<B>::type>(val_.second).format(arg, cb);
1038       break;
1039     default:
1040       arg.error("invalid index for pair");
1041     }
1042   }
1043
1044  private:
1045   const std::pair<A, B>& val_;
1046 };
1047
1048 // Partial specialization of FormatValue for tuples
1049 template <class... Args>
1050 class FormatValue<std::tuple<Args...>> {
1051   typedef std::tuple<Args...> Tuple;
1052  public:
1053   explicit FormatValue(const Tuple& val) : val_(val) { }
1054
1055   template <class FormatCallback>
1056   void format(FormatArg& arg, FormatCallback& cb) const {
1057     int key = arg.splitIntKey();
1058     arg.enforce(key >= 0, "tuple index must be non-negative");
1059     doFormat(key, arg, cb);
1060   }
1061
1062  private:
1063   static constexpr size_t valueCount = std::tuple_size<Tuple>::value;
1064
1065   template <size_t K, class Callback>
1066   typename std::enable_if<K == valueCount>::type
1067   doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
1068     arg.enforce("tuple index out of range, max=", i);
1069   }
1070
1071   template <size_t K, class Callback>
1072   typename std::enable_if<(K < valueCount)>::type
1073   doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
1074     if (i == K) {
1075       FormatValue<typename std::decay<
1076         typename std::tuple_element<K, Tuple>::type>::type>(
1077           std::get<K>(val_)).format(arg, cb);
1078     } else {
1079       doFormatFrom<K+1>(i, arg, cb);
1080     }
1081   }
1082
1083   template <class Callback>
1084   void doFormat(size_t i, FormatArg& arg, Callback& cb) const {
1085     return doFormatFrom<0>(i, arg, cb);
1086   }
1087
1088   const Tuple& val_;
1089 };
1090
1091 // Partial specialization of FormatValue for nested Formatters
1092 template <bool containerMode, class... Args>
1093 class FormatValue<Formatter<containerMode, Args...>, void> {
1094   typedef Formatter<containerMode, Args...> FormatterValue;
1095  public:
1096   explicit FormatValue(const FormatterValue& f) : f_(f) { }
1097
1098   template <class FormatCallback>
1099   void format(FormatArg& arg, FormatCallback& cb) const {
1100     format_value::formatFormatter(f_, arg, cb);
1101   }
1102  private:
1103   const FormatterValue& f_;
1104 };
1105
1106 /**
1107  * Formatter objects can be appended to strings, and therefore they're
1108  * compatible with folly::toAppend and folly::to.
1109  */
1110 template <class Tgt, bool containerMode, class... Args>
1111 typename std::enable_if<
1112    detail::IsSomeString<Tgt>::value>::type
1113 toAppend(const Formatter<containerMode, Args...>& value, Tgt * result) {
1114   value.appendTo(*result);
1115 }
1116
1117 }  // namespace folly