X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2FFormat.cpp;h=9ad5395e8f04f507c4496c9ed046a26622680148;hb=da2c859c9c8ce594b8760aae290503e2a33cef7f;hp=b09152daf1f7b82533f162e33683086cad8e7f96;hpb=3b4d7b6a8e7c001af8ff7fc4a55229d58b2114db;p=folly.git diff --git a/folly/Format.cpp b/folly/Format.cpp index b09152da..9ad5395e 100644 --- a/folly/Format.cpp +++ b/folly/Format.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ #include +#include +#include + #include namespace folly { @@ -24,7 +27,7 @@ namespace detail { extern const FormatArg::Align formatAlignTable[]; extern const FormatArg::Sign formatSignTable[]; -} // namespace detail +} // namespace detail using namespace folly::detail; @@ -48,12 +51,14 @@ void FormatValue::formatHelper( } // 2+: for null terminator and optional sign shenanigans. - char buf[2 + std::max({ - (2 + DoubleToStringConverter::kMaxFixedDigitsBeforePoint + - DoubleToStringConverter::kMaxFixedDigitsAfterPoint), - (8 + DoubleToStringConverter::kMaxExponentialDigits), - (7 + DoubleToStringConverter::kMaxPrecisionDigits)})]; - StringBuilder builder(buf + 1, static_cast (sizeof(buf) - 1)); + constexpr int bufLen = + 2 + constexpr_max( + 2 + DoubleToStringConverter::kMaxFixedDigitsBeforePoint + + DoubleToStringConverter::kMaxFixedDigitsAfterPoint, + constexpr_max(8 + DoubleToStringConverter::kMaxExponentialDigits, + 7 + DoubleToStringConverter::kMaxPrecisionDigits)); + char buf[bufLen]; + StringBuilder builder(buf + 1, bufLen - 1); char plusSign; switch (arg.sign) { @@ -77,6 +82,7 @@ void FormatValue::formatHelper( switch (arg.presentation) { case '%': val *= 100; + FOLLY_FALLTHROUGH; case 'f': case 'F': { @@ -155,7 +161,7 @@ void FormatValue::formatHelper( prefixLen = 1; } - piece = fbstring(p, len); + piece = fbstring(p, size_t(len)); } @@ -164,7 +170,7 @@ void FormatArg::initSlow() { auto end = fullArgString.end(); // Parse key - auto p = static_cast(memchr(b, ':', end - b)); + auto p = static_cast(memchr(b, ':', size_t(end - b))); if (!p) { key_ = StringPiece(b, end); return; @@ -173,7 +179,9 @@ void FormatArg::initSlow() { if (*p == ':') { // parse format spec - if (++p == end) return; + if (++p == end) { + return; + } // fill/align, or just align Align a; @@ -183,54 +191,87 @@ void FormatArg::initSlow() { fill = *p; align = a; p += 2; - if (p == end) return; + if (p == end) { + return; + } } else if ((a = formatAlignTable[static_cast(*p)]) != Align::INVALID) { align = a; - if (++p == end) return; + if (++p == end) { + return; + } } Sign s; unsigned char uSign = static_cast(*p); if ((s = formatSignTable[uSign]) != Sign::INVALID) { sign = s; - if (++p == end) return; + if (++p == end) { + return; + } } if (*p == '#') { basePrefix = true; - if (++p == end) return; + if (++p == end) { + return; + } } if (*p == '0') { enforce(align == Align::DEFAULT, "alignment specified twice"); fill = '0'; align = Align::PAD_AFTER_SIGN; - if (++p == end) return; + if (++p == end) { + return; + } } - if (*p >= '0' && *p <= '9') { - auto b = p; + auto readInt = [&] { + auto const c = p; do { ++p; } while (p != end && *p >= '0' && *p <= '9'); - width = to(StringPiece(b, p)); + return to(StringPiece(c, p)); + }; + + if (*p == '*') { + width = kDynamicWidth; + ++p; + + if (p == end) { + return; + } + + if (*p >= '0' && *p <= '9') { + widthIndex = readInt(); + } - if (p == end) return; + if (p == end) { + return; + } + } else if (*p >= '0' && *p <= '9') { + width = readInt(); + + if (p == end) { + return; + } } if (*p == ',') { thousandsSeparator = true; - if (++p == end) return; + if (++p == end) { + return; + } } if (*p == '.') { - auto b = ++p; + auto d = ++p; while (p != end && *p >= '0' && *p <= '9') { ++p; } - if (p != b) { - precision = to(StringPiece(b, p)); + if (p != d) { + precision = to(StringPiece(d, p)); if (p != end && *p == '.') { trailingDot = true; ++p; @@ -239,11 +280,15 @@ void FormatArg::initSlow() { trailingDot = true; } - if (p == end) return; + if (p == end) { + return; + } } presentation = *p; - if (++p == end) return; + if (++p == end) { + return; + } } error("extra characters in format string"); @@ -277,7 +322,7 @@ void FormatArg::validate(Type type) const { namespace detail { void insertThousandsGroupingUnsafe(char* start_buffer, char** end_buffer) { - uint32_t remaining_digits = *end_buffer - start_buffer; + uint32_t remaining_digits = uint32_t(*end_buffer - start_buffer); uint32_t separator_size = (remaining_digits - 1) / 3; uint32_t result_size = remaining_digits + separator_size; *end_buffer = *end_buffer + separator_size; @@ -287,7 +332,6 @@ void insertThousandsGroupingUnsafe(char* start_buffer, char** end_buffer) { uint32_t buffer_read_index = remaining_digits - 1; start_buffer[buffer_write_index + 1] = 0; - uint32_t count = 0; bool done = false; uint32_t next_group_size = 3; @@ -310,6 +354,17 @@ void insertThousandsGroupingUnsafe(char* start_buffer, char** end_buffer) { remaining_digits -= current_group_size; } } -} // detail +} // namespace detail + +FormatKeyNotFoundException::FormatKeyNotFoundException(StringPiece key) + : std::out_of_range(kMessagePrefix.str() + key.str()) {} + +constexpr StringPiece const FormatKeyNotFoundException::kMessagePrefix; + +namespace detail { +[[noreturn]] void throwFormatKeyNotFoundException(StringPiece key) { + throw FormatKeyNotFoundException(key); +} +} // namespace detail -} // namespace folly +} // namespace folly