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