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