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