leveldb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/ext/Rakefile +11 -0
- data/ext/leveldb/LICENSE +27 -0
- data/ext/leveldb/Makefile +206 -0
- data/ext/leveldb/build_config.mk +13 -0
- data/ext/leveldb/db/builder.cc +88 -0
- data/ext/leveldb/db/builder.h +34 -0
- data/ext/leveldb/db/c.cc +595 -0
- data/ext/leveldb/db/c_test.c +390 -0
- data/ext/leveldb/db/corruption_test.cc +359 -0
- data/ext/leveldb/db/db_bench.cc +979 -0
- data/ext/leveldb/db/db_impl.cc +1485 -0
- data/ext/leveldb/db/db_impl.h +203 -0
- data/ext/leveldb/db/db_iter.cc +299 -0
- data/ext/leveldb/db/db_iter.h +26 -0
- data/ext/leveldb/db/db_test.cc +2092 -0
- data/ext/leveldb/db/dbformat.cc +140 -0
- data/ext/leveldb/db/dbformat.h +227 -0
- data/ext/leveldb/db/dbformat_test.cc +112 -0
- data/ext/leveldb/db/filename.cc +139 -0
- data/ext/leveldb/db/filename.h +80 -0
- data/ext/leveldb/db/filename_test.cc +122 -0
- data/ext/leveldb/db/leveldb_main.cc +238 -0
- data/ext/leveldb/db/log_format.h +35 -0
- data/ext/leveldb/db/log_reader.cc +259 -0
- data/ext/leveldb/db/log_reader.h +108 -0
- data/ext/leveldb/db/log_test.cc +500 -0
- data/ext/leveldb/db/log_writer.cc +103 -0
- data/ext/leveldb/db/log_writer.h +48 -0
- data/ext/leveldb/db/memtable.cc +145 -0
- data/ext/leveldb/db/memtable.h +91 -0
- data/ext/leveldb/db/repair.cc +389 -0
- data/ext/leveldb/db/skiplist.h +379 -0
- data/ext/leveldb/db/skiplist_test.cc +378 -0
- data/ext/leveldb/db/snapshot.h +66 -0
- data/ext/leveldb/db/table_cache.cc +121 -0
- data/ext/leveldb/db/table_cache.h +61 -0
- data/ext/leveldb/db/version_edit.cc +266 -0
- data/ext/leveldb/db/version_edit.h +107 -0
- data/ext/leveldb/db/version_edit_test.cc +46 -0
- data/ext/leveldb/db/version_set.cc +1443 -0
- data/ext/leveldb/db/version_set.h +383 -0
- data/ext/leveldb/db/version_set_test.cc +179 -0
- data/ext/leveldb/db/write_batch.cc +147 -0
- data/ext/leveldb/db/write_batch_internal.h +49 -0
- data/ext/leveldb/db/write_batch_test.cc +120 -0
- data/ext/leveldb/doc/bench/db_bench_sqlite3.cc +718 -0
- data/ext/leveldb/doc/bench/db_bench_tree_db.cc +528 -0
- data/ext/leveldb/helpers/memenv/memenv.cc +384 -0
- data/ext/leveldb/helpers/memenv/memenv.h +20 -0
- data/ext/leveldb/helpers/memenv/memenv_test.cc +232 -0
- data/ext/leveldb/include/leveldb/c.h +291 -0
- data/ext/leveldb/include/leveldb/cache.h +99 -0
- data/ext/leveldb/include/leveldb/comparator.h +63 -0
- data/ext/leveldb/include/leveldb/db.h +161 -0
- data/ext/leveldb/include/leveldb/env.h +333 -0
- data/ext/leveldb/include/leveldb/filter_policy.h +70 -0
- data/ext/leveldb/include/leveldb/iterator.h +100 -0
- data/ext/leveldb/include/leveldb/options.h +195 -0
- data/ext/leveldb/include/leveldb/slice.h +109 -0
- data/ext/leveldb/include/leveldb/status.h +106 -0
- data/ext/leveldb/include/leveldb/table.h +85 -0
- data/ext/leveldb/include/leveldb/table_builder.h +92 -0
- data/ext/leveldb/include/leveldb/write_batch.h +64 -0
- data/ext/leveldb/issues/issue178_test.cc +92 -0
- data/ext/leveldb/port/atomic_pointer.h +224 -0
- data/ext/leveldb/port/port.h +19 -0
- data/ext/leveldb/port/port_example.h +135 -0
- data/ext/leveldb/port/port_posix.cc +54 -0
- data/ext/leveldb/port/port_posix.h +157 -0
- data/ext/leveldb/port/thread_annotations.h +59 -0
- data/ext/leveldb/port/win/stdint.h +24 -0
- data/ext/leveldb/table/block.cc +268 -0
- data/ext/leveldb/table/block.h +44 -0
- data/ext/leveldb/table/block_builder.cc +109 -0
- data/ext/leveldb/table/block_builder.h +57 -0
- data/ext/leveldb/table/filter_block.cc +111 -0
- data/ext/leveldb/table/filter_block.h +68 -0
- data/ext/leveldb/table/filter_block_test.cc +128 -0
- data/ext/leveldb/table/format.cc +145 -0
- data/ext/leveldb/table/format.h +108 -0
- data/ext/leveldb/table/iterator.cc +67 -0
- data/ext/leveldb/table/iterator_wrapper.h +63 -0
- data/ext/leveldb/table/merger.cc +197 -0
- data/ext/leveldb/table/merger.h +26 -0
- data/ext/leveldb/table/table.cc +275 -0
- data/ext/leveldb/table/table_builder.cc +270 -0
- data/ext/leveldb/table/table_test.cc +868 -0
- data/ext/leveldb/table/two_level_iterator.cc +182 -0
- data/ext/leveldb/table/two_level_iterator.h +34 -0
- data/ext/leveldb/util/arena.cc +68 -0
- data/ext/leveldb/util/arena.h +68 -0
- data/ext/leveldb/util/arena_test.cc +68 -0
- data/ext/leveldb/util/bloom.cc +95 -0
- data/ext/leveldb/util/bloom_test.cc +160 -0
- data/ext/leveldb/util/cache.cc +325 -0
- data/ext/leveldb/util/cache_test.cc +186 -0
- data/ext/leveldb/util/coding.cc +194 -0
- data/ext/leveldb/util/coding.h +104 -0
- data/ext/leveldb/util/coding_test.cc +196 -0
- data/ext/leveldb/util/comparator.cc +81 -0
- data/ext/leveldb/util/crc32c.cc +332 -0
- data/ext/leveldb/util/crc32c.h +45 -0
- data/ext/leveldb/util/crc32c_test.cc +72 -0
- data/ext/leveldb/util/env.cc +96 -0
- data/ext/leveldb/util/env_posix.cc +698 -0
- data/ext/leveldb/util/env_test.cc +104 -0
- data/ext/leveldb/util/filter_policy.cc +11 -0
- data/ext/leveldb/util/hash.cc +52 -0
- data/ext/leveldb/util/hash.h +19 -0
- data/ext/leveldb/util/histogram.cc +139 -0
- data/ext/leveldb/util/histogram.h +42 -0
- data/ext/leveldb/util/logging.cc +81 -0
- data/ext/leveldb/util/logging.h +47 -0
- data/ext/leveldb/util/mutexlock.h +41 -0
- data/ext/leveldb/util/options.cc +29 -0
- data/ext/leveldb/util/posix_logger.h +98 -0
- data/ext/leveldb/util/random.h +59 -0
- data/ext/leveldb/util/status.cc +75 -0
- data/ext/leveldb/util/testharness.cc +77 -0
- data/ext/leveldb/util/testharness.h +138 -0
- data/ext/leveldb/util/testutil.cc +51 -0
- data/ext/leveldb/util/testutil.h +53 -0
- data/lib/leveldb/version.rb +3 -0
- data/lib/leveldb.rb +1006 -0
- metadata +228 -0
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
// Endian-neutral encoding:
|
|
6
|
+
// * Fixed-length numbers are encoded with least-significant byte first
|
|
7
|
+
// * In addition we support variable length "varint" encoding
|
|
8
|
+
// * Strings are encoded prefixed by their length in varint format
|
|
9
|
+
|
|
10
|
+
#ifndef STORAGE_LEVELDB_UTIL_CODING_H_
|
|
11
|
+
#define STORAGE_LEVELDB_UTIL_CODING_H_
|
|
12
|
+
|
|
13
|
+
#include <stdint.h>
|
|
14
|
+
#include <string.h>
|
|
15
|
+
#include <string>
|
|
16
|
+
#include "leveldb/slice.h"
|
|
17
|
+
#include "port/port.h"
|
|
18
|
+
|
|
19
|
+
namespace leveldb {
|
|
20
|
+
|
|
21
|
+
// Standard Put... routines append to a string
|
|
22
|
+
extern void PutFixed32(std::string* dst, uint32_t value);
|
|
23
|
+
extern void PutFixed64(std::string* dst, uint64_t value);
|
|
24
|
+
extern void PutVarint32(std::string* dst, uint32_t value);
|
|
25
|
+
extern void PutVarint64(std::string* dst, uint64_t value);
|
|
26
|
+
extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value);
|
|
27
|
+
|
|
28
|
+
// Standard Get... routines parse a value from the beginning of a Slice
|
|
29
|
+
// and advance the slice past the parsed value.
|
|
30
|
+
extern bool GetVarint32(Slice* input, uint32_t* value);
|
|
31
|
+
extern bool GetVarint64(Slice* input, uint64_t* value);
|
|
32
|
+
extern bool GetLengthPrefixedSlice(Slice* input, Slice* result);
|
|
33
|
+
|
|
34
|
+
// Pointer-based variants of GetVarint... These either store a value
|
|
35
|
+
// in *v and return a pointer just past the parsed value, or return
|
|
36
|
+
// NULL on error. These routines only look at bytes in the range
|
|
37
|
+
// [p..limit-1]
|
|
38
|
+
extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v);
|
|
39
|
+
extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v);
|
|
40
|
+
|
|
41
|
+
// Returns the length of the varint32 or varint64 encoding of "v"
|
|
42
|
+
extern int VarintLength(uint64_t v);
|
|
43
|
+
|
|
44
|
+
// Lower-level versions of Put... that write directly into a character buffer
|
|
45
|
+
// REQUIRES: dst has enough space for the value being written
|
|
46
|
+
extern void EncodeFixed32(char* dst, uint32_t value);
|
|
47
|
+
extern void EncodeFixed64(char* dst, uint64_t value);
|
|
48
|
+
|
|
49
|
+
// Lower-level versions of Put... that write directly into a character buffer
|
|
50
|
+
// and return a pointer just past the last byte written.
|
|
51
|
+
// REQUIRES: dst has enough space for the value being written
|
|
52
|
+
extern char* EncodeVarint32(char* dst, uint32_t value);
|
|
53
|
+
extern char* EncodeVarint64(char* dst, uint64_t value);
|
|
54
|
+
|
|
55
|
+
// Lower-level versions of Get... that read directly from a character buffer
|
|
56
|
+
// without any bounds checking.
|
|
57
|
+
|
|
58
|
+
inline uint32_t DecodeFixed32(const char* ptr) {
|
|
59
|
+
if (port::kLittleEndian) {
|
|
60
|
+
// Load the raw bytes
|
|
61
|
+
uint32_t result;
|
|
62
|
+
memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
|
|
63
|
+
return result;
|
|
64
|
+
} else {
|
|
65
|
+
return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))
|
|
66
|
+
| (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
|
|
67
|
+
| (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
|
|
68
|
+
| (static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
inline uint64_t DecodeFixed64(const char* ptr) {
|
|
73
|
+
if (port::kLittleEndian) {
|
|
74
|
+
// Load the raw bytes
|
|
75
|
+
uint64_t result;
|
|
76
|
+
memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
|
|
77
|
+
return result;
|
|
78
|
+
} else {
|
|
79
|
+
uint64_t lo = DecodeFixed32(ptr);
|
|
80
|
+
uint64_t hi = DecodeFixed32(ptr + 4);
|
|
81
|
+
return (hi << 32) | lo;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Internal routine for use by fallback path of GetVarint32Ptr
|
|
86
|
+
extern const char* GetVarint32PtrFallback(const char* p,
|
|
87
|
+
const char* limit,
|
|
88
|
+
uint32_t* value);
|
|
89
|
+
inline const char* GetVarint32Ptr(const char* p,
|
|
90
|
+
const char* limit,
|
|
91
|
+
uint32_t* value) {
|
|
92
|
+
if (p < limit) {
|
|
93
|
+
uint32_t result = *(reinterpret_cast<const unsigned char*>(p));
|
|
94
|
+
if ((result & 128) == 0) {
|
|
95
|
+
*value = result;
|
|
96
|
+
return p + 1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return GetVarint32PtrFallback(p, limit, value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
} // namespace leveldb
|
|
103
|
+
|
|
104
|
+
#endif // STORAGE_LEVELDB_UTIL_CODING_H_
|
|
@@ -0,0 +1,196 @@
|
|
|
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/coding.h"
|
|
6
|
+
|
|
7
|
+
#include "util/testharness.h"
|
|
8
|
+
|
|
9
|
+
namespace leveldb {
|
|
10
|
+
|
|
11
|
+
class Coding { };
|
|
12
|
+
|
|
13
|
+
TEST(Coding, Fixed32) {
|
|
14
|
+
std::string s;
|
|
15
|
+
for (uint32_t v = 0; v < 100000; v++) {
|
|
16
|
+
PutFixed32(&s, v);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const char* p = s.data();
|
|
20
|
+
for (uint32_t v = 0; v < 100000; v++) {
|
|
21
|
+
uint32_t actual = DecodeFixed32(p);
|
|
22
|
+
ASSERT_EQ(v, actual);
|
|
23
|
+
p += sizeof(uint32_t);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
TEST(Coding, Fixed64) {
|
|
28
|
+
std::string s;
|
|
29
|
+
for (int power = 0; power <= 63; power++) {
|
|
30
|
+
uint64_t v = static_cast<uint64_t>(1) << power;
|
|
31
|
+
PutFixed64(&s, v - 1);
|
|
32
|
+
PutFixed64(&s, v + 0);
|
|
33
|
+
PutFixed64(&s, v + 1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const char* p = s.data();
|
|
37
|
+
for (int power = 0; power <= 63; power++) {
|
|
38
|
+
uint64_t v = static_cast<uint64_t>(1) << power;
|
|
39
|
+
uint64_t actual;
|
|
40
|
+
actual = DecodeFixed64(p);
|
|
41
|
+
ASSERT_EQ(v-1, actual);
|
|
42
|
+
p += sizeof(uint64_t);
|
|
43
|
+
|
|
44
|
+
actual = DecodeFixed64(p);
|
|
45
|
+
ASSERT_EQ(v+0, actual);
|
|
46
|
+
p += sizeof(uint64_t);
|
|
47
|
+
|
|
48
|
+
actual = DecodeFixed64(p);
|
|
49
|
+
ASSERT_EQ(v+1, actual);
|
|
50
|
+
p += sizeof(uint64_t);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Test that encoding routines generate little-endian encodings
|
|
55
|
+
TEST(Coding, EncodingOutput) {
|
|
56
|
+
std::string dst;
|
|
57
|
+
PutFixed32(&dst, 0x04030201);
|
|
58
|
+
ASSERT_EQ(4, dst.size());
|
|
59
|
+
ASSERT_EQ(0x01, static_cast<int>(dst[0]));
|
|
60
|
+
ASSERT_EQ(0x02, static_cast<int>(dst[1]));
|
|
61
|
+
ASSERT_EQ(0x03, static_cast<int>(dst[2]));
|
|
62
|
+
ASSERT_EQ(0x04, static_cast<int>(dst[3]));
|
|
63
|
+
|
|
64
|
+
dst.clear();
|
|
65
|
+
PutFixed64(&dst, 0x0807060504030201ull);
|
|
66
|
+
ASSERT_EQ(8, dst.size());
|
|
67
|
+
ASSERT_EQ(0x01, static_cast<int>(dst[0]));
|
|
68
|
+
ASSERT_EQ(0x02, static_cast<int>(dst[1]));
|
|
69
|
+
ASSERT_EQ(0x03, static_cast<int>(dst[2]));
|
|
70
|
+
ASSERT_EQ(0x04, static_cast<int>(dst[3]));
|
|
71
|
+
ASSERT_EQ(0x05, static_cast<int>(dst[4]));
|
|
72
|
+
ASSERT_EQ(0x06, static_cast<int>(dst[5]));
|
|
73
|
+
ASSERT_EQ(0x07, static_cast<int>(dst[6]));
|
|
74
|
+
ASSERT_EQ(0x08, static_cast<int>(dst[7]));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
TEST(Coding, Varint32) {
|
|
78
|
+
std::string s;
|
|
79
|
+
for (uint32_t i = 0; i < (32 * 32); i++) {
|
|
80
|
+
uint32_t v = (i / 32) << (i % 32);
|
|
81
|
+
PutVarint32(&s, v);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const char* p = s.data();
|
|
85
|
+
const char* limit = p + s.size();
|
|
86
|
+
for (uint32_t i = 0; i < (32 * 32); i++) {
|
|
87
|
+
uint32_t expected = (i / 32) << (i % 32);
|
|
88
|
+
uint32_t actual;
|
|
89
|
+
const char* start = p;
|
|
90
|
+
p = GetVarint32Ptr(p, limit, &actual);
|
|
91
|
+
ASSERT_TRUE(p != NULL);
|
|
92
|
+
ASSERT_EQ(expected, actual);
|
|
93
|
+
ASSERT_EQ(VarintLength(actual), p - start);
|
|
94
|
+
}
|
|
95
|
+
ASSERT_EQ(p, s.data() + s.size());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
TEST(Coding, Varint64) {
|
|
99
|
+
// Construct the list of values to check
|
|
100
|
+
std::vector<uint64_t> values;
|
|
101
|
+
// Some special values
|
|
102
|
+
values.push_back(0);
|
|
103
|
+
values.push_back(100);
|
|
104
|
+
values.push_back(~static_cast<uint64_t>(0));
|
|
105
|
+
values.push_back(~static_cast<uint64_t>(0) - 1);
|
|
106
|
+
for (uint32_t k = 0; k < 64; k++) {
|
|
107
|
+
// Test values near powers of two
|
|
108
|
+
const uint64_t power = 1ull << k;
|
|
109
|
+
values.push_back(power);
|
|
110
|
+
values.push_back(power-1);
|
|
111
|
+
values.push_back(power+1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
std::string s;
|
|
115
|
+
for (int i = 0; i < values.size(); i++) {
|
|
116
|
+
PutVarint64(&s, values[i]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const char* p = s.data();
|
|
120
|
+
const char* limit = p + s.size();
|
|
121
|
+
for (int i = 0; i < values.size(); i++) {
|
|
122
|
+
ASSERT_TRUE(p < limit);
|
|
123
|
+
uint64_t actual;
|
|
124
|
+
const char* start = p;
|
|
125
|
+
p = GetVarint64Ptr(p, limit, &actual);
|
|
126
|
+
ASSERT_TRUE(p != NULL);
|
|
127
|
+
ASSERT_EQ(values[i], actual);
|
|
128
|
+
ASSERT_EQ(VarintLength(actual), p - start);
|
|
129
|
+
}
|
|
130
|
+
ASSERT_EQ(p, limit);
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
TEST(Coding, Varint32Overflow) {
|
|
135
|
+
uint32_t result;
|
|
136
|
+
std::string input("\x81\x82\x83\x84\x85\x11");
|
|
137
|
+
ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result)
|
|
138
|
+
== NULL);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
TEST(Coding, Varint32Truncation) {
|
|
142
|
+
uint32_t large_value = (1u << 31) + 100;
|
|
143
|
+
std::string s;
|
|
144
|
+
PutVarint32(&s, large_value);
|
|
145
|
+
uint32_t result;
|
|
146
|
+
for (int len = 0; len < s.size() - 1; len++) {
|
|
147
|
+
ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == NULL);
|
|
148
|
+
}
|
|
149
|
+
ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != NULL);
|
|
150
|
+
ASSERT_EQ(large_value, result);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
TEST(Coding, Varint64Overflow) {
|
|
154
|
+
uint64_t result;
|
|
155
|
+
std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11");
|
|
156
|
+
ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result)
|
|
157
|
+
== NULL);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
TEST(Coding, Varint64Truncation) {
|
|
161
|
+
uint64_t large_value = (1ull << 63) + 100ull;
|
|
162
|
+
std::string s;
|
|
163
|
+
PutVarint64(&s, large_value);
|
|
164
|
+
uint64_t result;
|
|
165
|
+
for (int len = 0; len < s.size() - 1; len++) {
|
|
166
|
+
ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == NULL);
|
|
167
|
+
}
|
|
168
|
+
ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != NULL);
|
|
169
|
+
ASSERT_EQ(large_value, result);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
TEST(Coding, Strings) {
|
|
173
|
+
std::string s;
|
|
174
|
+
PutLengthPrefixedSlice(&s, Slice(""));
|
|
175
|
+
PutLengthPrefixedSlice(&s, Slice("foo"));
|
|
176
|
+
PutLengthPrefixedSlice(&s, Slice("bar"));
|
|
177
|
+
PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x')));
|
|
178
|
+
|
|
179
|
+
Slice input(s);
|
|
180
|
+
Slice v;
|
|
181
|
+
ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
|
|
182
|
+
ASSERT_EQ("", v.ToString());
|
|
183
|
+
ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
|
|
184
|
+
ASSERT_EQ("foo", v.ToString());
|
|
185
|
+
ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
|
|
186
|
+
ASSERT_EQ("bar", v.ToString());
|
|
187
|
+
ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
|
|
188
|
+
ASSERT_EQ(std::string(200, 'x'), v.ToString());
|
|
189
|
+
ASSERT_EQ("", input.ToString());
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
} // namespace leveldb
|
|
193
|
+
|
|
194
|
+
int main(int argc, char** argv) {
|
|
195
|
+
return leveldb::test::RunAllTests();
|
|
196
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
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 <algorithm>
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
#include "leveldb/comparator.h"
|
|
8
|
+
#include "leveldb/slice.h"
|
|
9
|
+
#include "port/port.h"
|
|
10
|
+
#include "util/logging.h"
|
|
11
|
+
|
|
12
|
+
namespace leveldb {
|
|
13
|
+
|
|
14
|
+
Comparator::~Comparator() { }
|
|
15
|
+
|
|
16
|
+
namespace {
|
|
17
|
+
class BytewiseComparatorImpl : public Comparator {
|
|
18
|
+
public:
|
|
19
|
+
BytewiseComparatorImpl() { }
|
|
20
|
+
|
|
21
|
+
virtual const char* Name() const {
|
|
22
|
+
return "leveldb.BytewiseComparator";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
virtual int Compare(const Slice& a, const Slice& b) const {
|
|
26
|
+
return a.compare(b);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
virtual void FindShortestSeparator(
|
|
30
|
+
std::string* start,
|
|
31
|
+
const Slice& limit) const {
|
|
32
|
+
// Find length of common prefix
|
|
33
|
+
size_t min_length = std::min(start->size(), limit.size());
|
|
34
|
+
size_t diff_index = 0;
|
|
35
|
+
while ((diff_index < min_length) &&
|
|
36
|
+
((*start)[diff_index] == limit[diff_index])) {
|
|
37
|
+
diff_index++;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (diff_index >= min_length) {
|
|
41
|
+
// Do not shorten if one string is a prefix of the other
|
|
42
|
+
} else {
|
|
43
|
+
uint8_t diff_byte = static_cast<uint8_t>((*start)[diff_index]);
|
|
44
|
+
if (diff_byte < static_cast<uint8_t>(0xff) &&
|
|
45
|
+
diff_byte + 1 < static_cast<uint8_t>(limit[diff_index])) {
|
|
46
|
+
(*start)[diff_index]++;
|
|
47
|
+
start->resize(diff_index + 1);
|
|
48
|
+
assert(Compare(*start, limit) < 0);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
virtual void FindShortSuccessor(std::string* key) const {
|
|
54
|
+
// Find first character that can be incremented
|
|
55
|
+
size_t n = key->size();
|
|
56
|
+
for (size_t i = 0; i < n; i++) {
|
|
57
|
+
const uint8_t byte = (*key)[i];
|
|
58
|
+
if (byte != static_cast<uint8_t>(0xff)) {
|
|
59
|
+
(*key)[i] = byte + 1;
|
|
60
|
+
key->resize(i+1);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// *key is a run of 0xffs. Leave it alone.
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
} // namespace
|
|
68
|
+
|
|
69
|
+
static port::OnceType once = LEVELDB_ONCE_INIT;
|
|
70
|
+
static const Comparator* bytewise;
|
|
71
|
+
|
|
72
|
+
static void InitModule() {
|
|
73
|
+
bytewise = new BytewiseComparatorImpl;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const Comparator* BytewiseComparator() {
|
|
77
|
+
port::InitOnce(&once, InitModule);
|
|
78
|
+
return bytewise;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
} // namespace leveldb
|