Address clang sign warning in Format-inl.h
[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.width != FormatArg::kDefaultWidth && arg.width < 0) {
310     throw BadFormatArg("folly::format: invalid width");
311   }
312   if (arg.precision != FormatArg::kDefaultPrecision && arg.precision < 0) {
313     throw BadFormatArg("folly::format: invalid precision");
314   }
315
316   if (arg.precision != FormatArg::kDefaultPrecision &&
317       val.size() > arg.precision) {
318     val.reset(val.data(), arg.precision);
319   }
320
321   constexpr int padBufSize = 128;
322   char padBuf[padBufSize];
323
324   // Output padding, no more than padBufSize at once
325   auto pad = [&padBuf, &cb, padBufSize] (int chars) {
326     while (chars) {
327       int n = std::min(chars, padBufSize);
328       cb(StringPiece(padBuf, n));
329       chars -= n;
330     }
331   };
332
333   int padRemaining = 0;
334   if (arg.width != FormatArg::kDefaultWidth && val.size() < arg.width) {
335     char fill = arg.fill == FormatArg::kDefaultFill ? ' ' : arg.fill;
336     int padChars = static_cast<int> (arg.width - val.size());
337     memset(padBuf, fill, std::min(padBufSize, padChars));
338
339     switch (arg.align) {
340     case FormatArg::Align::DEFAULT:
341     case FormatArg::Align::LEFT:
342       padRemaining = padChars;
343       break;
344     case FormatArg::Align::CENTER:
345       pad(padChars / 2);
346       padRemaining = padChars - padChars / 2;
347       break;
348     case FormatArg::Align::RIGHT:
349     case FormatArg::Align::PAD_AFTER_SIGN:
350       pad(padChars);
351       break;
352     default:
353       abort();
354       break;
355     }
356   }
357
358   cb(val);
359
360   if (padRemaining) {
361     pad(padRemaining);
362   }
363 }
364
365 template <class FormatCallback>
366 void formatNumber(StringPiece val, int prefixLen, FormatArg& arg,
367                   FormatCallback& cb) {
368   // precision means something different for numbers
369   arg.precision = FormatArg::kDefaultPrecision;
370   if (arg.align == FormatArg::Align::DEFAULT) {
371     arg.align = FormatArg::Align::RIGHT;
372   } else if (prefixLen && arg.align == FormatArg::Align::PAD_AFTER_SIGN) {
373     // Split off the prefix, then do any padding if necessary
374     cb(val.subpiece(0, prefixLen));
375     val.advance(prefixLen);
376     arg.width = std::max(arg.width - prefixLen, 0);
377   }
378   format_value::formatString(val, arg, cb);
379 }
380
381 template <class FormatCallback,
382           class Derived,
383           bool containerMode,
384           class... Args>
385 void formatFormatter(
386     const BaseFormatter<Derived, containerMode, Args...>& formatter,
387     FormatArg& arg,
388     FormatCallback& cb) {
389   if (arg.width == FormatArg::kDefaultWidth &&
390       arg.precision == FormatArg::kDefaultPrecision) {
391     // nothing to do
392     formatter(cb);
393   } else if (arg.align != FormatArg::Align::LEFT &&
394              arg.align != FormatArg::Align::DEFAULT) {
395     // We can only avoid creating a temporary string if we align left,
396     // as we'd need to know the size beforehand otherwise
397     format_value::formatString(formatter.fbstr(), arg, cb);
398   } else {
399     auto fn = [&arg, &cb] (StringPiece sp) mutable {
400       int sz = static_cast<int>(sp.size());
401       if (arg.precision != FormatArg::kDefaultPrecision) {
402         sz = std::min(arg.precision, sz);
403         sp.reset(sp.data(), sz);
404         arg.precision -= sz;
405       }
406       if (!sp.empty()) {
407         cb(sp);
408         if (arg.width != FormatArg::kDefaultWidth) {
409           arg.width = std::max(arg.width - sz, 0);
410         }
411       }
412     };
413     formatter(fn);
414     if (arg.width != FormatArg::kDefaultWidth && arg.width != 0) {
415       // Rely on formatString to do appropriate padding
416       format_value::formatString(StringPiece(), arg, cb);
417     }
418   }
419 }
420
421 }  // namespace format_value
422
423 // Definitions for default FormatValue classes
424
425 // Integral types (except bool)
426 template <class T>
427 class FormatValue<
428   T, typename std::enable_if<
429     std::is_integral<T>::value &&
430     !std::is_same<T, bool>::value>::type>
431   {
432  public:
433   explicit FormatValue(T val) : val_(val) { }
434   template <class FormatCallback>
435   void format(FormatArg& arg, FormatCallback& cb) const {
436     arg.validate(FormatArg::Type::INTEGER);
437     doFormat(arg, cb);
438   }
439
440   template <class FormatCallback>
441   void doFormat(FormatArg& arg, FormatCallback& cb) const {
442     char presentation = arg.presentation;
443     if (presentation == FormatArg::kDefaultPresentation) {
444       presentation = std::is_same<T, char>::value ? 'c' : 'd';
445     }
446
447     // Do all work as unsigned, we'll add the prefix ('0' or '0x' if necessary)
448     // and sign ourselves.
449     typedef typename std::make_unsigned<T>::type UT;
450     UT uval;
451     char sign;
452     if (std::is_signed<T>::value) {
453       if (folly::is_negative(val_)) {
454         uval = static_cast<UT>(-val_);
455         sign = '-';
456       } else {
457         uval = static_cast<UT>(val_);
458         switch (arg.sign) {
459         case FormatArg::Sign::PLUS_OR_MINUS:
460           sign = '+';
461           break;
462         case FormatArg::Sign::SPACE_OR_MINUS:
463           sign = ' ';
464           break;
465         default:
466           sign = '\0';
467           break;
468         }
469       }
470     } else {
471       uval = val_;
472       sign = '\0';
473
474       arg.enforce(arg.sign == FormatArg::Sign::DEFAULT,
475                   "sign specifications not allowed for unsigned values");
476     }
477
478     // max of:
479     // #x: 0x prefix + 16 bytes = 18 bytes
480     // #o: 0 prefix + 22 bytes = 23 bytes
481     // #b: 0b prefix + 64 bytes = 65 bytes
482     // ,d: 26 bytes (including thousands separators!)
483     // + nul terminator
484     // + 3 for sign and prefix shenanigans (see below)
485     constexpr size_t valBufSize = 69;
486     char valBuf[valBufSize];
487     char* valBufBegin = nullptr;
488     char* valBufEnd = nullptr;
489
490     // Defer to sprintf
491     auto useSprintf = [&] (const char* format) mutable {
492       valBufBegin = valBuf + 3;  // room for sign and base prefix
493       valBufEnd = valBufBegin + sprintf(valBufBegin, format,
494                                         static_cast<uintmax_t>(uval));
495     };
496
497     int prefixLen = 0;
498
499     switch (presentation) {
500     case 'n':  // TODO(tudorb): locale awareness?
501     case 'd':
502       arg.enforce(!arg.basePrefix,
503                   "base prefix not allowed with '", presentation,
504                   "' specifier");
505       if (arg.thousandsSeparator) {
506         useSprintf("%'ju");
507       } else {
508         // Use uintToBuffer, faster than sprintf
509         valBufBegin = valBuf + 3;
510         valBufEnd = valBufBegin + uint64ToBufferUnsafe(uval, valBufBegin);
511       }
512       break;
513     case 'c':
514       arg.enforce(!arg.basePrefix,
515                   "base prefix not allowed with '", presentation,
516                   "' specifier");
517       arg.enforce(!arg.thousandsSeparator,
518                   "thousands separator (',') not allowed with '",
519                   presentation, "' specifier");
520       valBufBegin = valBuf + 3;
521       *valBufBegin = static_cast<char>(uval);
522       valBufEnd = valBufBegin + 1;
523       break;
524     case 'o':
525     case 'O':
526       arg.enforce(!arg.thousandsSeparator,
527                   "thousands separator (',') not allowed with '",
528                   presentation, "' specifier");
529       valBufEnd = valBuf + valBufSize - 1;
530       valBufBegin = valBuf + detail::uintToOctal(valBuf, valBufSize - 1, uval);
531       if (arg.basePrefix) {
532         *--valBufBegin = '0';
533         prefixLen = 1;
534       }
535       break;
536     case 'x':
537       arg.enforce(!arg.thousandsSeparator,
538                   "thousands separator (',') not allowed with '",
539                   presentation, "' specifier");
540       valBufEnd = valBuf + valBufSize - 1;
541       valBufBegin = valBuf + detail::uintToHexLower(valBuf, valBufSize - 1,
542                                                     uval);
543       if (arg.basePrefix) {
544         *--valBufBegin = 'x';
545         *--valBufBegin = '0';
546         prefixLen = 2;
547       }
548       break;
549     case 'X':
550       arg.enforce(!arg.thousandsSeparator,
551                   "thousands separator (',') not allowed with '",
552                   presentation, "' specifier");
553       valBufEnd = valBuf + valBufSize - 1;
554       valBufBegin = valBuf + detail::uintToHexUpper(valBuf, valBufSize - 1,
555                                                     uval);
556       if (arg.basePrefix) {
557         *--valBufBegin = 'X';
558         *--valBufBegin = '0';
559         prefixLen = 2;
560       }
561       break;
562     case 'b':
563     case 'B':
564       arg.enforce(!arg.thousandsSeparator,
565                   "thousands separator (',') not allowed with '",
566                   presentation, "' specifier");
567       valBufEnd = valBuf + valBufSize - 1;
568       valBufBegin = valBuf + detail::uintToBinary(valBuf, valBufSize - 1,
569                                                   uval);
570       if (arg.basePrefix) {
571         *--valBufBegin = presentation;  // 0b or 0B
572         *--valBufBegin = '0';
573         prefixLen = 2;
574       }
575       break;
576     default:
577       arg.error("invalid specifier '", presentation, "'");
578     }
579
580     if (sign) {
581       *--valBufBegin = sign;
582       ++prefixLen;
583     }
584
585     format_value::formatNumber(StringPiece(valBufBegin, valBufEnd), prefixLen,
586                                arg, cb);
587   }
588
589  private:
590   T val_;
591 };
592
593 // Bool
594 template <>
595 class FormatValue<bool> {
596  public:
597   explicit FormatValue(bool val) : val_(val) { }
598
599   template <class FormatCallback>
600   void format(FormatArg& arg, FormatCallback& cb) const {
601     if (arg.presentation == FormatArg::kDefaultPresentation) {
602       arg.validate(FormatArg::Type::OTHER);
603       format_value::formatString(val_ ? "true" : "false", arg, cb);
604     } else {  // number
605       FormatValue<int>(val_).format(arg, cb);
606     }
607   }
608
609  private:
610   bool val_;
611 };
612
613 // double
614 template <>
615 class FormatValue<double> {
616  public:
617   explicit FormatValue(double val) : val_(val) { }
618
619   template <class FormatCallback>
620   void format(FormatArg& arg, FormatCallback& cb) const {
621     using ::double_conversion::DoubleToStringConverter;
622     using ::double_conversion::StringBuilder;
623
624     arg.validate(FormatArg::Type::FLOAT);
625
626     if (arg.presentation == FormatArg::kDefaultPresentation) {
627       arg.presentation = 'g';
628     }
629
630     const char* infinitySymbol = isupper(arg.presentation) ? "INF" : "inf";
631     const char* nanSymbol = isupper(arg.presentation) ? "NAN" : "nan";
632     char exponentSymbol = isupper(arg.presentation) ? 'E' : 'e';
633
634     if (arg.precision == FormatArg::kDefaultPrecision) {
635       arg.precision = 6;
636     }
637
638     // 2+: for null terminator and optional sign shenanigans.
639     char buf[2 + std::max({
640         (2 + DoubleToStringConverter::kMaxFixedDigitsBeforePoint +
641          DoubleToStringConverter::kMaxFixedDigitsAfterPoint),
642         (8 + DoubleToStringConverter::kMaxExponentialDigits),
643         (7 + DoubleToStringConverter::kMaxPrecisionDigits)})];
644     StringBuilder builder(buf + 1, static_cast<int> (sizeof(buf) - 1));
645
646     char plusSign;
647     switch (arg.sign) {
648     case FormatArg::Sign::PLUS_OR_MINUS:
649       plusSign = '+';
650       break;
651     case FormatArg::Sign::SPACE_OR_MINUS:
652       plusSign = ' ';
653       break;
654     default:
655       plusSign = '\0';
656       break;
657     };
658
659     auto flags =
660         DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
661         (arg.trailingDot ? DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT
662                          : 0);
663
664     double val = val_;
665     switch (arg.presentation) {
666     case '%':
667       val *= 100;
668     case 'f':
669     case 'F':
670       {
671         if (arg.precision >
672             DoubleToStringConverter::kMaxFixedDigitsAfterPoint) {
673           arg.precision = DoubleToStringConverter::kMaxFixedDigitsAfterPoint;
674         }
675         DoubleToStringConverter conv(flags,
676                                      infinitySymbol,
677                                      nanSymbol,
678                                      exponentSymbol,
679                                      -4,
680                                      arg.precision,
681                                      0,
682                                      0);
683         arg.enforce(conv.ToFixed(val, arg.precision, &builder),
684                     "fixed double conversion failed");
685       }
686       break;
687     case 'e':
688     case 'E':
689       {
690         if (arg.precision > DoubleToStringConverter::kMaxExponentialDigits) {
691           arg.precision = DoubleToStringConverter::kMaxExponentialDigits;
692         }
693
694         DoubleToStringConverter conv(flags,
695                                      infinitySymbol,
696                                      nanSymbol,
697                                      exponentSymbol,
698                                      -4,
699                                      arg.precision,
700                                      0,
701                                      0);
702         arg.enforce(conv.ToExponential(val, arg.precision, &builder));
703       }
704       break;
705     case 'n':  // should be locale-aware, but isn't
706     case 'g':
707     case 'G':
708       {
709         if (arg.precision < DoubleToStringConverter::kMinPrecisionDigits) {
710           arg.precision = DoubleToStringConverter::kMinPrecisionDigits;
711         } else if (arg.precision >
712                    DoubleToStringConverter::kMaxPrecisionDigits) {
713           arg.precision = DoubleToStringConverter::kMaxPrecisionDigits;
714         }
715         DoubleToStringConverter conv(flags,
716                                      infinitySymbol,
717                                      nanSymbol,
718                                      exponentSymbol,
719                                      -4,
720                                      arg.precision,
721                                      0,
722                                      0);
723         arg.enforce(conv.ToShortest(val, &builder));
724       }
725       break;
726     default:
727       arg.error("invalid specifier '", arg.presentation, "'");
728     }
729
730     int len = builder.position();
731     builder.Finalize();
732     DCHECK_GT(len, 0);
733
734     // Add '+' or ' ' sign if needed
735     char* p = buf + 1;
736     // anything that's neither negative nor nan
737     int prefixLen = 0;
738     if (plusSign && (*p != '-' && *p != 'n' && *p != 'N')) {
739       *--p = plusSign;
740       ++len;
741       prefixLen = 1;
742     } else if (*p == '-') {
743       prefixLen = 1;
744     }
745
746     format_value::formatNumber(StringPiece(p, len), prefixLen, arg, cb);
747   }
748
749  private:
750   double val_;
751 };
752
753 // float (defer to double)
754 template <>
755 class FormatValue<float> {
756  public:
757   explicit FormatValue(float val) : val_(val) { }
758
759   template <class FormatCallback>
760   void format(FormatArg& arg, FormatCallback& cb) const {
761     FormatValue<double>(val_).format(arg, cb);
762   }
763
764  private:
765   float val_;
766 };
767
768 // Sring-y types (implicitly convertible to StringPiece, except char*)
769 template <class T>
770 class FormatValue<
771   T, typename std::enable_if<
772       (!std::is_pointer<T>::value ||
773        !std::is_same<char, typename std::decay<
774           typename std::remove_pointer<T>::type>::type>::value) &&
775       std::is_convertible<T, StringPiece>::value>::type>
776   {
777  public:
778   explicit FormatValue(StringPiece val) : val_(val) { }
779
780   template <class FormatCallback>
781   void format(FormatArg& arg, FormatCallback& cb) const {
782     if (arg.keyEmpty()) {
783       arg.validate(FormatArg::Type::OTHER);
784       arg.enforce(arg.presentation == FormatArg::kDefaultPresentation ||
785                   arg.presentation == 's',
786                   "invalid specifier '", arg.presentation, "'");
787       format_value::formatString(val_, arg, cb);
788     } else {
789       FormatValue<char>(val_.at(arg.splitIntKey())).format(arg, cb);
790     }
791   }
792
793  private:
794   StringPiece val_;
795 };
796
797 // Null
798 template <>
799 class FormatValue<std::nullptr_t> {
800  public:
801   explicit FormatValue(std::nullptr_t) { }
802
803   template <class FormatCallback>
804   void format(FormatArg& arg, FormatCallback& cb) const {
805     arg.validate(FormatArg::Type::OTHER);
806     arg.enforce(arg.presentation == FormatArg::kDefaultPresentation,
807                 "invalid specifier '", arg.presentation, "'");
808     format_value::formatString("(null)", arg, cb);
809   }
810 };
811
812 // Partial specialization of FormatValue for char*
813 template <class T>
814 class FormatValue<
815   T*,
816   typename std::enable_if<
817       std::is_same<char, typename std::decay<T>::type>::value>::type>
818   {
819  public:
820   explicit FormatValue(T* val) : val_(val) { }
821
822   template <class FormatCallback>
823   void format(FormatArg& arg, FormatCallback& cb) const {
824     if (arg.keyEmpty()) {
825       if (!val_) {
826         FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
827       } else {
828         FormatValue<StringPiece>(val_).format(arg, cb);
829       }
830     } else {
831       FormatValue<typename std::decay<T>::type>(
832           val_[arg.splitIntKey()]).format(arg, cb);
833     }
834   }
835
836  private:
837   T* val_;
838 };
839
840 // Partial specialization of FormatValue for void*
841 template <class T>
842 class FormatValue<
843   T*,
844   typename std::enable_if<
845       std::is_same<void, typename std::decay<T>::type>::value>::type>
846   {
847  public:
848   explicit FormatValue(T* val) : val_(val) { }
849
850   template <class FormatCallback>
851   void format(FormatArg& arg, FormatCallback& cb) const {
852     if (!val_) {
853       FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
854     } else {
855       // Print as a pointer, in hex.
856       arg.validate(FormatArg::Type::OTHER);
857       arg.enforce(arg.presentation == FormatArg::kDefaultPresentation,
858                   "invalid specifier '", arg.presentation, "'");
859       arg.basePrefix = true;
860       arg.presentation = 'x';
861       if (arg.align == FormatArg::Align::DEFAULT) {
862         arg.align = FormatArg::Align::LEFT;
863       }
864       FormatValue<uintptr_t>(
865           reinterpret_cast<uintptr_t>(val_)).doFormat(arg, cb);
866     }
867   }
868
869  private:
870   T* val_;
871 };
872
873 template <class T, class = void>
874 class TryFormatValue {
875  public:
876   template <class FormatCallback>
877   static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
878     arg.error("No formatter available for this type");
879   }
880 };
881
882 template <class T>
883 class TryFormatValue<
884   T,
885   typename std::enable_if<
886       0 < sizeof(FormatValue<typename std::decay<T>::type>)>::type>
887   {
888  public:
889   template <class FormatCallback>
890   static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
891     FormatValue<typename std::decay<T>::type>(value).format(arg, cb);
892   }
893 };
894
895 // Partial specialization of FormatValue for other pointers
896 template <class T>
897 class FormatValue<
898   T*,
899   typename std::enable_if<
900       !std::is_same<char, typename std::decay<T>::type>::value &&
901       !std::is_same<void, typename std::decay<T>::type>::value>::type>
902   {
903  public:
904   explicit FormatValue(T* val) : val_(val) { }
905
906   template <class FormatCallback>
907   void format(FormatArg& arg, FormatCallback& cb) const {
908     if (arg.keyEmpty()) {
909       FormatValue<void*>((void*)val_).format(arg, cb);
910     } else {
911       TryFormatValue<T>::formatOrFail(val_[arg.splitIntKey()], arg, cb);
912     }
913   }
914  private:
915   T* val_;
916 };
917
918 namespace detail {
919
920 // Shortcut, so we don't have to use enable_if everywhere
921 struct FormatTraitsBase {
922   typedef void enabled;
923 };
924
925 // Traits that define enabled, value_type, and at() for anything
926 // indexable with integral keys: pointers, arrays, vectors, and maps
927 // with integral keys
928 template <class T, class Enable=void> struct IndexableTraits;
929
930 // Base class for sequences (vectors, deques)
931 template <class C>
932 struct IndexableTraitsSeq : public FormatTraitsBase {
933   typedef C container_type;
934   typedef typename C::value_type value_type;
935   static const value_type& at(const C& c, int idx) {
936     return c.at(idx);
937   }
938
939   static const value_type& at(const C& c, int idx,
940                               const value_type& dflt) {
941     return (idx >= 0 && idx < c.size()) ? c.at(idx) : dflt;
942   }
943 };
944
945 // Base class for associative types (maps)
946 template <class C>
947 struct IndexableTraitsAssoc : public FormatTraitsBase {
948   typedef typename C::value_type::second_type value_type;
949   static const value_type& at(const C& c, int idx) {
950     return c.at(static_cast<typename C::key_type>(idx));
951   }
952   static const value_type& at(const C& c, int idx,
953                               const value_type& dflt) {
954     auto pos = c.find(static_cast<typename C::key_type>(idx));
955     return pos != c.end() ? pos->second : dflt;
956   }
957 };
958
959 // std::array
960 template <class T, size_t N>
961 struct IndexableTraits<std::array<T, N>>
962   : public IndexableTraitsSeq<std::array<T, N>> {
963 };
964
965 // std::vector
966 template <class T, class A>
967 struct IndexableTraits<std::vector<T, A>>
968   : public IndexableTraitsSeq<std::vector<T, A>> {
969 };
970
971 // std::deque
972 template <class T, class A>
973 struct IndexableTraits<std::deque<T, A>>
974   : public IndexableTraitsSeq<std::deque<T, A>> {
975 };
976
977 // fbvector
978 template <class T, class A>
979 struct IndexableTraits<fbvector<T, A>>
980   : public IndexableTraitsSeq<fbvector<T, A>> {
981 };
982
983 // small_vector
984 template <class T, size_t M, class A, class B, class C>
985 struct IndexableTraits<small_vector<T, M, A, B, C>>
986   : public IndexableTraitsSeq<small_vector<T, M, A, B, C>> {
987 };
988
989 // std::map with integral keys
990 template <class K, class T, class C, class A>
991 struct IndexableTraits<
992   std::map<K, T, C, A>,
993   typename std::enable_if<std::is_integral<K>::value>::type>
994   : public IndexableTraitsAssoc<std::map<K, T, C, A>> {
995 };
996
997 // std::unordered_map with integral keys
998 template <class K, class T, class H, class E, class A>
999 struct IndexableTraits<
1000   std::unordered_map<K, T, H, E, A>,
1001   typename std::enable_if<std::is_integral<K>::value>::type>
1002   : public IndexableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {
1003 };
1004
1005 }  // namespace detail
1006
1007 // Partial specialization of FormatValue for integer-indexable containers
1008 template <class T>
1009 class FormatValue<
1010   T,
1011   typename detail::IndexableTraits<T>::enabled> {
1012  public:
1013   explicit FormatValue(const T& val) : val_(val) { }
1014
1015   template <class FormatCallback>
1016   void format(FormatArg& arg, FormatCallback& cb) const {
1017     FormatValue<typename std::decay<
1018       typename detail::IndexableTraits<T>::value_type>::type>(
1019         detail::IndexableTraits<T>::at(
1020             val_, arg.splitIntKey())).format(arg, cb);
1021   }
1022
1023  private:
1024   const T& val_;
1025 };
1026
1027 template <class Container, class Value>
1028 class FormatValue<
1029   detail::DefaultValueWrapper<Container, Value>,
1030   typename detail::IndexableTraits<Container>::enabled> {
1031  public:
1032   explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
1033     : val_(val) { }
1034
1035   template <class FormatCallback>
1036   void format(FormatArg& arg, FormatCallback& cb) const {
1037     FormatValue<typename std::decay<
1038       typename detail::IndexableTraits<Container>::value_type>::type>(
1039           detail::IndexableTraits<Container>::at(
1040               val_.container,
1041               arg.splitIntKey(),
1042               val_.defaultValue)).format(arg, cb);
1043   }
1044
1045  private:
1046   const detail::DefaultValueWrapper<Container, Value>& val_;
1047 };
1048
1049 namespace detail {
1050
1051 // Define enabled, key_type, convert from StringPiece to the key types
1052 // that we support
1053 template <class T> struct KeyFromStringPiece;
1054
1055 // std::string
1056 template <>
1057 struct KeyFromStringPiece<std::string> : public FormatTraitsBase {
1058   typedef std::string key_type;
1059   static std::string convert(StringPiece s) {
1060     return s.toString();
1061   }
1062   typedef void enabled;
1063 };
1064
1065 // fbstring
1066 template <>
1067 struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
1068   typedef fbstring key_type;
1069   static fbstring convert(StringPiece s) {
1070     return s.toFbstring();
1071   }
1072 };
1073
1074 // StringPiece
1075 template <>
1076 struct KeyFromStringPiece<StringPiece> : public FormatTraitsBase {
1077   typedef StringPiece key_type;
1078   static StringPiece convert(StringPiece s) {
1079     return s;
1080   }
1081 };
1082
1083 // Base class for associative types keyed by strings
1084 template <class T> struct KeyableTraitsAssoc : public FormatTraitsBase {
1085   typedef typename T::key_type key_type;
1086   typedef typename T::value_type::second_type value_type;
1087   static const value_type& at(const T& map, StringPiece key) {
1088     return map.at(KeyFromStringPiece<key_type>::convert(key));
1089   }
1090   static const value_type& at(const T& map, StringPiece key,
1091                               const value_type& dflt) {
1092     auto pos = map.find(KeyFromStringPiece<key_type>::convert(key));
1093     return pos != map.end() ? pos->second : dflt;
1094   }
1095 };
1096
1097 // Define enabled, key_type, value_type, at() for supported string-keyed
1098 // types
1099 template <class T, class Enabled=void> struct KeyableTraits;
1100
1101 // std::map with string key
1102 template <class K, class T, class C, class A>
1103 struct KeyableTraits<
1104   std::map<K, T, C, A>,
1105   typename KeyFromStringPiece<K>::enabled>
1106   : public KeyableTraitsAssoc<std::map<K, T, C, A>> {
1107 };
1108
1109 // std::unordered_map with string key
1110 template <class K, class T, class H, class E, class A>
1111 struct KeyableTraits<
1112   std::unordered_map<K, T, H, E, A>,
1113   typename KeyFromStringPiece<K>::enabled>
1114   : public KeyableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {
1115 };
1116
1117 }  // namespace detail
1118
1119 // Partial specialization of FormatValue for string-keyed containers
1120 template <class T>
1121 class FormatValue<
1122   T,
1123   typename detail::KeyableTraits<T>::enabled> {
1124  public:
1125   explicit FormatValue(const T& val) : val_(val) { }
1126
1127   template <class FormatCallback>
1128   void format(FormatArg& arg, FormatCallback& cb) const {
1129     FormatValue<typename std::decay<
1130       typename detail::KeyableTraits<T>::value_type>::type>(
1131         detail::KeyableTraits<T>::at(
1132             val_, arg.splitKey())).format(arg, cb);
1133   }
1134
1135  private:
1136   const T& val_;
1137 };
1138
1139 template <class Container, class Value>
1140 class FormatValue<
1141   detail::DefaultValueWrapper<Container, Value>,
1142   typename detail::KeyableTraits<Container>::enabled> {
1143  public:
1144   explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
1145     : val_(val) { }
1146
1147   template <class FormatCallback>
1148   void format(FormatArg& arg, FormatCallback& cb) const {
1149     FormatValue<typename std::decay<
1150       typename detail::KeyableTraits<Container>::value_type>::type>(
1151           detail::KeyableTraits<Container>::at(
1152               val_.container,
1153               arg.splitKey(),
1154               val_.defaultValue)).format(arg, cb);
1155   }
1156
1157  private:
1158   const detail::DefaultValueWrapper<Container, Value>& val_;
1159 };
1160
1161 // Partial specialization of FormatValue for pairs
1162 template <class A, class B>
1163 class FormatValue<std::pair<A, B>> {
1164  public:
1165   explicit FormatValue(const std::pair<A, B>& val) : val_(val) { }
1166
1167   template <class FormatCallback>
1168   void format(FormatArg& arg, FormatCallback& cb) const {
1169     int key = arg.splitIntKey();
1170     switch (key) {
1171     case 0:
1172       FormatValue<typename std::decay<A>::type>(val_.first).format(arg, cb);
1173       break;
1174     case 1:
1175       FormatValue<typename std::decay<B>::type>(val_.second).format(arg, cb);
1176       break;
1177     default:
1178       arg.error("invalid index for pair");
1179     }
1180   }
1181
1182  private:
1183   const std::pair<A, B>& val_;
1184 };
1185
1186 // Partial specialization of FormatValue for tuples
1187 template <class... Args>
1188 class FormatValue<std::tuple<Args...>> {
1189   typedef std::tuple<Args...> Tuple;
1190  public:
1191   explicit FormatValue(const Tuple& val) : val_(val) { }
1192
1193   template <class FormatCallback>
1194   void format(FormatArg& arg, FormatCallback& cb) const {
1195     int key = arg.splitIntKey();
1196     arg.enforce(key >= 0, "tuple index must be non-negative");
1197     doFormat(key, arg, cb);
1198   }
1199
1200  private:
1201   static constexpr size_t valueCount = std::tuple_size<Tuple>::value;
1202
1203   template <size_t K, class Callback>
1204   typename std::enable_if<K == valueCount>::type
1205   doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
1206     arg.enforce("tuple index out of range, max=", i);
1207   }
1208
1209   template <size_t K, class Callback>
1210   typename std::enable_if<(K < valueCount)>::type
1211   doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
1212     if (i == K) {
1213       FormatValue<typename std::decay<
1214         typename std::tuple_element<K, Tuple>::type>::type>(
1215           std::get<K>(val_)).format(arg, cb);
1216     } else {
1217       doFormatFrom<K+1>(i, arg, cb);
1218     }
1219   }
1220
1221   template <class Callback>
1222   void doFormat(size_t i, FormatArg& arg, Callback& cb) const {
1223     return doFormatFrom<0>(i, arg, cb);
1224   }
1225
1226   const Tuple& val_;
1227 };
1228
1229 // Partial specialization of FormatValue for nested Formatters
1230 template <bool containerMode, class... Args,
1231           template <bool, class...> class F>
1232 class FormatValue<F<containerMode, Args...>,
1233                   typename std::enable_if<detail::IsFormatter<
1234                       F<containerMode, Args...>>::value>::type> {
1235   typedef typename F<containerMode, Args...>::BaseType FormatterValue;
1236
1237  public:
1238   explicit FormatValue(const FormatterValue& f) : f_(f) { }
1239
1240   template <class FormatCallback>
1241   void format(FormatArg& arg, FormatCallback& cb) const {
1242     format_value::formatFormatter(f_, arg, cb);
1243   }
1244  private:
1245   const FormatterValue& f_;
1246 };
1247
1248 /**
1249  * Formatter objects can be appended to strings, and therefore they're
1250  * compatible with folly::toAppend and folly::to.
1251  */
1252 template <class Tgt, class Derived, bool containerMode, class... Args>
1253 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
1254     const BaseFormatter<Derived, containerMode, Args...>& value, Tgt* result) {
1255   value.appendTo(*result);
1256 }
1257
1258 }  // namespace folly
1259
1260 #pragma GCC diagnostic pop