1// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5#include "util/logging.h"
6
7#include <cstdarg>
8#include <cstdio>
9#include <cstdlib>
10#include <limits>
11
12#include "leveldb/env.h"
13#include "leveldb/slice.h"
14
15namespace leveldb {
16
17void AppendNumberTo(std::string* str, uint64_t num) {
18 char buf[30];
19 std::snprintf(buf, sizeof(buf), "%llu", static_cast<unsigned long long>(num));
20 str->append(buf);
21}
22
23void AppendEscapedStringTo(std::string* str, const Slice& value) {
24 for (size_t i = 0; i < value.size(); i++) {
25 char c = value[i];
26 if (c >= ' ' && c <= '~') {
27 str->push_back(c);
28 } else {
29 char buf[10];
30 std::snprintf(buf, sizeof(buf), "\\x%02x",
31 static_cast<unsigned int>(c) & 0xff);
32 str->append(buf);
33 }
34 }
35}
36
37std::string NumberToString(uint64_t num) {
38 std::string r;
39 AppendNumberTo(&r, num);
40 return r;
41}
42
43std::string EscapeString(const Slice& value) {
44 std::string r;
45 AppendEscapedStringTo(&r, value);
46 return r;
47}
48
49bool ConsumeDecimalNumber(Slice* in, uint64_t* val) {
50 // Constants that will be optimized away.
51 constexpr const uint64_t kMaxUint64 = std::numeric_limits<uint64_t>::max();
52 constexpr const char kLastDigitOfMaxUint64 =
53 '0' + static_cast<char>(kMaxUint64 % 10);
54
55 uint64_t value = 0;
56
57 // reinterpret_cast-ing from char* to uint8_t* to avoid signedness.
58 const uint8_t* start = reinterpret_cast<const uint8_t*>(in->data());
59
60 const uint8_t* end = start + in->size();
61 const uint8_t* current = start;
62 for (; current != end; ++current) {
63 const uint8_t ch = *current;
64 if (ch < '0' || ch > '9') break;
65
66 // Overflow check.
67 // kMaxUint64 / 10 is also constant and will be optimized away.
68 if (value > kMaxUint64 / 10 ||
69 (value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) {
70 return false;
71 }
72
73 value = (value * 10) + (ch - '0');
74 }
75
76 *val = value;
77 const size_t digits_consumed = current - start;
78 in->remove_prefix(digits_consumed);
79 return digits_consumed != 0;
80}
81
82} // namespace leveldb
83