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