leveldb-ruby 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.
- data/README +17 -0
- data/ext/leveldb/extconf.rb +10 -0
- data/ext/leveldb/leveldb.cc +181 -0
- data/leveldb/Makefile +172 -0
- data/leveldb/db/builder.cc +90 -0
- data/leveldb/db/builder.h +36 -0
- data/leveldb/db/corruption_test.cc +354 -0
- data/leveldb/db/db_bench.cc +677 -0
- data/leveldb/db/db_impl.cc +1236 -0
- data/leveldb/db/db_impl.h +180 -0
- data/leveldb/db/db_iter.cc +298 -0
- data/leveldb/db/db_iter.h +26 -0
- data/leveldb/db/db_test.cc +1192 -0
- data/leveldb/db/dbformat.cc +87 -0
- data/leveldb/db/dbformat.h +165 -0
- data/leveldb/db/dbformat_test.cc +112 -0
- data/leveldb/db/filename.cc +135 -0
- data/leveldb/db/filename.h +80 -0
- data/leveldb/db/filename_test.cc +122 -0
- data/leveldb/db/log_format.h +35 -0
- data/leveldb/db/log_reader.cc +254 -0
- data/leveldb/db/log_reader.h +108 -0
- data/leveldb/db/log_test.cc +500 -0
- data/leveldb/db/log_writer.cc +103 -0
- data/leveldb/db/log_writer.h +48 -0
- data/leveldb/db/memtable.cc +108 -0
- data/leveldb/db/memtable.h +85 -0
- data/leveldb/db/repair.cc +384 -0
- data/leveldb/db/skiplist.h +378 -0
- data/leveldb/db/skiplist_test.cc +378 -0
- data/leveldb/db/snapshot.h +66 -0
- data/leveldb/db/table_cache.cc +95 -0
- data/leveldb/db/table_cache.h +50 -0
- data/leveldb/db/version_edit.cc +268 -0
- data/leveldb/db/version_edit.h +106 -0
- data/leveldb/db/version_edit_test.cc +46 -0
- data/leveldb/db/version_set.cc +1060 -0
- data/leveldb/db/version_set.h +306 -0
- data/leveldb/db/write_batch.cc +138 -0
- data/leveldb/db/write_batch_internal.h +45 -0
- data/leveldb/db/write_batch_test.cc +89 -0
- data/leveldb/include/leveldb/cache.h +99 -0
- data/leveldb/include/leveldb/comparator.h +63 -0
- data/leveldb/include/leveldb/db.h +148 -0
- data/leveldb/include/leveldb/env.h +302 -0
- data/leveldb/include/leveldb/iterator.h +100 -0
- data/leveldb/include/leveldb/options.h +198 -0
- data/leveldb/include/leveldb/slice.h +109 -0
- data/leveldb/include/leveldb/status.h +100 -0
- data/leveldb/include/leveldb/table.h +70 -0
- data/leveldb/include/leveldb/table_builder.h +91 -0
- data/leveldb/include/leveldb/write_batch.h +64 -0
- data/leveldb/port/port.h +23 -0
- data/leveldb/port/port_android.cc +64 -0
- data/leveldb/port/port_android.h +150 -0
- data/leveldb/port/port_chromium.cc +80 -0
- data/leveldb/port/port_chromium.h +97 -0
- data/leveldb/port/port_example.h +115 -0
- data/leveldb/port/port_osx.cc +50 -0
- data/leveldb/port/port_osx.h +125 -0
- data/leveldb/port/port_posix.cc +50 -0
- data/leveldb/port/port_posix.h +94 -0
- data/leveldb/port/sha1_portable.cc +298 -0
- data/leveldb/port/sha1_portable.h +25 -0
- data/leveldb/port/sha1_test.cc +39 -0
- data/leveldb/port/win/stdint.h +24 -0
- data/leveldb/table/block.cc +263 -0
- data/leveldb/table/block.h +43 -0
- data/leveldb/table/block_builder.cc +109 -0
- data/leveldb/table/block_builder.h +57 -0
- data/leveldb/table/format.cc +131 -0
- data/leveldb/table/format.h +103 -0
- data/leveldb/table/iterator.cc +67 -0
- data/leveldb/table/iterator_wrapper.h +63 -0
- data/leveldb/table/merger.cc +197 -0
- data/leveldb/table/merger.h +26 -0
- data/leveldb/table/table.cc +175 -0
- data/leveldb/table/table_builder.cc +227 -0
- data/leveldb/table/table_test.cc +845 -0
- data/leveldb/table/two_level_iterator.cc +182 -0
- data/leveldb/table/two_level_iterator.h +34 -0
- data/leveldb/util/arena.cc +68 -0
- data/leveldb/util/arena.h +68 -0
- data/leveldb/util/arena_test.cc +68 -0
- data/leveldb/util/cache.cc +255 -0
- data/leveldb/util/cache_test.cc +169 -0
- data/leveldb/util/coding.cc +194 -0
- data/leveldb/util/coding.h +104 -0
- data/leveldb/util/coding_test.cc +173 -0
- data/leveldb/util/comparator.cc +72 -0
- data/leveldb/util/crc32c.cc +332 -0
- data/leveldb/util/crc32c.h +45 -0
- data/leveldb/util/crc32c_test.cc +72 -0
- data/leveldb/util/env.cc +77 -0
- data/leveldb/util/env_chromium.cc +612 -0
- data/leveldb/util/env_posix.cc +606 -0
- data/leveldb/util/env_test.cc +102 -0
- data/leveldb/util/hash.cc +45 -0
- data/leveldb/util/hash.h +19 -0
- data/leveldb/util/histogram.cc +128 -0
- data/leveldb/util/histogram.h +41 -0
- data/leveldb/util/logging.cc +81 -0
- data/leveldb/util/logging.h +47 -0
- data/leveldb/util/mutexlock.h +39 -0
- data/leveldb/util/options.cc +28 -0
- data/leveldb/util/random.h +59 -0
- data/leveldb/util/status.cc +75 -0
- data/leveldb/util/testharness.cc +65 -0
- data/leveldb/util/testharness.h +129 -0
- data/leveldb/util/testutil.cc +51 -0
- data/leveldb/util/testutil.h +53 -0
- data/lib/leveldb.rb +36 -0
- metadata +183 -0
|
@@ -0,0 +1,169 @@
|
|
|
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 "leveldb/cache.h"
|
|
6
|
+
|
|
7
|
+
#include <vector>
|
|
8
|
+
#include "util/coding.h"
|
|
9
|
+
#include "util/testharness.h"
|
|
10
|
+
|
|
11
|
+
namespace leveldb {
|
|
12
|
+
|
|
13
|
+
// Conversions between numeric keys/values and the types expected by Cache.
|
|
14
|
+
static std::string EncodeKey(int k) {
|
|
15
|
+
std::string result;
|
|
16
|
+
PutFixed32(&result, k);
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
static int DecodeKey(const Slice& k) {
|
|
20
|
+
assert(k.size() == 4);
|
|
21
|
+
return DecodeFixed32(k.data());
|
|
22
|
+
}
|
|
23
|
+
static void* EncodeValue(uintptr_t v) { return reinterpret_cast<void*>(v); }
|
|
24
|
+
static int DecodeValue(void* v) { return reinterpret_cast<uintptr_t>(v); }
|
|
25
|
+
|
|
26
|
+
class CacheTest {
|
|
27
|
+
public:
|
|
28
|
+
static CacheTest* current_;
|
|
29
|
+
|
|
30
|
+
static void Deleter(const Slice& key, void* v) {
|
|
31
|
+
current_->deleted_keys_.push_back(DecodeKey(key));
|
|
32
|
+
current_->deleted_values_.push_back(DecodeValue(v));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static const int kCacheSize = 100;
|
|
36
|
+
std::vector<int> deleted_keys_;
|
|
37
|
+
std::vector<int> deleted_values_;
|
|
38
|
+
Cache* cache_;
|
|
39
|
+
|
|
40
|
+
CacheTest() : cache_(NewLRUCache(kCacheSize)) {
|
|
41
|
+
current_ = this;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
~CacheTest() {
|
|
45
|
+
delete cache_;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
int Lookup(int key) {
|
|
49
|
+
Cache::Handle* handle = cache_->Lookup(EncodeKey(key));
|
|
50
|
+
const int r = (handle == NULL) ? -1 : DecodeValue(cache_->Value(handle));
|
|
51
|
+
if (handle != NULL) {
|
|
52
|
+
cache_->Release(handle);
|
|
53
|
+
}
|
|
54
|
+
return r;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void Insert(int key, int value, int charge = 1) {
|
|
58
|
+
cache_->Release(cache_->Insert(EncodeKey(key), EncodeValue(value), charge,
|
|
59
|
+
&CacheTest::Deleter));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void Erase(int key) {
|
|
63
|
+
cache_->Erase(EncodeKey(key));
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
CacheTest* CacheTest::current_;
|
|
67
|
+
|
|
68
|
+
TEST(CacheTest, HitAndMiss) {
|
|
69
|
+
ASSERT_EQ(-1, Lookup(100));
|
|
70
|
+
|
|
71
|
+
Insert(100, 101);
|
|
72
|
+
ASSERT_EQ(101, Lookup(100));
|
|
73
|
+
ASSERT_EQ(-1, Lookup(200));
|
|
74
|
+
ASSERT_EQ(-1, Lookup(300));
|
|
75
|
+
|
|
76
|
+
Insert(200, 201);
|
|
77
|
+
ASSERT_EQ(101, Lookup(100));
|
|
78
|
+
ASSERT_EQ(201, Lookup(200));
|
|
79
|
+
ASSERT_EQ(-1, Lookup(300));
|
|
80
|
+
|
|
81
|
+
Insert(100, 102);
|
|
82
|
+
ASSERT_EQ(102, Lookup(100));
|
|
83
|
+
ASSERT_EQ(201, Lookup(200));
|
|
84
|
+
ASSERT_EQ(-1, Lookup(300));
|
|
85
|
+
|
|
86
|
+
ASSERT_EQ(1, deleted_keys_.size());
|
|
87
|
+
ASSERT_EQ(100, deleted_keys_[0]);
|
|
88
|
+
ASSERT_EQ(101, deleted_values_[0]);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
TEST(CacheTest, Erase) {
|
|
92
|
+
Erase(200);
|
|
93
|
+
ASSERT_EQ(0, deleted_keys_.size());
|
|
94
|
+
|
|
95
|
+
Insert(100, 101);
|
|
96
|
+
Insert(200, 201);
|
|
97
|
+
Erase(100);
|
|
98
|
+
ASSERT_EQ(-1, Lookup(100));
|
|
99
|
+
ASSERT_EQ(201, Lookup(200));
|
|
100
|
+
ASSERT_EQ(1, deleted_keys_.size());
|
|
101
|
+
ASSERT_EQ(100, deleted_keys_[0]);
|
|
102
|
+
ASSERT_EQ(101, deleted_values_[0]);
|
|
103
|
+
|
|
104
|
+
Erase(100);
|
|
105
|
+
ASSERT_EQ(-1, Lookup(100));
|
|
106
|
+
ASSERT_EQ(201, Lookup(200));
|
|
107
|
+
ASSERT_EQ(1, deleted_keys_.size());
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
TEST(CacheTest, EntriesArePinned) {
|
|
111
|
+
Insert(100, 101);
|
|
112
|
+
Cache::Handle* h1 = cache_->Lookup(EncodeKey(100));
|
|
113
|
+
ASSERT_EQ(101, DecodeValue(cache_->Value(h1)));
|
|
114
|
+
|
|
115
|
+
Insert(100, 102);
|
|
116
|
+
Cache::Handle* h2 = cache_->Lookup(EncodeKey(100));
|
|
117
|
+
ASSERT_EQ(102, DecodeValue(cache_->Value(h2)));
|
|
118
|
+
ASSERT_EQ(0, deleted_keys_.size());
|
|
119
|
+
|
|
120
|
+
cache_->Release(h1);
|
|
121
|
+
ASSERT_EQ(1, deleted_keys_.size());
|
|
122
|
+
ASSERT_EQ(100, deleted_keys_[0]);
|
|
123
|
+
ASSERT_EQ(101, deleted_values_[0]);
|
|
124
|
+
|
|
125
|
+
Erase(100);
|
|
126
|
+
ASSERT_EQ(-1, Lookup(100));
|
|
127
|
+
ASSERT_EQ(1, deleted_keys_.size());
|
|
128
|
+
|
|
129
|
+
cache_->Release(h2);
|
|
130
|
+
ASSERT_EQ(2, deleted_keys_.size());
|
|
131
|
+
ASSERT_EQ(100, deleted_keys_[1]);
|
|
132
|
+
ASSERT_EQ(102, deleted_values_[1]);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
TEST(CacheTest, EvictionPolicy) {
|
|
136
|
+
Insert(100, 101);
|
|
137
|
+
Insert(200, 201);
|
|
138
|
+
|
|
139
|
+
// Frequently used entry must be kept around
|
|
140
|
+
for (int i = 0; i < kCacheSize; i++) {
|
|
141
|
+
Insert(1000+i, 2000+i);
|
|
142
|
+
ASSERT_EQ(2000+i, Lookup(1000+i));
|
|
143
|
+
ASSERT_EQ(101, Lookup(100));
|
|
144
|
+
}
|
|
145
|
+
ASSERT_EQ(101, Lookup(100));
|
|
146
|
+
ASSERT_EQ(2, deleted_keys_.size());
|
|
147
|
+
ASSERT_EQ(200, deleted_keys_[0]);
|
|
148
|
+
ASSERT_EQ(201, deleted_values_[0]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
TEST(CacheTest, HeavyEntry) {
|
|
152
|
+
Insert(100, 101);
|
|
153
|
+
Insert(200, 201, kCacheSize);
|
|
154
|
+
ASSERT_EQ(1, deleted_keys_.size());
|
|
155
|
+
ASSERT_EQ(100, deleted_keys_[0]);
|
|
156
|
+
ASSERT_EQ(101, deleted_values_[0]);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
TEST(CacheTest, NewId) {
|
|
160
|
+
uint64_t a = cache_->NewId();
|
|
161
|
+
uint64_t b = cache_->NewId();
|
|
162
|
+
ASSERT_NE(a, b);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
int main(int argc, char** argv) {
|
|
168
|
+
return leveldb::test::RunAllTests();
|
|
169
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
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
|
+
namespace leveldb {
|
|
8
|
+
|
|
9
|
+
void EncodeFixed32(char* buf, uint32_t value) {
|
|
10
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
11
|
+
memcpy(buf, &value, sizeof(value));
|
|
12
|
+
#else
|
|
13
|
+
buf[0] = value & 0xff;
|
|
14
|
+
buf[1] = (value >> 8) & 0xff;
|
|
15
|
+
buf[2] = (value >> 16) & 0xff;
|
|
16
|
+
buf[3] = (value >> 24) & 0xff;
|
|
17
|
+
#endif
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void EncodeFixed64(char* buf, uint64_t value) {
|
|
21
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
22
|
+
memcpy(buf, &value, sizeof(value));
|
|
23
|
+
#else
|
|
24
|
+
buf[0] = value & 0xff;
|
|
25
|
+
buf[1] = (value >> 8) & 0xff;
|
|
26
|
+
buf[2] = (value >> 16) & 0xff;
|
|
27
|
+
buf[3] = (value >> 24) & 0xff;
|
|
28
|
+
buf[4] = (value >> 32) & 0xff;
|
|
29
|
+
buf[5] = (value >> 40) & 0xff;
|
|
30
|
+
buf[6] = (value >> 48) & 0xff;
|
|
31
|
+
buf[7] = (value >> 56) & 0xff;
|
|
32
|
+
#endif
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void PutFixed32(std::string* dst, uint32_t value) {
|
|
36
|
+
char buf[sizeof(value)];
|
|
37
|
+
EncodeFixed32(buf, value);
|
|
38
|
+
dst->append(buf, sizeof(buf));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void PutFixed64(std::string* dst, uint64_t value) {
|
|
42
|
+
char buf[sizeof(value)];
|
|
43
|
+
EncodeFixed64(buf, value);
|
|
44
|
+
dst->append(buf, sizeof(buf));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
char* EncodeVarint32(char* dst, uint32_t v) {
|
|
48
|
+
// Operate on characters as unsigneds
|
|
49
|
+
unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
|
|
50
|
+
static const int B = 128;
|
|
51
|
+
if (v < (1<<7)) {
|
|
52
|
+
*(ptr++) = v;
|
|
53
|
+
} else if (v < (1<<14)) {
|
|
54
|
+
*(ptr++) = v | B;
|
|
55
|
+
*(ptr++) = v>>7;
|
|
56
|
+
} else if (v < (1<<21)) {
|
|
57
|
+
*(ptr++) = v | B;
|
|
58
|
+
*(ptr++) = (v>>7) | B;
|
|
59
|
+
*(ptr++) = v>>14;
|
|
60
|
+
} else if (v < (1<<28)) {
|
|
61
|
+
*(ptr++) = v | B;
|
|
62
|
+
*(ptr++) = (v>>7) | B;
|
|
63
|
+
*(ptr++) = (v>>14) | B;
|
|
64
|
+
*(ptr++) = v>>21;
|
|
65
|
+
} else {
|
|
66
|
+
*(ptr++) = v | B;
|
|
67
|
+
*(ptr++) = (v>>7) | B;
|
|
68
|
+
*(ptr++) = (v>>14) | B;
|
|
69
|
+
*(ptr++) = (v>>21) | B;
|
|
70
|
+
*(ptr++) = v>>28;
|
|
71
|
+
}
|
|
72
|
+
return reinterpret_cast<char*>(ptr);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void PutVarint32(std::string* dst, uint32_t v) {
|
|
76
|
+
char buf[5];
|
|
77
|
+
char* ptr = EncodeVarint32(buf, v);
|
|
78
|
+
dst->append(buf, ptr - buf);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
char* EncodeVarint64(char* dst, uint64_t v) {
|
|
82
|
+
static const int B = 128;
|
|
83
|
+
unsigned char* ptr = reinterpret_cast<unsigned char*>(dst);
|
|
84
|
+
while (v >= B) {
|
|
85
|
+
*(ptr++) = (v & (B-1)) | B;
|
|
86
|
+
v >>= 7;
|
|
87
|
+
}
|
|
88
|
+
*(ptr++) = static_cast<unsigned char>(v);
|
|
89
|
+
return reinterpret_cast<char*>(ptr);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void PutVarint64(std::string* dst, uint64_t v) {
|
|
93
|
+
char buf[10];
|
|
94
|
+
char* ptr = EncodeVarint64(buf, v);
|
|
95
|
+
dst->append(buf, ptr - buf);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void PutLengthPrefixedSlice(std::string* dst, const Slice& value) {
|
|
99
|
+
PutVarint32(dst, value.size());
|
|
100
|
+
dst->append(value.data(), value.size());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
int VarintLength(uint64_t v) {
|
|
104
|
+
int len = 1;
|
|
105
|
+
while (v >= 128) {
|
|
106
|
+
v >>= 7;
|
|
107
|
+
len++;
|
|
108
|
+
}
|
|
109
|
+
return len;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const char* GetVarint32PtrFallback(const char* p,
|
|
113
|
+
const char* limit,
|
|
114
|
+
uint32_t* value) {
|
|
115
|
+
uint32_t result = 0;
|
|
116
|
+
for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
|
|
117
|
+
uint32_t byte = *(reinterpret_cast<const unsigned char*>(p));
|
|
118
|
+
p++;
|
|
119
|
+
if (byte & 128) {
|
|
120
|
+
// More bytes are present
|
|
121
|
+
result |= ((byte & 127) << shift);
|
|
122
|
+
} else {
|
|
123
|
+
result |= (byte << shift);
|
|
124
|
+
*value = result;
|
|
125
|
+
return reinterpret_cast<const char*>(p);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return NULL;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
bool GetVarint32(Slice* input, uint32_t* value) {
|
|
132
|
+
const char* p = input->data();
|
|
133
|
+
const char* limit = p + input->size();
|
|
134
|
+
const char* q = GetVarint32Ptr(p, limit, value);
|
|
135
|
+
if (q == NULL) {
|
|
136
|
+
return false;
|
|
137
|
+
} else {
|
|
138
|
+
*input = Slice(q, limit - q);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) {
|
|
144
|
+
uint64_t result = 0;
|
|
145
|
+
for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) {
|
|
146
|
+
uint64_t byte = *(reinterpret_cast<const unsigned char*>(p));
|
|
147
|
+
p++;
|
|
148
|
+
if (byte & 128) {
|
|
149
|
+
// More bytes are present
|
|
150
|
+
result |= ((byte & 127) << shift);
|
|
151
|
+
} else {
|
|
152
|
+
result |= (byte << shift);
|
|
153
|
+
*value = result;
|
|
154
|
+
return reinterpret_cast<const char*>(p);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return NULL;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
bool GetVarint64(Slice* input, uint64_t* value) {
|
|
161
|
+
const char* p = input->data();
|
|
162
|
+
const char* limit = p + input->size();
|
|
163
|
+
const char* q = GetVarint64Ptr(p, limit, value);
|
|
164
|
+
if (q == NULL) {
|
|
165
|
+
return false;
|
|
166
|
+
} else {
|
|
167
|
+
*input = Slice(q, limit - q);
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const char* GetLengthPrefixedSlice(const char* p, const char* limit,
|
|
173
|
+
Slice* result) {
|
|
174
|
+
uint32_t len;
|
|
175
|
+
p = GetVarint32Ptr(p, limit, &len);
|
|
176
|
+
if (p == NULL) return NULL;
|
|
177
|
+
if (p + len > limit) return NULL;
|
|
178
|
+
*result = Slice(p, len);
|
|
179
|
+
return p + len;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
|
|
183
|
+
uint32_t len;
|
|
184
|
+
if (GetVarint32(input, &len) &&
|
|
185
|
+
input->size() >= len) {
|
|
186
|
+
*result = Slice(input->data(), len);
|
|
187
|
+
input->remove_prefix(len);
|
|
188
|
+
return true;
|
|
189
|
+
} else {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
}
|
|
@@ -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>(ptr[0]))
|
|
66
|
+
| (static_cast<uint32_t>(ptr[1]) << 8)
|
|
67
|
+
| (static_cast<uint32_t>(ptr[2]) << 16)
|
|
68
|
+
| (static_cast<uint32_t>(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
|
+
}
|
|
103
|
+
|
|
104
|
+
#endif // STORAGE_LEVELDB_UTIL_CODING_H_
|