proxygen
folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type > Class Template Reference

#include <Format-inl.h>

Public Member Functions

 FormatValue (T val)
 
T getValue () const
 
template<class FormatCallback >
void format (FormatArg &arg, FormatCallback &cb) const
 
template<class FormatCallback >
void doFormat (FormatArg &arg, FormatCallback &cb) const
 

Private Attributes

T val_
 

Detailed Description

template<class T>
class folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type >

Definition at line 423 of file Format-inl.h.

Constructor & Destructor Documentation

template<class T >
folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type >::FormatValue ( T  val)
inlineexplicit

Member Function Documentation

template<class T >
template<class FormatCallback >
void folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type >::doFormat ( FormatArg arg,
FormatCallback &  cb 
) const
inline

Definition at line 441 of file Format-inl.h.

References folly::FormatArg::basePrefix, folly::FormatArg::enforce(), folly::FormatArg::error(), folly::format_value::formatNumber(), folly::detail::insertThousandsGroupingUnsafe(), folly::is_negative(), folly::FormatArg::presentation, folly::FormatArg::sign, folly::FormatArg::thousandsSeparator, type, folly::uint64ToBufferUnsafe(), folly::detail::uintToBinary(), folly::detail::uintToHexLower(), folly::detail::uintToHexUpper(), folly::detail::uintToOctal(), and value.

441  {
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) {
460  sign = '+';
461  break;
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  }
uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer)
Definition: Conv.h:383
size_t uintToBinary(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:142
PskType type
size_t uintToHexLower(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:90
size_t uintToOctal(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:112
static constexpr char kDefaultPresentation
Definition: FormatArg.h:156
static const char *const value
Definition: Conv.cpp:50
void insertThousandsGroupingUnsafe(char *start_buffer, char **end_buffer)
Definition: Format.cpp:387
constexpr bool is_negative(T x)
Definition: Traits.h:675
size_t uintToHexUpper(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:99
Range< const char * > StringPiece
void formatNumber(StringPiece val, int prefixLen, FormatArg &arg, FormatCallback &cb)
Definition: Format-inl.h:357
template<class T >
template<class FormatCallback >
void folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type >::format ( FormatArg arg,
FormatCallback &  cb 
) const
inline

Definition at line 435 of file Format-inl.h.

References folly::FormatArg::validate().

template<class T >
T folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type >::getValue ( ) const
inline

Member Data Documentation

template<class T >
T folly::FormatValue< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, bool >::value >::type >::val_
private

Definition at line 630 of file Format-inl.h.


The documentation for this class was generated from the following file: