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