Commit 9773e441 authored by Phil Willoughby's avatar Phil Willoughby Committed by Facebook Github Bot

Run clang-format over Format*.h

Summary:
Changes are planned, this will make it easier for the new code to look good
without making the older code look weird.

Reviewed By: yfeldblum

Differential Revision: D4514839

fbshipit-source-id: 43f8cd7d85901e1915cc434a0f4b5fd6bce1ec7a
parent 3259ce0e
...@@ -60,8 +60,8 @@ const size_t kMaxBinaryLength = 8 * sizeof(uintmax_t); ...@@ -60,8 +60,8 @@ const size_t kMaxBinaryLength = 8 * sizeof(uintmax_t);
* [buf+begin, buf+bufLen). * [buf+begin, buf+bufLen).
*/ */
template <class Uint> template <class Uint>
size_t uintToHex(char* buffer, size_t bufLen, Uint v, size_t
const char (&repr)[256][2]) { uintToHex(char* buffer, size_t bufLen, Uint v, const char (&repr)[256][2]) {
// 'v >>= 7, v >>= 1' is no more than a work around to get rid of shift size // 'v >>= 7, v >>= 1' is no more than a work around to get rid of shift size
// warning when Uint = uint8_t (it's false as v >= 256 implies sizeof(v) > 1). // warning when Uint = uint8_t (it's false as v >= 256 implies sizeof(v) > 1).
for (; !less_than<unsigned, 256>(v); v >>= 7, v >>= 1) { for (; !less_than<unsigned, 256>(v); v >>= 7, v >>= 1) {
...@@ -151,26 +151,28 @@ size_t uintToBinary(char* buffer, size_t bufLen, Uint v) { ...@@ -151,26 +151,28 @@ size_t uintToBinary(char* buffer, size_t bufLen, Uint v) {
return bufLen; return bufLen;
} }
} // namespace detail } // namespace detail
template <class Derived, bool containerMode, class... Args> template <class Derived, bool containerMode, class... Args>
BaseFormatter<Derived, containerMode, Args...>::BaseFormatter(StringPiece str, BaseFormatter<Derived, containerMode, Args...>::BaseFormatter(
Args&&... args) StringPiece str,
Args&&... args)
: str_(str), : str_(str),
values_(FormatValue<typename std::decay<Args>::type>( values_(FormatValue<typename std::decay<Args>::type>(
std::forward<Args>(args))...) { std::forward<Args>(args))...) {
static_assert(!containerMode || sizeof...(Args) == 1, static_assert(
"Exactly one argument required in container mode"); !containerMode || sizeof...(Args) == 1,
"Exactly one argument required in container mode");
} }
template <class Derived, bool containerMode, class... Args> template <class Derived, bool containerMode, class... Args>
template <class Output> template <class Output>
void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out) void BaseFormatter<Derived, containerMode, Args...>::operator()(
const { Output& out) const {
// Copy raw string (without format specifiers) to output; // Copy raw string (without format specifiers) to output;
// not as simple as we'd like, as we still need to translate "}}" to "}" // not as simple as we'd like, as we still need to translate "}}" to "}"
// and throw if we see any lone "}" // and throw if we see any lone "}"
auto outputString = [&out] (StringPiece s) { auto outputString = [&out](StringPiece s) {
auto p = s.begin(); auto p = s.begin();
auto end = s.end(); auto end = s.end();
while (p != end) { while (p != end) {
...@@ -225,10 +227,11 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out) ...@@ -225,10 +227,11 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out)
p = q + 1; p = q + 1;
int argIndex = 0; int argIndex = 0;
auto piece = arg.splitKey<true>(); // empty key component is okay auto piece = arg.splitKey<true>(); // empty key component is okay
if (containerMode) { // static if (containerMode) { // static
arg.enforce(arg.width != FormatArg::kDynamicWidth, arg.enforce(
"dynamic field width not supported in vformat()"); arg.width != FormatArg::kDynamicWidth,
"dynamic field width not supported in vformat()");
if (piece.empty()) { if (piece.empty()) {
arg.setNextIntKey(nextArg++); arg.setNextIntKey(nextArg++);
hasDefaultArgIndex = true; hasDefaultArgIndex = true;
...@@ -239,8 +242,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out) ...@@ -239,8 +242,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out)
} else { } else {
if (piece.empty()) { if (piece.empty()) {
if (arg.width == FormatArg::kDynamicWidth) { if (arg.width == FormatArg::kDynamicWidth) {
arg.enforce(arg.widthIndex == FormatArg::kNoIndex, arg.enforce(
"cannot provide width arg index without value arg index"); arg.widthIndex == FormatArg::kNoIndex,
"cannot provide width arg index without value arg index");
int sizeArg = nextArg++; int sizeArg = nextArg++;
arg.width = getSizeArg(size_t(sizeArg), arg); arg.width = getSizeArg(size_t(sizeArg), arg);
} }
...@@ -249,8 +253,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out) ...@@ -249,8 +253,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out)
hasDefaultArgIndex = true; hasDefaultArgIndex = true;
} else { } else {
if (arg.width == FormatArg::kDynamicWidth) { if (arg.width == FormatArg::kDynamicWidth) {
arg.enforce(arg.widthIndex != FormatArg::kNoIndex, arg.enforce(
"cannot provide value arg index without width arg index"); arg.widthIndex != FormatArg::kNoIndex,
"cannot provide value arg index without width arg index");
arg.width = getSizeArg(size_t(arg.widthIndex), arg); arg.width = getSizeArg(size_t(arg.widthIndex), arg);
} }
...@@ -274,9 +279,10 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out) ...@@ -274,9 +279,10 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out)
} }
template <class Derived, bool containerMode, class... Args> template <class Derived, bool containerMode, class... Args>
void writeTo(FILE* fp, void writeTo(
const BaseFormatter<Derived, containerMode, Args...>& formatter) { FILE* fp,
auto writer = [fp] (StringPiece sp) { const BaseFormatter<Derived, containerMode, Args...>& formatter) {
auto writer = [fp](StringPiece sp) {
size_t n = fwrite(sp.data(), 1, sp.size(), fp); size_t n = fwrite(sp.data(), 1, sp.size(), fp);
if (n < sp.size()) { if (n < sp.size()) {
throwSystemError("Formatter writeTo", "fwrite failed"); throwSystemError("Formatter writeTo", "fwrite failed");
...@@ -309,7 +315,7 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) { ...@@ -309,7 +315,7 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) {
char padBuf[padBufSize]; char padBuf[padBufSize];
// Output padding, no more than padBufSize at once // Output padding, no more than padBufSize at once
auto pad = [&padBuf, &cb, padBufSize] (int chars) { auto pad = [&padBuf, &cb, padBufSize](int chars) {
while (chars) { while (chars) {
int n = std::min(chars, padBufSize); int n = std::min(chars, padBufSize);
cb(StringPiece(padBuf, size_t(n))); cb(StringPiece(padBuf, size_t(n)));
...@@ -321,25 +327,25 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) { ...@@ -321,25 +327,25 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) {
if (arg.width != FormatArg::kDefaultWidth && if (arg.width != FormatArg::kDefaultWidth &&
val.size() < static_cast<size_t>(arg.width)) { val.size() < static_cast<size_t>(arg.width)) {
char fill = arg.fill == FormatArg::kDefaultFill ? ' ' : arg.fill; char fill = arg.fill == FormatArg::kDefaultFill ? ' ' : arg.fill;
int padChars = static_cast<int> (arg.width - val.size()); int padChars = static_cast<int>(arg.width - val.size());
memset(padBuf, fill, size_t(std::min(padBufSize, padChars))); memset(padBuf, fill, size_t(std::min(padBufSize, padChars)));
switch (arg.align) { switch (arg.align) {
case FormatArg::Align::DEFAULT: case FormatArg::Align::DEFAULT:
case FormatArg::Align::LEFT: case FormatArg::Align::LEFT:
padRemaining = padChars; padRemaining = padChars;
break; break;
case FormatArg::Align::CENTER: case FormatArg::Align::CENTER:
pad(padChars / 2); pad(padChars / 2);
padRemaining = padChars - padChars / 2; padRemaining = padChars - padChars / 2;
break; break;
case FormatArg::Align::RIGHT: case FormatArg::Align::RIGHT:
case FormatArg::Align::PAD_AFTER_SIGN: case FormatArg::Align::PAD_AFTER_SIGN:
pad(padChars); pad(padChars);
break; break;
default: default:
abort(); abort();
break; break;
} }
} }
...@@ -351,8 +357,11 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) { ...@@ -351,8 +357,11 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) {
} }
template <class FormatCallback> template <class FormatCallback>
void formatNumber(StringPiece val, int prefixLen, FormatArg& arg, void formatNumber(
FormatCallback& cb) { StringPiece val,
int prefixLen,
FormatArg& arg,
FormatCallback& cb) {
// precision means something different for numbers // precision means something different for numbers
arg.precision = FormatArg::kDefaultPrecision; arg.precision = FormatArg::kDefaultPrecision;
if (arg.align == FormatArg::Align::DEFAULT) { if (arg.align == FormatArg::Align::DEFAULT) {
...@@ -366,10 +375,11 @@ void formatNumber(StringPiece val, int prefixLen, FormatArg& arg, ...@@ -366,10 +375,11 @@ void formatNumber(StringPiece val, int prefixLen, FormatArg& arg,
format_value::formatString(val, arg, cb); format_value::formatString(val, arg, cb);
} }
template <class FormatCallback, template <
class Derived, class FormatCallback,
bool containerMode, class Derived,
class... Args> bool containerMode,
class... Args>
void formatFormatter( void formatFormatter(
const BaseFormatter<Derived, containerMode, Args...>& formatter, const BaseFormatter<Derived, containerMode, Args...>& formatter,
FormatArg& arg, FormatArg& arg,
...@@ -378,13 +388,14 @@ void formatFormatter( ...@@ -378,13 +388,14 @@ void formatFormatter(
arg.precision == FormatArg::kDefaultPrecision) { arg.precision == FormatArg::kDefaultPrecision) {
// nothing to do // nothing to do
formatter(cb); formatter(cb);
} else if (arg.align != FormatArg::Align::LEFT && } else if (
arg.align != FormatArg::Align::DEFAULT) { arg.align != FormatArg::Align::LEFT &&
arg.align != FormatArg::Align::DEFAULT) {
// We can only avoid creating a temporary string if we align left, // We can only avoid creating a temporary string if we align left,
// as we'd need to know the size beforehand otherwise // as we'd need to know the size beforehand otherwise
format_value::formatString(formatter.fbstr(), arg, cb); format_value::formatString(formatter.fbstr(), arg, cb);
} else { } else {
auto fn = [&arg, &cb] (StringPiece sp) mutable { auto fn = [&arg, &cb](StringPiece sp) mutable {
int sz = static_cast<int>(sp.size()); int sz = static_cast<int>(sp.size());
if (arg.precision != FormatArg::kDefaultPrecision) { if (arg.precision != FormatArg::kDefaultPrecision) {
sz = std::min(arg.precision, sz); sz = std::min(arg.precision, sz);
...@@ -406,19 +417,18 @@ void formatFormatter( ...@@ -406,19 +417,18 @@ void formatFormatter(
} }
} }
} // namespace format_value } // namespace format_value
// Definitions for default FormatValue classes // Definitions for default FormatValue classes
// Integral types (except bool) // Integral types (except bool)
template <class T> template <class T>
class FormatValue< class FormatValue<
T, typename std::enable_if< T,
std::is_integral<T>::value && typename std::enable_if<
!std::is_same<T, bool>::value>::type> std::is_integral<T>::value && !std::is_same<T, bool>::value>::type> {
{
public: public:
explicit FormatValue(T val) : val_(val) { } explicit FormatValue(T val) : val_(val) {}
T getValue() const { T getValue() const {
return val_; return val_;
...@@ -449,23 +459,24 @@ class FormatValue< ...@@ -449,23 +459,24 @@ class FormatValue<
} else { } else {
uval = static_cast<UT>(val_); uval = static_cast<UT>(val_);
switch (arg.sign) { switch (arg.sign) {
case FormatArg::Sign::PLUS_OR_MINUS: case FormatArg::Sign::PLUS_OR_MINUS:
sign = '+'; sign = '+';
break; break;
case FormatArg::Sign::SPACE_OR_MINUS: case FormatArg::Sign::SPACE_OR_MINUS:
sign = ' '; sign = ' ';
break; break;
default: default:
sign = '\0'; sign = '\0';
break; break;
} }
} }
} else { } else {
uval = static_cast<UT>(val_); uval = static_cast<UT>(val_);
sign = '\0'; sign = '\0';
arg.enforce(arg.sign == FormatArg::Sign::DEFAULT, arg.enforce(
"sign specifications not allowed for unsigned values"); arg.sign == FormatArg::Sign::DEFAULT,
"sign specifications not allowed for unsigned values");
} }
// max of: // max of:
...@@ -482,109 +493,131 @@ class FormatValue< ...@@ -482,109 +493,131 @@ class FormatValue<
int prefixLen = 0; int prefixLen = 0;
switch (presentation) { switch (presentation) {
case 'n': { case 'n': {
arg.enforce(!arg.basePrefix, arg.enforce(
"base prefix not allowed with '", presentation, !arg.basePrefix,
"' specifier"); "base prefix not allowed with '",
presentation,
arg.enforce(!arg.thousandsSeparator, "' specifier");
"cannot use ',' with the '", presentation,
"' specifier"); arg.enforce(
!arg.thousandsSeparator,
valBufBegin = valBuf + 3; // room for sign and base prefix "cannot use ',' with the '",
presentation,
"' specifier");
valBufBegin = valBuf + 3; // room for sign and base prefix
#if defined(__ANDROID__) #if defined(__ANDROID__)
int len = snprintf(valBufBegin, (valBuf + valBufSize) - valBufBegin, int len = snprintf(
"%" PRIuMAX, static_cast<uintmax_t>(uval)); valBufBegin,
(valBuf + valBufSize) - valBufBegin,
"%" PRIuMAX,
static_cast<uintmax_t>(uval));
#else #else
int len = snprintf( int len = snprintf(
valBufBegin, valBufBegin,
size_t((valBuf + valBufSize) - valBufBegin), size_t((valBuf + valBufSize) - valBufBegin),
"%ju", "%ju",
static_cast<uintmax_t>(uval)); static_cast<uintmax_t>(uval));
#endif #endif
// valBufSize should always be big enough, so this should never // valBufSize should always be big enough, so this should never
// happen. // happen.
assert(len < valBuf + valBufSize - valBufBegin); assert(len < valBuf + valBufSize - valBufBegin);
valBufEnd = valBufBegin + len; valBufEnd = valBufBegin + len;
break; break;
}
case 'd':
arg.enforce(!arg.basePrefix,
"base prefix not allowed with '", presentation,
"' specifier");
valBufBegin = valBuf + 3; // room for sign and base prefix
// Use uintToBuffer, faster than sprintf
valBufEnd = valBufBegin + uint64ToBufferUnsafe(uval, valBufBegin);
if (arg.thousandsSeparator) {
detail::insertThousandsGroupingUnsafe(valBufBegin, &valBufEnd);
}
break;
case 'c':
arg.enforce(!arg.basePrefix,
"base prefix not allowed with '", presentation,
"' specifier");
arg.enforce(!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation, "' specifier");
valBufBegin = valBuf + 3;
*valBufBegin = static_cast<char>(uval);
valBufEnd = valBufBegin + 1;
break;
case 'o':
case 'O':
arg.enforce(!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation, "' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin = valBuf + detail::uintToOctal(valBuf, valBufSize - 1, uval);
if (arg.basePrefix) {
*--valBufBegin = '0';
prefixLen = 1;
}
break;
case 'x':
arg.enforce(!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation, "' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin = valBuf + detail::uintToHexLower(valBuf, valBufSize - 1,
uval);
if (arg.basePrefix) {
*--valBufBegin = 'x';
*--valBufBegin = '0';
prefixLen = 2;
}
break;
case 'X':
arg.enforce(!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation, "' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin = valBuf + detail::uintToHexUpper(valBuf, valBufSize - 1,
uval);
if (arg.basePrefix) {
*--valBufBegin = 'X';
*--valBufBegin = '0';
prefixLen = 2;
}
break;
case 'b':
case 'B':
arg.enforce(!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation, "' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin = valBuf + detail::uintToBinary(valBuf, valBufSize - 1,
uval);
if (arg.basePrefix) {
*--valBufBegin = presentation; // 0b or 0B
*--valBufBegin = '0';
prefixLen = 2;
} }
break; case 'd':
default: arg.enforce(
arg.error("invalid specifier '", presentation, "'"); !arg.basePrefix,
"base prefix not allowed with '",
presentation,
"' specifier");
valBufBegin = valBuf + 3; // room for sign and base prefix
// Use uintToBuffer, faster than sprintf
valBufEnd = valBufBegin + uint64ToBufferUnsafe(uval, valBufBegin);
if (arg.thousandsSeparator) {
detail::insertThousandsGroupingUnsafe(valBufBegin, &valBufEnd);
}
break;
case 'c':
arg.enforce(
!arg.basePrefix,
"base prefix not allowed with '",
presentation,
"' specifier");
arg.enforce(
!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation,
"' specifier");
valBufBegin = valBuf + 3;
*valBufBegin = static_cast<char>(uval);
valBufEnd = valBufBegin + 1;
break;
case 'o':
case 'O':
arg.enforce(
!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation,
"' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin =
valBuf + detail::uintToOctal(valBuf, valBufSize - 1, uval);
if (arg.basePrefix) {
*--valBufBegin = '0';
prefixLen = 1;
}
break;
case 'x':
arg.enforce(
!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation,
"' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin =
valBuf + detail::uintToHexLower(valBuf, valBufSize - 1, uval);
if (arg.basePrefix) {
*--valBufBegin = 'x';
*--valBufBegin = '0';
prefixLen = 2;
}
break;
case 'X':
arg.enforce(
!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation,
"' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin =
valBuf + detail::uintToHexUpper(valBuf, valBufSize - 1, uval);
if (arg.basePrefix) {
*--valBufBegin = 'X';
*--valBufBegin = '0';
prefixLen = 2;
}
break;
case 'b':
case 'B':
arg.enforce(
!arg.thousandsSeparator,
"thousands separator (',') not allowed with '",
presentation,
"' specifier");
valBufEnd = valBuf + valBufSize - 1;
valBufBegin =
valBuf + detail::uintToBinary(valBuf, valBufSize - 1, uval);
if (arg.basePrefix) {
*--valBufBegin = presentation; // 0b or 0B
*--valBufBegin = '0';
prefixLen = 2;
}
break;
default:
arg.error("invalid specifier '", presentation, "'");
} }
if (sign) { if (sign) {
...@@ -592,8 +625,8 @@ class FormatValue< ...@@ -592,8 +625,8 @@ class FormatValue<
++prefixLen; ++prefixLen;
} }
format_value::formatNumber(StringPiece(valBufBegin, valBufEnd), prefixLen, format_value::formatNumber(
arg, cb); StringPiece(valBufBegin, valBufEnd), prefixLen, arg, cb);
} }
private: private:
...@@ -604,14 +637,14 @@ class FormatValue< ...@@ -604,14 +637,14 @@ class FormatValue<
template <> template <>
class FormatValue<bool> { class FormatValue<bool> {
public: public:
explicit FormatValue(bool val) : val_(val) { } explicit FormatValue(bool val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
if (arg.presentation == FormatArg::kDefaultPresentation) { if (arg.presentation == FormatArg::kDefaultPresentation) {
arg.validate(FormatArg::Type::OTHER); arg.validate(FormatArg::Type::OTHER);
format_value::formatString(val_ ? "true" : "false", arg, cb); format_value::formatString(val_ ? "true" : "false", arg, cb);
} else { // number } else { // number
FormatValue<int>(val_).format(arg, cb); FormatValue<int>(val_).format(arg, cb);
} }
} }
...@@ -624,7 +657,7 @@ class FormatValue<bool> { ...@@ -624,7 +657,7 @@ class FormatValue<bool> {
template <> template <>
class FormatValue<double> { class FormatValue<double> {
public: public:
explicit FormatValue(double val) : val_(val) { } explicit FormatValue(double val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
...@@ -644,7 +677,7 @@ class FormatValue<double> { ...@@ -644,7 +677,7 @@ class FormatValue<double> {
template <> template <>
class FormatValue<float> { class FormatValue<float> {
public: public:
explicit FormatValue(float val) : val_(val) { } explicit FormatValue(float val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
...@@ -658,22 +691,27 @@ class FormatValue<float> { ...@@ -658,22 +691,27 @@ class FormatValue<float> {
// Sring-y types (implicitly convertible to StringPiece, except char*) // Sring-y types (implicitly convertible to StringPiece, except char*)
template <class T> template <class T>
class FormatValue< class FormatValue<
T, typename std::enable_if< T,
(!std::is_pointer<T>::value || typename std::enable_if<
!std::is_same<char, typename std::decay< (!std::is_pointer<T>::value ||
typename std::remove_pointer<T>::type>::type>::value) && !std::is_same<
std::is_convertible<T, StringPiece>::value>::type> char,
{ typename std::decay<typename std::remove_pointer<T>::type>::type>::
value) &&
std::is_convertible<T, StringPiece>::value>::type> {
public: public:
explicit FormatValue(StringPiece val) : val_(val) { } explicit FormatValue(StringPiece val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
if (arg.keyEmpty()) { if (arg.keyEmpty()) {
arg.validate(FormatArg::Type::OTHER); arg.validate(FormatArg::Type::OTHER);
arg.enforce(arg.presentation == FormatArg::kDefaultPresentation || arg.enforce(
arg.presentation == 's', arg.presentation == FormatArg::kDefaultPresentation ||
"invalid specifier '", arg.presentation, "'"); arg.presentation == 's',
"invalid specifier '",
arg.presentation,
"'");
format_value::formatString(val_, arg, cb); format_value::formatString(val_, arg, cb);
} else { } else {
FormatValue<char>(val_.at(size_t(arg.splitIntKey()))).format(arg, cb); FormatValue<char>(val_.at(size_t(arg.splitIntKey()))).format(arg, cb);
...@@ -688,13 +726,16 @@ class FormatValue< ...@@ -688,13 +726,16 @@ class FormatValue<
template <> template <>
class FormatValue<std::nullptr_t> { class FormatValue<std::nullptr_t> {
public: public:
explicit FormatValue(std::nullptr_t) { } explicit FormatValue(std::nullptr_t) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
arg.validate(FormatArg::Type::OTHER); arg.validate(FormatArg::Type::OTHER);
arg.enforce(arg.presentation == FormatArg::kDefaultPresentation, arg.enforce(
"invalid specifier '", arg.presentation, "'"); arg.presentation == FormatArg::kDefaultPresentation,
"invalid specifier '",
arg.presentation,
"'");
format_value::formatString("(null)", arg, cb); format_value::formatString("(null)", arg, cb);
} }
}; };
...@@ -702,12 +743,11 @@ class FormatValue<std::nullptr_t> { ...@@ -702,12 +743,11 @@ class FormatValue<std::nullptr_t> {
// Partial specialization of FormatValue for char* // Partial specialization of FormatValue for char*
template <class T> template <class T>
class FormatValue< class FormatValue<
T*, T*,
typename std::enable_if< typename std::enable_if<
std::is_same<char, typename std::decay<T>::type>::value>::type> std::is_same<char, typename std::decay<T>::type>::value>::type> {
{
public: public:
explicit FormatValue(T* val) : val_(val) { } explicit FormatValue(T* val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
...@@ -718,8 +758,8 @@ class FormatValue< ...@@ -718,8 +758,8 @@ class FormatValue<
FormatValue<StringPiece>(val_).format(arg, cb); FormatValue<StringPiece>(val_).format(arg, cb);
} }
} else { } else {
FormatValue<typename std::decay<T>::type>( FormatValue<typename std::decay<T>::type>(val_[arg.splitIntKey()])
val_[arg.splitIntKey()]).format(arg, cb); .format(arg, cb);
} }
} }
...@@ -730,12 +770,11 @@ class FormatValue< ...@@ -730,12 +770,11 @@ class FormatValue<
// Partial specialization of FormatValue for void* // Partial specialization of FormatValue for void*
template <class T> template <class T>
class FormatValue< class FormatValue<
T*, T*,
typename std::enable_if< typename std::enable_if<
std::is_same<void, typename std::decay<T>::type>::value>::type> std::is_same<void, typename std::decay<T>::type>::value>::type> {
{
public: public:
explicit FormatValue(T* val) : val_(val) { } explicit FormatValue(T* val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
...@@ -744,15 +783,18 @@ class FormatValue< ...@@ -744,15 +783,18 @@ class FormatValue<
} else { } else {
// Print as a pointer, in hex. // Print as a pointer, in hex.
arg.validate(FormatArg::Type::OTHER); arg.validate(FormatArg::Type::OTHER);
arg.enforce(arg.presentation == FormatArg::kDefaultPresentation, arg.enforce(
"invalid specifier '", arg.presentation, "'"); arg.presentation == FormatArg::kDefaultPresentation,
"invalid specifier '",
arg.presentation,
"'");
arg.basePrefix = true; arg.basePrefix = true;
arg.presentation = 'x'; arg.presentation = 'x';
if (arg.align == FormatArg::Align::DEFAULT) { if (arg.align == FormatArg::Align::DEFAULT) {
arg.align = FormatArg::Align::LEFT; arg.align = FormatArg::Align::LEFT;
} }
FormatValue<uintptr_t>( FormatValue<uintptr_t>(reinterpret_cast<uintptr_t>(val_))
reinterpret_cast<uintptr_t>(val_)).doFormat(arg, cb); .doFormat(arg, cb);
} }
} }
...@@ -764,19 +806,17 @@ template <class T, class = void> ...@@ -764,19 +806,17 @@ template <class T, class = void>
class TryFormatValue { class TryFormatValue {
public: public:
template <class FormatCallback> template <class FormatCallback>
static void formatOrFail(T& /* value */, static void
FormatArg& arg, formatOrFail(T& /* value */, FormatArg& arg, FormatCallback& /* cb */) {
FormatCallback& /* cb */) {
arg.error("No formatter available for this type"); arg.error("No formatter available for this type");
} }
}; };
template <class T> template <class T>
class TryFormatValue< class TryFormatValue<
T, T,
typename std::enable_if< typename std::enable_if<
0 < sizeof(FormatValue<typename std::decay<T>::type>)>::type> 0 < sizeof(FormatValue<typename std::decay<T>::type>)>::type> {
{
public: public:
template <class FormatCallback> template <class FormatCallback>
static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) { static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
...@@ -787,13 +827,12 @@ class TryFormatValue< ...@@ -787,13 +827,12 @@ class TryFormatValue<
// Partial specialization of FormatValue for other pointers // Partial specialization of FormatValue for other pointers
template <class T> template <class T>
class FormatValue< class FormatValue<
T*, T*,
typename std::enable_if< typename std::enable_if<
!std::is_same<char, typename std::decay<T>::type>::value && !std::is_same<char, typename std::decay<T>::type>::value &&
!std::is_same<void, typename std::decay<T>::type>::value>::type> !std::is_same<void, typename std::decay<T>::type>::value>::type> {
{
public: public:
explicit FormatValue(T* val) : val_(val) { } explicit FormatValue(T* val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
...@@ -803,6 +842,7 @@ class FormatValue< ...@@ -803,6 +842,7 @@ class FormatValue<
TryFormatValue<T>::formatOrFail(val_[arg.splitIntKey()], arg, cb); TryFormatValue<T>::formatOrFail(val_[arg.splitIntKey()], arg, cb);
} }
} }
private: private:
T* val_; T* val_;
}; };
...@@ -812,53 +852,46 @@ namespace detail { ...@@ -812,53 +852,46 @@ namespace detail {
// std::array // std::array
template <class T, size_t N> template <class T, size_t N>
struct IndexableTraits<std::array<T, N>> struct IndexableTraits<std::array<T, N>>
: public IndexableTraitsSeq<std::array<T, N>> { : public IndexableTraitsSeq<std::array<T, N>> {};
};
// std::vector // std::vector
template <class T, class A> template <class T, class A>
struct IndexableTraits<std::vector<T, A>> struct IndexableTraits<std::vector<T, A>>
: public IndexableTraitsSeq<std::vector<T, A>> { : public IndexableTraitsSeq<std::vector<T, A>> {};
};
// std::deque // std::deque
template <class T, class A> template <class T, class A>
struct IndexableTraits<std::deque<T, A>> struct IndexableTraits<std::deque<T, A>>
: public IndexableTraitsSeq<std::deque<T, A>> { : public IndexableTraitsSeq<std::deque<T, A>> {};
};
// std::map with integral keys // std::map with integral keys
template <class K, class T, class C, class A> template <class K, class T, class C, class A>
struct IndexableTraits< struct IndexableTraits<
std::map<K, T, C, A>, std::map<K, T, C, A>,
typename std::enable_if<std::is_integral<K>::value>::type> typename std::enable_if<std::is_integral<K>::value>::type>
: public IndexableTraitsAssoc<std::map<K, T, C, A>> { : public IndexableTraitsAssoc<std::map<K, T, C, A>> {};
};
// std::unordered_map with integral keys // std::unordered_map with integral keys
template <class K, class T, class H, class E, class A> template <class K, class T, class H, class E, class A>
struct IndexableTraits< struct IndexableTraits<
std::unordered_map<K, T, H, E, A>, std::unordered_map<K, T, H, E, A>,
typename std::enable_if<std::is_integral<K>::value>::type> typename std::enable_if<std::is_integral<K>::value>::type>
: public IndexableTraitsAssoc<std::unordered_map<K, T, H, E, A>> { : public IndexableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {};
};
} // namespace detail } // namespace detail
// Partial specialization of FormatValue for integer-indexable containers // Partial specialization of FormatValue for integer-indexable containers
template <class T> template <class T>
class FormatValue< class FormatValue<T, typename detail::IndexableTraits<T>::enabled> {
T,
typename detail::IndexableTraits<T>::enabled> {
public: public:
explicit FormatValue(const T& val) : val_(val) { } explicit FormatValue(const T& val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
FormatValue<typename std::decay< FormatValue<typename std::decay<
typename detail::IndexableTraits<T>::value_type>::type>( typename detail::IndexableTraits<T>::value_type>::type>(
detail::IndexableTraits<T>::at( detail::IndexableTraits<T>::at(val_, arg.splitIntKey()))
val_, arg.splitIntKey())).format(arg, cb); .format(arg, cb);
} }
private: private:
...@@ -867,20 +900,19 @@ class FormatValue< ...@@ -867,20 +900,19 @@ class FormatValue<
template <class Container, class Value> template <class Container, class Value>
class FormatValue< class FormatValue<
detail::DefaultValueWrapper<Container, Value>, detail::DefaultValueWrapper<Container, Value>,
typename detail::IndexableTraits<Container>::enabled> { typename detail::IndexableTraits<Container>::enabled> {
public: public:
explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val) explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
: val_(val) { } : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
FormatValue<typename std::decay< FormatValue<typename std::decay<
typename detail::IndexableTraits<Container>::value_type>::type>( typename detail::IndexableTraits<Container>::value_type>::type>(
detail::IndexableTraits<Container>::at( detail::IndexableTraits<Container>::at(
val_.container, val_.container, arg.splitIntKey(), val_.defaultValue))
arg.splitIntKey(), .format(arg, cb);
val_.defaultValue)).format(arg, cb);
} }
private: private:
...@@ -891,7 +923,8 @@ namespace detail { ...@@ -891,7 +923,8 @@ namespace detail {
// Define enabled, key_type, convert from StringPiece to the key types // Define enabled, key_type, convert from StringPiece to the key types
// that we support // that we support
template <class T> struct KeyFromStringPiece; template <class T>
struct KeyFromStringPiece;
// std::string // std::string
template <> template <>
...@@ -922,14 +955,15 @@ struct KeyFromStringPiece<StringPiece> : public FormatTraitsBase { ...@@ -922,14 +955,15 @@ struct KeyFromStringPiece<StringPiece> : public FormatTraitsBase {
}; };
// Base class for associative types keyed by strings // Base class for associative types keyed by strings
template <class T> struct KeyableTraitsAssoc : public FormatTraitsBase { template <class T>
struct KeyableTraitsAssoc : public FormatTraitsBase {
typedef typename T::key_type key_type; typedef typename T::key_type key_type;
typedef typename T::value_type::second_type value_type; typedef typename T::value_type::second_type value_type;
static const value_type& at(const T& map, StringPiece key) { static const value_type& at(const T& map, StringPiece key) {
return map.at(KeyFromStringPiece<key_type>::convert(key)); return map.at(KeyFromStringPiece<key_type>::convert(key));
} }
static const value_type& at(const T& map, StringPiece key, static const value_type&
const value_type& dflt) { at(const T& map, StringPiece key, const value_type& dflt) {
auto pos = map.find(KeyFromStringPiece<key_type>::convert(key)); auto pos = map.find(KeyFromStringPiece<key_type>::convert(key));
return pos != map.end() ? pos->second : dflt; return pos != map.end() ? pos->second : dflt;
} }
...@@ -937,40 +971,37 @@ template <class T> struct KeyableTraitsAssoc : public FormatTraitsBase { ...@@ -937,40 +971,37 @@ template <class T> struct KeyableTraitsAssoc : public FormatTraitsBase {
// Define enabled, key_type, value_type, at() for supported string-keyed // Define enabled, key_type, value_type, at() for supported string-keyed
// types // types
template <class T, class Enabled=void> struct KeyableTraits; template <class T, class Enabled = void>
struct KeyableTraits;
// std::map with string key // std::map with string key
template <class K, class T, class C, class A> template <class K, class T, class C, class A>
struct KeyableTraits< struct KeyableTraits<
std::map<K, T, C, A>, std::map<K, T, C, A>,
typename KeyFromStringPiece<K>::enabled> typename KeyFromStringPiece<K>::enabled>
: public KeyableTraitsAssoc<std::map<K, T, C, A>> { : public KeyableTraitsAssoc<std::map<K, T, C, A>> {};
};
// std::unordered_map with string key // std::unordered_map with string key
template <class K, class T, class H, class E, class A> template <class K, class T, class H, class E, class A>
struct KeyableTraits< struct KeyableTraits<
std::unordered_map<K, T, H, E, A>, std::unordered_map<K, T, H, E, A>,
typename KeyFromStringPiece<K>::enabled> typename KeyFromStringPiece<K>::enabled>
: public KeyableTraitsAssoc<std::unordered_map<K, T, H, E, A>> { : public KeyableTraitsAssoc<std::unordered_map<K, T, H, E, A>> {};
};
} // namespace detail } // namespace detail
// Partial specialization of FormatValue for string-keyed containers // Partial specialization of FormatValue for string-keyed containers
template <class T> template <class T>
class FormatValue< class FormatValue<T, typename detail::KeyableTraits<T>::enabled> {
T,
typename detail::KeyableTraits<T>::enabled> {
public: public:
explicit FormatValue(const T& val) : val_(val) { } explicit FormatValue(const T& val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
FormatValue<typename std::decay< FormatValue<typename std::decay<
typename detail::KeyableTraits<T>::value_type>::type>( typename detail::KeyableTraits<T>::value_type>::type>(
detail::KeyableTraits<T>::at( detail::KeyableTraits<T>::at(val_, arg.splitKey()))
val_, arg.splitKey())).format(arg, cb); .format(arg, cb);
} }
private: private:
...@@ -979,20 +1010,19 @@ class FormatValue< ...@@ -979,20 +1010,19 @@ class FormatValue<
template <class Container, class Value> template <class Container, class Value>
class FormatValue< class FormatValue<
detail::DefaultValueWrapper<Container, Value>, detail::DefaultValueWrapper<Container, Value>,
typename detail::KeyableTraits<Container>::enabled> { typename detail::KeyableTraits<Container>::enabled> {
public: public:
explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val) explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
: val_(val) { } : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
FormatValue<typename std::decay< FormatValue<typename std::decay<
typename detail::KeyableTraits<Container>::value_type>::type>( typename detail::KeyableTraits<Container>::value_type>::type>(
detail::KeyableTraits<Container>::at( detail::KeyableTraits<Container>::at(
val_.container, val_.container, arg.splitKey(), val_.defaultValue))
arg.splitKey(), .format(arg, cb);
val_.defaultValue)).format(arg, cb);
} }
private: private:
...@@ -1003,20 +1033,20 @@ class FormatValue< ...@@ -1003,20 +1033,20 @@ class FormatValue<
template <class A, class B> template <class A, class B>
class FormatValue<std::pair<A, B>> { class FormatValue<std::pair<A, B>> {
public: public:
explicit FormatValue(const std::pair<A, B>& val) : val_(val) { } explicit FormatValue(const std::pair<A, B>& val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
int key = arg.splitIntKey(); int key = arg.splitIntKey();
switch (key) { switch (key) {
case 0: case 0:
FormatValue<typename std::decay<A>::type>(val_.first).format(arg, cb); FormatValue<typename std::decay<A>::type>(val_.first).format(arg, cb);
break; break;
case 1: case 1:
FormatValue<typename std::decay<B>::type>(val_.second).format(arg, cb); FormatValue<typename std::decay<B>::type>(val_.second).format(arg, cb);
break; break;
default: default:
arg.error("invalid index for pair"); arg.error("invalid index for pair");
} }
} }
...@@ -1028,8 +1058,9 @@ class FormatValue<std::pair<A, B>> { ...@@ -1028,8 +1058,9 @@ class FormatValue<std::pair<A, B>> {
template <class... Args> template <class... Args>
class FormatValue<std::tuple<Args...>> { class FormatValue<std::tuple<Args...>> {
typedef std::tuple<Args...> Tuple; typedef std::tuple<Args...> Tuple;
public: public:
explicit FormatValue(const Tuple& val) : val_(val) { } explicit FormatValue(const Tuple& val) : val_(val) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
...@@ -1042,8 +1073,8 @@ class FormatValue<std::tuple<Args...>> { ...@@ -1042,8 +1073,8 @@ class FormatValue<std::tuple<Args...>> {
static constexpr size_t valueCount = std::tuple_size<Tuple>::value; static constexpr size_t valueCount = std::tuple_size<Tuple>::value;
template <size_t K, class Callback> template <size_t K, class Callback>
typename std::enable_if<K == valueCount>::type doFormatFrom( typename std::enable_if<K == valueCount>::type
size_t i, FormatArg& arg, Callback& /* cb */) const { doFormatFrom(size_t i, FormatArg& arg, Callback& /* cb */) const {
arg.enforce("tuple index out of range, max=", i); arg.enforce("tuple index out of range, max=", i);
} }
...@@ -1052,10 +1083,10 @@ class FormatValue<std::tuple<Args...>> { ...@@ -1052,10 +1083,10 @@ class FormatValue<std::tuple<Args...>> {
doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const { doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
if (i == K) { if (i == K) {
FormatValue<typename std::decay< FormatValue<typename std::decay<
typename std::tuple_element<K, Tuple>::type>::type>( typename std::tuple_element<K, Tuple>::type>::type>(std::get<K>(val_))
std::get<K>(val_)).format(arg, cb); .format(arg, cb);
} else { } else {
doFormatFrom<K+1>(i, arg, cb); doFormatFrom<K + 1>(i, arg, cb);
} }
} }
...@@ -1068,20 +1099,21 @@ class FormatValue<std::tuple<Args...>> { ...@@ -1068,20 +1099,21 @@ class FormatValue<std::tuple<Args...>> {
}; };
// Partial specialization of FormatValue for nested Formatters // Partial specialization of FormatValue for nested Formatters
template <bool containerMode, class... Args, template <bool containerMode, class... Args, template <bool, class...> class F>
template <bool, class...> class F> class FormatValue<
class FormatValue<F<containerMode, Args...>, F<containerMode, Args...>,
typename std::enable_if<detail::IsFormatter< typename std::enable_if<
F<containerMode, Args...>>::value>::type> { detail::IsFormatter<F<containerMode, Args...>>::value>::type> {
typedef typename F<containerMode, Args...>::BaseType FormatterValue; typedef typename F<containerMode, Args...>::BaseType FormatterValue;
public: public:
explicit FormatValue(const FormatterValue& f) : f_(f) { } explicit FormatValue(const FormatterValue& f) : f_(f) {}
template <class FormatCallback> template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const { void format(FormatArg& arg, FormatCallback& cb) const {
format_value::formatFormatter(f_, arg, cb); format_value::formatFormatter(f_, arg, cb);
} }
private: private:
const FormatterValue& f_; const FormatterValue& f_;
}; };
...@@ -1092,10 +1124,11 @@ class FormatValue<F<containerMode, Args...>, ...@@ -1092,10 +1124,11 @@ class FormatValue<F<containerMode, Args...>,
*/ */
template <class Tgt, class Derived, bool containerMode, class... Args> template <class Tgt, class Derived, bool containerMode, class... Args>
typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend( typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
const BaseFormatter<Derived, containerMode, Args...>& value, Tgt* result) { const BaseFormatter<Derived, containerMode, Args...>& value,
Tgt* result) {
value.appendTo(*result); value.appendTo(*result);
} }
} // namespace folly } // namespace folly
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include <type_traits> #include <type_traits>
#include <folly/Conv.h> #include <folly/Conv.h>
#include <folly/FormatArg.h>
#include <folly/Range.h> #include <folly/Range.h>
#include <folly/Traits.h>
#include <folly/String.h> #include <folly/String.h>
#include <folly/FormatArg.h> #include <folly/Traits.h>
// Ignore shadowing warnings within this file, so includers can use -Wshadow. // Ignore shadowing warnings within this file, so includers can use -Wshadow.
#pragma GCC diagnostic push #pragma GCC diagnostic push
...@@ -34,12 +34,14 @@ ...@@ -34,12 +34,14 @@
namespace folly { namespace folly {
// forward declarations // forward declarations
template <bool containerMode, class... Args> class Formatter; template <bool containerMode, class... Args>
class Formatter;
template <class... Args> template <class... Args>
Formatter<false, Args...> format(StringPiece fmt, Args&&... args); Formatter<false, Args...> format(StringPiece fmt, Args&&... args);
template <class C> template <class C>
Formatter<true, C> vformat(StringPiece fmt, C&& container); Formatter<true, C> vformat(StringPiece fmt, C&& container);
template <class T, class Enable=void> class FormatValue; template <class T, class Enable = void>
class FormatValue;
// meta-attribute to identify formatters in this sea of template weirdness // meta-attribute to identify formatters in this sea of template weirdness
namespace detail { namespace detail {
...@@ -71,9 +73,9 @@ class BaseFormatter { ...@@ -71,9 +73,9 @@ class BaseFormatter {
* Append to a string. * Append to a string.
*/ */
template <class Str> template <class Str>
typename std::enable_if<IsSomeString<Str>::value>::type typename std::enable_if<IsSomeString<Str>::value>::type appendTo(
appendTo(Str& str) const { Str& str) const {
auto appender = [&str] (StringPiece s) { str.append(s.data(), s.size()); }; auto appender = [&str](StringPiece s) { str.append(s.data(), s.size()); };
(*this)(appender); (*this)(appender);
} }
...@@ -102,8 +104,8 @@ class BaseFormatter { ...@@ -102,8 +104,8 @@ class BaseFormatter {
typedef BaseFormatter BaseType; typedef BaseFormatter BaseType;
private: private:
typedef std::tuple<FormatValue< typedef std::tuple<FormatValue<typename std::decay<Args>::type>...>
typename std::decay<Args>::type>...> ValueTuple; ValueTuple;
static constexpr size_t valueCount = std::tuple_size<ValueTuple>::value; static constexpr size_t valueCount = std::tuple_size<ValueTuple>::value;
template <size_t K, class Callback> template <size_t K, class Callback>
...@@ -118,7 +120,7 @@ class BaseFormatter { ...@@ -118,7 +120,7 @@ class BaseFormatter {
if (i == K) { if (i == K) {
static_cast<const Derived*>(this)->template doFormatArg<K>(arg, cb); static_cast<const Derived*>(this)->template doFormatArg<K>(arg, cb);
} else { } else {
doFormatFrom<K+1>(i, arg, cb); doFormatFrom<K + 1>(i, arg, cb);
} }
} }
...@@ -128,32 +130,36 @@ class BaseFormatter { ...@@ -128,32 +130,36 @@ class BaseFormatter {
} }
template <size_t K> template <size_t K>
typename std::enable_if<K == valueCount, int>::type typename std::enable_if<K == valueCount, int>::type getSizeArgFrom(
getSizeArgFrom(size_t i, const FormatArg& arg) const { size_t i,
const FormatArg& arg) const {
arg.error("argument index out of range, max=", i); arg.error("argument index out of range, max=", i);
} }
template <class T> template <class T>
typename std::enable_if<std::is_integral<T>::value && typename std::enable_if<
!std::is_same<T, bool>::value, int>::type std::is_integral<T>::value && !std::is_same<T, bool>::value,
int>::type
getValue(const FormatValue<T>& format, const FormatArg&) const { getValue(const FormatValue<T>& format, const FormatArg&) const {
return static_cast<int>(format.getValue()); return static_cast<int>(format.getValue());
} }
template <class T> template <class T>
typename std::enable_if<!std::is_integral<T>::value || typename std::enable_if<
std::is_same<T, bool>::value, int>::type !std::is_integral<T>::value || std::is_same<T, bool>::value,
int>::type
getValue(const FormatValue<T>&, const FormatArg& arg) const { getValue(const FormatValue<T>&, const FormatArg& arg) const {
arg.error("dynamic field width argument must be integral"); arg.error("dynamic field width argument must be integral");
} }
template <size_t K> template <size_t K>
typename std::enable_if<K < valueCount, int>::type typename std::enable_if <
getSizeArgFrom(size_t i, const FormatArg& arg) const { K<valueCount, int>::type getSizeArgFrom(size_t i, const FormatArg& arg)
const {
if (i == K) { if (i == K) {
return getValue(std::get<K>(values_), arg); return getValue(std::get<K>(values_), arg);
} }
return getSizeArgFrom<K+1>(i, arg); return getSizeArgFrom<K + 1>(i, arg);
} }
int getSizeArg(size_t i, const FormatArg& arg) const { int getSizeArg(size_t i, const FormatArg& arg) const {
...@@ -181,23 +187,26 @@ class BaseFormatter { ...@@ -181,23 +187,26 @@ class BaseFormatter {
}; };
template <bool containerMode, class... Args> template <bool containerMode, class... Args>
class Formatter : public BaseFormatter<Formatter<containerMode, Args...>, class Formatter : public BaseFormatter<
containerMode, Formatter<containerMode, Args...>,
Args...> { containerMode,
Args...> {
private: private:
explicit Formatter(StringPiece& str, Args&&... args) explicit Formatter(StringPiece& str, Args&&... args)
: BaseFormatter<Formatter<containerMode, Args...>, : BaseFormatter<
containerMode, Formatter<containerMode, Args...>,
Args...>(str, std::forward<Args>(args)...) {} containerMode,
Args...>(str, std::forward<Args>(args)...) {}
template <size_t K, class Callback> template <size_t K, class Callback>
void doFormatArg(FormatArg& arg, Callback& cb) const { void doFormatArg(FormatArg& arg, Callback& cb) const {
std::get<K>(this->values_).format(arg, cb); std::get<K>(this->values_).format(arg, cb);
} }
friend class BaseFormatter<Formatter<containerMode, Args...>, friend class BaseFormatter<
containerMode, Formatter<containerMode, Args...>,
Args...>; containerMode,
Args...>;
template <class... A> template <class... A>
friend Formatter<false, A...> format(StringPiece fmt, A&&... arg); friend Formatter<false, A...> format(StringPiece fmt, A&&... arg);
...@@ -208,9 +217,10 @@ class Formatter : public BaseFormatter<Formatter<containerMode, Args...>, ...@@ -208,9 +217,10 @@ class Formatter : public BaseFormatter<Formatter<containerMode, Args...>,
/** /**
* Formatter objects can be written to streams. * Formatter objects can be written to streams.
*/ */
template<bool containerMode, class... Args> template <bool containerMode, class... Args>
std::ostream& operator<<(std::ostream& out, std::ostream& operator<<(
const Formatter<containerMode, Args...>& formatter) { std::ostream& out,
const Formatter<containerMode, Args...>& formatter) {
auto writer = [&out](StringPiece sp) { auto writer = [&out](StringPiece sp) {
out.write(sp.data(), std::streamsize(sp.size())); out.write(sp.data(), std::streamsize(sp.size()));
}; };
...@@ -222,8 +232,9 @@ std::ostream& operator<<(std::ostream& out, ...@@ -222,8 +232,9 @@ std::ostream& operator<<(std::ostream& out,
* Formatter objects can be written to stdio FILEs. * Formatter objects can be written to stdio FILEs.
*/ */
template <class Derived, bool containerMode, class... Args> template <class Derived, bool containerMode, class... Args>
void writeTo(FILE* fp, void writeTo(
const BaseFormatter<Derived, containerMode, Args...>& formatter); FILE* fp,
const BaseFormatter<Derived, containerMode, Args...>& formatter);
/** /**
* Create a formatter object. * Create a formatter object.
...@@ -234,8 +245,7 @@ void writeTo(FILE* fp, ...@@ -234,8 +245,7 @@ void writeTo(FILE* fp,
*/ */
template <class... Args> template <class... Args>
Formatter<false, Args...> format(StringPiece fmt, Args&&... args) { Formatter<false, Args...> format(StringPiece fmt, Args&&... args) {
return Formatter<false, Args...>( return Formatter<false, Args...>(fmt, std::forward<Args>(args)...);
fmt, std::forward<Args>(args)...);
} }
/** /**
...@@ -262,8 +272,7 @@ inline std::string sformat(StringPiece fmt, Args&&... args) { ...@@ -262,8 +272,7 @@ inline std::string sformat(StringPiece fmt, Args&&... args) {
*/ */
template <class Container> template <class Container>
Formatter<true, Container> vformat(StringPiece fmt, Container&& container) { Formatter<true, Container> vformat(StringPiece fmt, Container&& container) {
return Formatter<true, Container>( return Formatter<true, Container>(fmt, std::forward<Container>(container));
fmt, std::forward<Container>(container));
} }
/** /**
...@@ -283,20 +292,20 @@ inline std::string svformat(StringPiece fmt, Container&& container) { ...@@ -283,20 +292,20 @@ inline std::string svformat(StringPiece fmt, Container&& container) {
* format("[no_such_key"], defaulted(map, 42)) -> 42 * format("[no_such_key"], defaulted(map, 42)) -> 42
*/ */
namespace detail { namespace detail {
template <class Container, class Value> struct DefaultValueWrapper { template <class Container, class Value>
struct DefaultValueWrapper {
DefaultValueWrapper(const Container& container, const Value& defaultValue) DefaultValueWrapper(const Container& container, const Value& defaultValue)
: container(container), : container(container), defaultValue(defaultValue) {}
defaultValue(defaultValue) {
}
const Container& container; const Container& container;
const Value& defaultValue; const Value& defaultValue;
}; };
} // namespace } // namespace
template <class Container, class Value> template <class Container, class Value>
detail::DefaultValueWrapper<Container, Value> detail::DefaultValueWrapper<Container, Value> defaulted(
defaulted(const Container& c, const Value& v) { const Container& c,
const Value& v) {
return detail::DefaultValueWrapper<Container, Value>(c, v); return detail::DefaultValueWrapper<Container, Value>(c, v);
} }
...@@ -345,25 +354,28 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb); ...@@ -345,25 +354,28 @@ void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb);
* field width") * field width")
*/ */
template <class FormatCallback> template <class FormatCallback>
void formatNumber(StringPiece val, int prefixLen, FormatArg& arg, void formatNumber(
FormatCallback& cb); StringPiece val,
int prefixLen,
FormatArg& arg,
FormatCallback& cb);
/** /**
* Format a Formatter object recursively. Behaves just like * Format a Formatter object recursively. Behaves just like
* formatString(fmt.str(), arg, cb); but avoids creating a temporary * formatString(fmt.str(), arg, cb); but avoids creating a temporary
* string if possible. * string if possible.
*/ */
template <class FormatCallback, template <
class Derived, class FormatCallback,
bool containerMode, class Derived,
class... Args> bool containerMode,
class... Args>
void formatFormatter( void formatFormatter(
const BaseFormatter<Derived, containerMode, Args...>& formatter, const BaseFormatter<Derived, containerMode, Args...>& formatter,
FormatArg& arg, FormatArg& arg,
FormatCallback& cb); FormatCallback& cb);
} // namespace format_value } // namespace format_value
/* /*
* Specialize folly::FormatValue for your type. * Specialize folly::FormatValue for your type.
...@@ -411,8 +423,9 @@ inline std::string sformatChecked(StringPiece fmt, Args&&... args) { ...@@ -411,8 +423,9 @@ inline std::string sformatChecked(StringPiece fmt, Args&&... args) {
return formatChecked(fmt, std::forward<Args>(args)...).str(); return formatChecked(fmt, std::forward<Args>(args)...).str();
} }
template <class Container> template <class Container>
Formatter<true, Container> vformatChecked(StringPiece fmt, Formatter<true, Container> vformatChecked(
Container&& container) { StringPiece fmt,
Container&& container) {
return vformat(fmt, std::forward<Container>(container)); return vformat(fmt, std::forward<Container>(container));
} }
template <class Container> template <class Container>
...@@ -430,7 +443,7 @@ vformatChecked(Str* out, StringPiece fmt, Container&& container) { ...@@ -430,7 +443,7 @@ vformatChecked(Str* out, StringPiece fmt, Container&& container) {
vformatChecked(fmt, std::forward<Container>(container)).appendTo(*out); vformatChecked(fmt, std::forward<Container>(container)).appendTo(*out);
} }
} // namespace folly } // namespace folly
#include <folly/Format-inl.h> #include <folly/Format-inl.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment