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