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