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