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