diff options
Diffstat (limited to 'util/logging.cc')
-rw-r--r-- | util/logging.cc | 63 |
1 files changed, 36 insertions, 27 deletions
diff --git a/util/logging.cc b/util/logging.cc index d48b6dd..8d6fb5b 100644 --- a/util/logging.cc +++ b/util/logging.cc @@ -4,10 +4,11 @@ #include "util/logging.h" -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> +#include <cstdarg> +#include <cstdio> +#include <cstdlib> +#include <limits> + #include "leveldb/env.h" #include "leveldb/slice.h" @@ -15,7 +16,7 @@ namespace leveldb { void AppendNumberTo(std::string* str, uint64_t num) { char buf[30]; - snprintf(buf, sizeof(buf), "%llu", (unsigned long long) num); + std::snprintf(buf, sizeof(buf), "%llu", static_cast<unsigned long long>(num)); str->append(buf); } @@ -26,8 +27,8 @@ void AppendEscapedStringTo(std::string* str, const Slice& value) { str->push_back(c); } else { char buf[10]; - snprintf(buf, sizeof(buf), "\\x%02x", - static_cast<unsigned int>(c) & 0xff); + std::snprintf(buf, sizeof(buf), "\\x%02x", + static_cast<unsigned int>(c) & 0xff); str->append(buf); } } @@ -46,28 +47,36 @@ std::string EscapeString(const Slice& value) { } bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { - uint64_t v = 0; - int digits = 0; - while (!in->empty()) { - char c = (*in)[0]; - if (c >= '0' && c <= '9') { - ++digits; - // |delta| intentionally unit64_t to avoid Android crash (see log). - const uint64_t delta = (c - '0'); - static const uint64_t kMaxUint64 = ~static_cast<uint64_t>(0); - if (v > kMaxUint64/10 || - (v == kMaxUint64/10 && delta > kMaxUint64%10)) { - // Overflow - return false; - } - v = (v * 10) + delta; - in->remove_prefix(1); - } else { - break; + // Constants that will be optimized away. + constexpr const uint64_t kMaxUint64 = std::numeric_limits<uint64_t>::max(); + constexpr const char kLastDigitOfMaxUint64 = + '0' + static_cast<char>(kMaxUint64 % 10); + + uint64_t value = 0; + + // reinterpret_cast-ing from char* to uint8_t* to avoid signedness. + const uint8_t* start = reinterpret_cast<const uint8_t*>(in->data()); + + const uint8_t* end = start + in->size(); + const uint8_t* current = start; + for (; current != end; ++current) { + const uint8_t ch = *current; + if (ch < '0' || ch > '9') break; + + // Overflow check. + // kMaxUint64 / 10 is also constant and will be optimized away. + if (value > kMaxUint64 / 10 || + (value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) { + return false; } + + value = (value * 10) + (ch - '0'); } - *val = v; - return (digits > 0); + + *val = value; + const size_t digits_consumed = current - start; + in->remove_prefix(digits_consumed); + return digits_consumed != 0; } } // namespace leveldb |