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