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