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