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