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