Disable zerocopy if we're notified about deferred copies, add a isZeroCopyWriteInProg...
[folly.git] / folly / Format-inl.h
1 /*
2  * Copyright 2017 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 FOLLY_PUSH_WARNING
35 FOLLY_GCC_DISABLE_WARNING("-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
64 uintToHex(char* buffer, size_t bufLen, Uint v, 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(
158     StringPiece str,
159     Args&&... args)
160     : str_(str), values_(std::forward<Args>(args)...) {}
161
162 template <class Derived, bool containerMode, class... Args>
163 template <class Output>
164 void BaseFormatter<Derived, containerMode, Args...>::operator()(
165     Output& out) const {
166   // Copy raw string (without format specifiers) to output;
167   // not as simple as we'd like, as we still need to translate "}}" to "}"
168   // and throw if we see any lone "}"
169   auto outputString = [&out](StringPiece s) {
170     auto p = s.begin();
171     auto end = s.end();
172     while (p != end) {
173       auto q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
174       if (!q) {
175         out(StringPiece(p, end));
176         break;
177       }
178       ++q;
179       out(StringPiece(p, q));
180       p = q;
181
182       if (p == end || *p != '}') {
183         throwBadFormatArg("folly::format: single '}' in format string");
184       }
185       ++p;
186     }
187   };
188
189   auto p = str_.begin();
190   auto end = str_.end();
191
192   int nextArg = 0;
193   bool hasDefaultArgIndex = false;
194   bool hasExplicitArgIndex = false;
195   while (p != end) {
196     auto q = static_cast<const char*>(memchr(p, '{', size_t(end - p)));
197     if (!q) {
198       outputString(StringPiece(p, end));
199       break;
200     }
201     outputString(StringPiece(p, q));
202     p = q + 1;
203
204     if (p == end) {
205       throwBadFormatArg("folly::format: '}' at end of format string");
206     }
207
208     // "{{" -> "{"
209     if (*p == '{') {
210       out(StringPiece(p, 1));
211       ++p;
212       continue;
213     }
214
215     // Format string
216     q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
217     if (q == nullptr) {
218       throwBadFormatArg("folly::format: missing ending '}'");
219     }
220     FormatArg arg(StringPiece(p, q));
221     p = q + 1;
222
223     int argIndex = 0;
224     auto piece = arg.splitKey<true>(); // empty key component is okay
225     if (containerMode) { // static
226       arg.enforce(
227           arg.width != FormatArg::kDynamicWidth,
228           "dynamic field width not supported in vformat()");
229       if (piece.empty()) {
230         arg.setNextIntKey(nextArg++);
231         hasDefaultArgIndex = true;
232       } else {
233         arg.setNextKey(piece);
234         hasExplicitArgIndex = true;
235       }
236     } else {
237       if (piece.empty()) {
238         if (arg.width == FormatArg::kDynamicWidth) {
239           arg.enforce(
240               arg.widthIndex == FormatArg::kNoIndex,
241               "cannot provide width arg index without value arg index");
242           int sizeArg = nextArg++;
243           arg.width = asDerived().getSizeArg(size_t(sizeArg), arg);
244         }
245
246         argIndex = nextArg++;
247         hasDefaultArgIndex = true;
248       } else {
249         if (arg.width == FormatArg::kDynamicWidth) {
250           arg.enforce(
251               arg.widthIndex != FormatArg::kNoIndex,
252               "cannot provide value arg index without width arg index");
253           arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg);
254         }
255
256         try {
257           argIndex = to<int>(piece);
258         } catch (const std::out_of_range&) {
259           arg.error("argument index must be integer");
260         }
261         arg.enforce(argIndex >= 0, "argument index must be non-negative");
262         hasExplicitArgIndex = true;
263       }
264     }
265
266     if (hasDefaultArgIndex && hasExplicitArgIndex) {
267       throwBadFormatArg(
268           "folly::format: may not have both default and explicit arg indexes");
269     }
270
271     asDerived().doFormat(size_t(argIndex), arg, out);
272   }
273 }
274
275 template <class Derived, bool containerMode, class... Args>
276 void writeTo(
277     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     throwBadFormatArg("folly::format: invalid width");
294   }
295   if (arg.precision != FormatArg::kDefaultPrecision && arg.precision < 0) {
296     throwBadFormatArg("folly::format: invalid precision");
297   }
298
299   if (arg.precision != FormatArg::kDefaultPrecision &&
300       val.size() > static_cast<size_t>(arg.precision)) {
301     val.reset(val.data(), static_cast<size_t>(arg.precision));
302   }
303
304   constexpr int padBufSize = 128;
305   char padBuf[padBufSize];
306
307   // Output padding, no more than padBufSize at once
308   auto pad = [&padBuf, &cb, padBufSize](int chars) {
309     while (chars) {
310       int n = std::min(chars, padBufSize);
311       cb(StringPiece(padBuf, size_t(n)));
312       chars -= n;
313     }
314   };
315
316   int padRemaining = 0;
317   if (arg.width != FormatArg::kDefaultWidth &&
318       val.size() < static_cast<size_t>(arg.width)) {
319     char fill = arg.fill == FormatArg::kDefaultFill ? ' ' : arg.fill;
320     int padChars = static_cast<int>(arg.width - val.size());
321     memset(padBuf, fill, size_t(std::min(padBufSize, padChars)));
322
323     switch (arg.align) {
324       case FormatArg::Align::DEFAULT:
325       case FormatArg::Align::LEFT:
326         padRemaining = padChars;
327         break;
328       case FormatArg::Align::CENTER:
329         pad(padChars / 2);
330         padRemaining = padChars - padChars / 2;
331         break;
332       case FormatArg::Align::RIGHT:
333       case FormatArg::Align::PAD_AFTER_SIGN:
334         pad(padChars);
335         break;
336       default:
337         abort();
338         break;
339     }
340   }
341
342   cb(val);
343
344   if (padRemaining) {
345     pad(padRemaining);
346   }
347 }
348
349 template <class FormatCallback>
350 void formatNumber(
351     StringPiece val,
352     int prefixLen,
353     FormatArg& arg,
354     FormatCallback& cb) {
355   // precision means something different for numbers
356   arg.precision = FormatArg::kDefaultPrecision;
357   if (arg.align == FormatArg::Align::DEFAULT) {
358     arg.align = FormatArg::Align::RIGHT;
359   } else if (prefixLen && arg.align == FormatArg::Align::PAD_AFTER_SIGN) {
360     // Split off the prefix, then do any padding if necessary
361     cb(val.subpiece(0, size_t(prefixLen)));
362     val.advance(size_t(prefixLen));
363     arg.width = std::max(arg.width - prefixLen, 0);
364   }
365   format_value::formatString(val, arg, cb);
366 }
367
368 template <
369     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 (
382       arg.align != FormatArg::Align::LEFT &&
383       arg.align != FormatArg::Align::DEFAULT) {
384     // We can only avoid creating a temporary string if we align left,
385     // as we'd need to know the size beforehand otherwise
386     format_value::formatString(formatter.fbstr(), arg, cb);
387   } else {
388     auto fn = [&arg, &cb](StringPiece sp) mutable {
389       int sz = static_cast<int>(sp.size());
390       if (arg.precision != FormatArg::kDefaultPrecision) {
391         sz = std::min(arg.precision, sz);
392         sp.reset(sp.data(), size_t(sz));
393         arg.precision -= sz;
394       }
395       if (!sp.empty()) {
396         cb(sp);
397         if (arg.width != FormatArg::kDefaultWidth) {
398           arg.width = std::max(arg.width - sz, 0);
399         }
400       }
401     };
402     formatter(fn);
403     if (arg.width != FormatArg::kDefaultWidth && arg.width != 0) {
404       // Rely on formatString to do appropriate padding
405       format_value::formatString(StringPiece(), arg, cb);
406     }
407   }
408 }
409
410 } // namespace format_value
411
412 // Definitions for default FormatValue classes
413
414 // Integral types (except bool)
415 template <class T>
416 class FormatValue<
417     T,
418     typename std::enable_if<
419         std::is_integral<T>::value && !std::is_same<T, bool>::value>::type> {
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 = UT(-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 = static_cast<UT>(val_);
465       sign = '\0';
466
467       arg.enforce(
468           arg.sign == FormatArg::Sign::DEFAULT,
469           "sign specifications not allowed for unsigned values");
470     }
471
472     // max of:
473     // #x: 0x prefix + 16 bytes = 18 bytes
474     // #o: 0 prefix + 22 bytes = 23 bytes
475     // #b: 0b prefix + 64 bytes = 65 bytes
476     // ,d: 26 bytes (including thousands separators!)
477     // + nul terminator
478     // + 3 for sign and prefix shenanigans (see below)
479     constexpr size_t valBufSize = 69;
480     char valBuf[valBufSize];
481     char* valBufBegin = nullptr;
482     char* valBufEnd = nullptr;
483
484     int prefixLen = 0;
485     switch (presentation) {
486       case 'n': {
487         arg.enforce(
488             !arg.basePrefix,
489             "base prefix not allowed with '",
490             presentation,
491             "' specifier");
492
493         arg.enforce(
494             !arg.thousandsSeparator,
495             "cannot use ',' with the '",
496             presentation,
497             "' specifier");
498
499         valBufBegin = valBuf + 3; // room for sign and base prefix
500 #if defined(__ANDROID__)
501         int len = snprintf(
502             valBufBegin,
503             (valBuf + valBufSize) - valBufBegin,
504             "%" PRIuMAX,
505             static_cast<uintmax_t>(uval));
506 #else
507         int len = snprintf(
508             valBufBegin,
509             size_t((valBuf + valBufSize) - valBufBegin),
510             "%ju",
511             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(
521             !arg.basePrefix,
522             "base prefix not allowed with '",
523             presentation,
524             "' specifier");
525         valBufBegin = valBuf + 3; // room for sign and base prefix
526
527         // Use uintToBuffer, faster than sprintf
528         valBufEnd = valBufBegin + uint64ToBufferUnsafe(uval, valBufBegin);
529         if (arg.thousandsSeparator) {
530           detail::insertThousandsGroupingUnsafe(valBufBegin, &valBufEnd);
531         }
532         break;
533       case 'c':
534         arg.enforce(
535             !arg.basePrefix,
536             "base prefix not allowed with '",
537             presentation,
538             "' specifier");
539         arg.enforce(
540             !arg.thousandsSeparator,
541             "thousands separator (',') not allowed with '",
542             presentation,
543             "' specifier");
544         valBufBegin = valBuf + 3;
545         *valBufBegin = static_cast<char>(uval);
546         valBufEnd = valBufBegin + 1;
547         break;
548       case 'o':
549       case 'O':
550         arg.enforce(
551             !arg.thousandsSeparator,
552             "thousands separator (',') not allowed with '",
553             presentation,
554             "' specifier");
555         valBufEnd = valBuf + valBufSize - 1;
556         valBufBegin =
557             valBuf + detail::uintToOctal(valBuf, valBufSize - 1, uval);
558         if (arg.basePrefix) {
559           *--valBufBegin = '0';
560           prefixLen = 1;
561         }
562         break;
563       case 'x':
564         arg.enforce(
565             !arg.thousandsSeparator,
566             "thousands separator (',') not allowed with '",
567             presentation,
568             "' specifier");
569         valBufEnd = valBuf + valBufSize - 1;
570         valBufBegin =
571             valBuf + detail::uintToHexLower(valBuf, valBufSize - 1, uval);
572         if (arg.basePrefix) {
573           *--valBufBegin = 'x';
574           *--valBufBegin = '0';
575           prefixLen = 2;
576         }
577         break;
578       case 'X':
579         arg.enforce(
580             !arg.thousandsSeparator,
581             "thousands separator (',') not allowed with '",
582             presentation,
583             "' specifier");
584         valBufEnd = valBuf + valBufSize - 1;
585         valBufBegin =
586             valBuf + detail::uintToHexUpper(valBuf, valBufSize - 1, uval);
587         if (arg.basePrefix) {
588           *--valBufBegin = 'X';
589           *--valBufBegin = '0';
590           prefixLen = 2;
591         }
592         break;
593       case 'b':
594       case 'B':
595         arg.enforce(
596             !arg.thousandsSeparator,
597             "thousands separator (',') not allowed with '",
598             presentation,
599             "' specifier");
600         valBufEnd = valBuf + valBufSize - 1;
601         valBufBegin =
602             valBuf + detail::uintToBinary(valBuf, valBufSize - 1, uval);
603         if (arg.basePrefix) {
604           *--valBufBegin = presentation; // 0b or 0B
605           *--valBufBegin = '0';
606           prefixLen = 2;
607         }
608         break;
609       default:
610         arg.error("invalid specifier '", presentation, "'");
611     }
612
613     if (sign) {
614       *--valBufBegin = sign;
615       ++prefixLen;
616     }
617
618     format_value::formatNumber(
619         StringPiece(valBufBegin, valBufEnd), prefixLen, arg, cb);
620   }
621
622  private:
623   T val_;
624 };
625
626 // Bool
627 template <>
628 class FormatValue<bool> {
629  public:
630   explicit FormatValue(bool val) : val_(val) {}
631
632   template <class FormatCallback>
633   void format(FormatArg& arg, FormatCallback& cb) const {
634     if (arg.presentation == FormatArg::kDefaultPresentation) {
635       arg.validate(FormatArg::Type::OTHER);
636       format_value::formatString(val_ ? "true" : "false", arg, cb);
637     } else { // number
638       FormatValue<int>(val_).format(arg, cb);
639     }
640   }
641
642  private:
643   bool val_;
644 };
645
646 // double
647 template <>
648 class FormatValue<double> {
649  public:
650   explicit FormatValue(double val) : val_(val) {}
651
652   template <class FormatCallback>
653   void format(FormatArg& arg, FormatCallback& cb) const {
654     fbstring piece;
655     int prefixLen;
656     formatHelper(piece, prefixLen, arg);
657     format_value::formatNumber(piece, prefixLen, arg, cb);
658   }
659
660  private:
661   void formatHelper(fbstring& piece, int& prefixLen, FormatArg& arg) const;
662
663   double val_;
664 };
665
666 // float (defer to double)
667 template <>
668 class FormatValue<float> {
669  public:
670   explicit FormatValue(float val) : val_(val) {}
671
672   template <class FormatCallback>
673   void format(FormatArg& arg, FormatCallback& cb) const {
674     FormatValue<double>(val_).format(arg, cb);
675   }
676
677  private:
678   float val_;
679 };
680
681 // String-y types (implicitly convertible to StringPiece, except char*)
682 template <class T>
683 class FormatValue<
684     T,
685     typename std::enable_if<
686         (!std::is_pointer<T>::value ||
687          !std::is_same<
688              char,
689              typename std::decay<typename std::remove_pointer<T>::type>::type>::
690              value) &&
691         std::is_convertible<T, StringPiece>::value>::type> {
692  public:
693   explicit FormatValue(StringPiece val) : val_(val) {}
694
695   template <class FormatCallback>
696   void format(FormatArg& arg, FormatCallback& cb) const {
697     if (arg.keyEmpty()) {
698       arg.validate(FormatArg::Type::OTHER);
699       arg.enforce(
700           arg.presentation == FormatArg::kDefaultPresentation ||
701               arg.presentation == 's',
702           "invalid specifier '",
703           arg.presentation,
704           "'");
705       format_value::formatString(val_, arg, cb);
706     } else {
707       FormatValue<char>(val_.at(size_t(arg.splitIntKey()))).format(arg, cb);
708     }
709   }
710
711  private:
712   StringPiece val_;
713 };
714
715 // Null
716 template <>
717 class FormatValue<std::nullptr_t> {
718  public:
719   explicit FormatValue(std::nullptr_t) {}
720
721   template <class FormatCallback>
722   void format(FormatArg& arg, FormatCallback& cb) const {
723     arg.validate(FormatArg::Type::OTHER);
724     arg.enforce(
725         arg.presentation == FormatArg::kDefaultPresentation,
726         "invalid specifier '",
727         arg.presentation,
728         "'");
729     format_value::formatString("(null)", arg, cb);
730   }
731 };
732
733 // Partial specialization of FormatValue for char*
734 template <class T>
735 class FormatValue<
736     T*,
737     typename std::enable_if<
738         std::is_same<char, typename std::decay<T>::type>::value>::type> {
739  public:
740   explicit FormatValue(T* val) : val_(val) {}
741
742   template <class FormatCallback>
743   void format(FormatArg& arg, FormatCallback& cb) const {
744     if (arg.keyEmpty()) {
745       if (!val_) {
746         FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
747       } else {
748         FormatValue<StringPiece>(val_).format(arg, cb);
749       }
750     } else {
751       FormatValue<typename std::decay<T>::type>(val_[arg.splitIntKey()])
752           .format(arg, cb);
753     }
754   }
755
756  private:
757   T* val_;
758 };
759
760 // Partial specialization of FormatValue for void*
761 template <class T>
762 class FormatValue<
763     T*,
764     typename std::enable_if<
765         std::is_same<void, typename std::decay<T>::type>::value>::type> {
766  public:
767   explicit FormatValue(T* val) : val_(val) {}
768
769   template <class FormatCallback>
770   void format(FormatArg& arg, FormatCallback& cb) const {
771     if (!val_) {
772       FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
773     } else {
774       // Print as a pointer, in hex.
775       arg.validate(FormatArg::Type::OTHER);
776       arg.enforce(
777           arg.presentation == FormatArg::kDefaultPresentation,
778           "invalid specifier '",
779           arg.presentation,
780           "'");
781       arg.basePrefix = true;
782       arg.presentation = 'x';
783       if (arg.align == FormatArg::Align::DEFAULT) {
784         arg.align = FormatArg::Align::LEFT;
785       }
786       FormatValue<uintptr_t>(reinterpret_cast<uintptr_t>(val_))
787           .doFormat(arg, cb);
788     }
789   }
790
791  private:
792   T* val_;
793 };
794
795 template <class T, class = void>
796 class TryFormatValue {
797  public:
798   template <class FormatCallback>
799   static void
800   formatOrFail(T& /* value */, FormatArg& arg, FormatCallback& /* cb */) {
801     arg.error("No formatter available for this type");
802   }
803 };
804
805 template <class T>
806 class TryFormatValue<
807     T,
808     typename std::enable_if<
809         0 < sizeof(FormatValue<typename std::decay<T>::type>)>::type> {
810  public:
811   template <class FormatCallback>
812   static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
813     FormatValue<typename std::decay<T>::type>(value).format(arg, cb);
814   }
815 };
816
817 // Partial specialization of FormatValue for other pointers
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 &&
823         !std::is_same<void, typename std::decay<T>::type>::value>::type> {
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       FormatValue<void*>((void*)val_).format(arg, cb);
831     } else {
832       TryFormatValue<T>::formatOrFail(val_[arg.splitIntKey()], arg, cb);
833     }
834   }
835
836  private:
837   T* val_;
838 };
839
840 namespace detail {
841
842 // std::array
843 template <class T, size_t N>
844 struct IndexableTraits<std::array<T, N>>
845     : public IndexableTraitsSeq<std::array<T, N>> {};
846
847 // std::vector
848 template <class T, class A>
849 struct IndexableTraits<std::vector<T, A>>
850     : public IndexableTraitsSeq<std::vector<T, A>> {};
851
852 // std::deque
853 template <class T, class A>
854 struct IndexableTraits<std::deque<T, A>>
855     : public IndexableTraitsSeq<std::deque<T, A>> {};
856
857 // std::map with integral keys
858 template <class K, class T, class C, class A>
859 struct IndexableTraits<
860     std::map<K, T, C, A>,
861     typename std::enable_if<std::is_integral<K>::value>::type>
862     : public IndexableTraitsAssoc<std::map<K, T, C, A>> {};
863
864 // std::unordered_map with integral keys
865 template <class K, class T, class H, class E, class A>
866 struct IndexableTraits<
867     std::unordered_map<K, T, H, E, A>,
868     typename std::enable_if<std::is_integral<K>::value>::type>
869     : public IndexableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {};
870
871 } // namespace detail
872
873 // Partial specialization of FormatValue for integer-indexable containers
874 template <class T>
875 class FormatValue<T, typename detail::IndexableTraits<T>::enabled> {
876  public:
877   explicit FormatValue(const T& val) : val_(val) {}
878
879   template <class FormatCallback>
880   void format(FormatArg& arg, FormatCallback& cb) const {
881     FormatValue<typename std::decay<
882         typename detail::IndexableTraits<T>::value_type>::type>(
883         detail::IndexableTraits<T>::at(val_, arg.splitIntKey()))
884         .format(arg, cb);
885   }
886
887  private:
888   const T& val_;
889 };
890
891 template <class Container, class Value>
892 class FormatValue<
893     detail::DefaultValueWrapper<Container, Value>,
894     typename detail::IndexableTraits<Container>::enabled> {
895  public:
896   explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
897       : val_(val) {}
898
899   template <class FormatCallback>
900   void format(FormatArg& arg, FormatCallback& cb) const {
901     FormatValue<typename std::decay<
902         typename detail::IndexableTraits<Container>::value_type>::type>(
903         detail::IndexableTraits<Container>::at(
904             val_.container, arg.splitIntKey(), val_.defaultValue))
905         .format(arg, cb);
906   }
907
908  private:
909   const detail::DefaultValueWrapper<Container, Value>& val_;
910 };
911
912 namespace detail {
913
914 // Define enabled, key_type, convert from StringPiece to the key types
915 // that we support
916 template <class T>
917 struct KeyFromStringPiece;
918
919 // std::string
920 template <>
921 struct KeyFromStringPiece<std::string> : public FormatTraitsBase {
922   typedef std::string key_type;
923   static std::string convert(StringPiece s) {
924     return s.toString();
925   }
926   typedef void enabled;
927 };
928
929 // fbstring
930 template <>
931 struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
932   typedef fbstring key_type;
933   static fbstring convert(StringPiece s) {
934     return s.to<fbstring>();
935   }
936 };
937
938 // StringPiece
939 template <>
940 struct KeyFromStringPiece<StringPiece> : public FormatTraitsBase {
941   typedef StringPiece key_type;
942   static StringPiece convert(StringPiece s) {
943     return s;
944   }
945 };
946
947 // Base class for associative types keyed by strings
948 template <class T>
949 struct KeyableTraitsAssoc : public FormatTraitsBase {
950   typedef typename T::key_type key_type;
951   typedef typename T::value_type::second_type value_type;
952   static const value_type& at(const T& map, StringPiece key) {
953     return map.at(KeyFromStringPiece<key_type>::convert(key));
954   }
955   static const value_type&
956   at(const T& map, StringPiece key, const value_type& dflt) {
957     auto pos = map.find(KeyFromStringPiece<key_type>::convert(key));
958     return pos != map.end() ? pos->second : dflt;
959   }
960 };
961
962 // Define enabled, key_type, value_type, at() for supported string-keyed
963 // types
964 template <class T, class Enabled = void>
965 struct KeyableTraits;
966
967 // std::map with string key
968 template <class K, class T, class C, class A>
969 struct KeyableTraits<
970     std::map<K, T, C, A>,
971     typename KeyFromStringPiece<K>::enabled>
972     : public KeyableTraitsAssoc<std::map<K, T, C, A>> {};
973
974 // std::unordered_map with string key
975 template <class K, class T, class H, class E, class A>
976 struct KeyableTraits<
977     std::unordered_map<K, T, H, E, A>,
978     typename KeyFromStringPiece<K>::enabled>
979     : public KeyableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {};
980
981 } // namespace detail
982
983 // Partial specialization of FormatValue for string-keyed containers
984 template <class T>
985 class FormatValue<T, typename detail::KeyableTraits<T>::enabled> {
986  public:
987   explicit FormatValue(const T& val) : val_(val) {}
988
989   template <class FormatCallback>
990   void format(FormatArg& arg, FormatCallback& cb) const {
991     FormatValue<typename std::decay<
992         typename detail::KeyableTraits<T>::value_type>::type>(
993         detail::KeyableTraits<T>::at(val_, arg.splitKey()))
994         .format(arg, cb);
995   }
996
997  private:
998   const T& val_;
999 };
1000
1001 template <class Container, class Value>
1002 class FormatValue<
1003     detail::DefaultValueWrapper<Container, Value>,
1004     typename detail::KeyableTraits<Container>::enabled> {
1005  public:
1006   explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
1007       : val_(val) {}
1008
1009   template <class FormatCallback>
1010   void format(FormatArg& arg, FormatCallback& cb) const {
1011     FormatValue<typename std::decay<
1012         typename detail::KeyableTraits<Container>::value_type>::type>(
1013         detail::KeyableTraits<Container>::at(
1014             val_.container, arg.splitKey(), val_.defaultValue))
1015         .format(arg, cb);
1016   }
1017
1018  private:
1019   const detail::DefaultValueWrapper<Container, Value>& val_;
1020 };
1021
1022 // Partial specialization of FormatValue for pairs
1023 template <class A, class B>
1024 class FormatValue<std::pair<A, B>> {
1025  public:
1026   explicit FormatValue(const std::pair<A, B>& val) : val_(val) {}
1027
1028   template <class FormatCallback>
1029   void format(FormatArg& arg, FormatCallback& cb) const {
1030     int key = arg.splitIntKey();
1031     switch (key) {
1032       case 0:
1033         FormatValue<typename std::decay<A>::type>(val_.first).format(arg, cb);
1034         break;
1035       case 1:
1036         FormatValue<typename std::decay<B>::type>(val_.second).format(arg, cb);
1037         break;
1038       default:
1039         arg.error("invalid index for pair");
1040     }
1041   }
1042
1043  private:
1044   const std::pair<A, B>& val_;
1045 };
1046
1047 // Partial specialization of FormatValue for tuples
1048 template <class... Args>
1049 class FormatValue<std::tuple<Args...>> {
1050   typedef std::tuple<Args...> Tuple;
1051
1052  public:
1053   explicit FormatValue(const Tuple& val) : val_(val) {}
1054
1055   template <class FormatCallback>
1056   void format(FormatArg& arg, FormatCallback& cb) const {
1057     int key = arg.splitIntKey();
1058     arg.enforce(key >= 0, "tuple index must be non-negative");
1059     doFormat(size_t(key), arg, cb);
1060   }
1061
1062  private:
1063   static constexpr size_t valueCount = std::tuple_size<Tuple>::value;
1064
1065   template <size_t K, class Callback>
1066   typename std::enable_if<K == valueCount>::type
1067   doFormatFrom(size_t i, FormatArg& arg, Callback& /* cb */) const {
1068     arg.enforce("tuple index out of range, max=", i);
1069   }
1070
1071   template <size_t K, class Callback>
1072   typename std::enable_if<(K < valueCount)>::type
1073   doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
1074     if (i == K) {
1075       FormatValue<typename std::decay<
1076           typename std::tuple_element<K, Tuple>::type>::type>(std::get<K>(val_))
1077           .format(arg, cb);
1078     } else {
1079       doFormatFrom<K + 1>(i, arg, cb);
1080     }
1081   }
1082
1083   template <class Callback>
1084   void doFormat(size_t i, FormatArg& arg, Callback& cb) const {
1085     return doFormatFrom<0>(i, arg, cb);
1086   }
1087
1088   const Tuple& val_;
1089 };
1090
1091 // Partial specialization of FormatValue for nested Formatters
1092 template <bool containerMode, class... Args, template <bool, class...> class F>
1093 class FormatValue<
1094     F<containerMode, Args...>,
1095     typename std::enable_if<
1096         detail::IsFormatter<F<containerMode, Args...>>::value>::type> {
1097   typedef typename F<containerMode, Args...>::BaseType FormatterValue;
1098
1099  public:
1100   explicit FormatValue(const FormatterValue& f) : f_(f) {}
1101
1102   template <class FormatCallback>
1103   void format(FormatArg& arg, FormatCallback& cb) const {
1104     format_value::formatFormatter(f_, arg, cb);
1105   }
1106
1107  private:
1108   const FormatterValue& f_;
1109 };
1110
1111 /**
1112  * Formatter objects can be appended to strings, and therefore they're
1113  * compatible with folly::toAppend and folly::to.
1114  */
1115 template <class Tgt, class Derived, bool containerMode, class... Args>
1116 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
1117     const BaseFormatter<Derived, containerMode, Args...>& value,
1118     Tgt* result) {
1119   value.appendTo(*result);
1120 }
1121
1122 } // namespace folly
1123
1124 FOLLY_POP_WARNING