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