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