leveldb-ruby 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/README +17 -0
  2. data/ext/leveldb/extconf.rb +10 -0
  3. data/ext/leveldb/leveldb.cc +181 -0
  4. data/leveldb/Makefile +172 -0
  5. data/leveldb/db/builder.cc +90 -0
  6. data/leveldb/db/builder.h +36 -0
  7. data/leveldb/db/corruption_test.cc +354 -0
  8. data/leveldb/db/db_bench.cc +677 -0
  9. data/leveldb/db/db_impl.cc +1236 -0
  10. data/leveldb/db/db_impl.h +180 -0
  11. data/leveldb/db/db_iter.cc +298 -0
  12. data/leveldb/db/db_iter.h +26 -0
  13. data/leveldb/db/db_test.cc +1192 -0
  14. data/leveldb/db/dbformat.cc +87 -0
  15. data/leveldb/db/dbformat.h +165 -0
  16. data/leveldb/db/dbformat_test.cc +112 -0
  17. data/leveldb/db/filename.cc +135 -0
  18. data/leveldb/db/filename.h +80 -0
  19. data/leveldb/db/filename_test.cc +122 -0
  20. data/leveldb/db/log_format.h +35 -0
  21. data/leveldb/db/log_reader.cc +254 -0
  22. data/leveldb/db/log_reader.h +108 -0
  23. data/leveldb/db/log_test.cc +500 -0
  24. data/leveldb/db/log_writer.cc +103 -0
  25. data/leveldb/db/log_writer.h +48 -0
  26. data/leveldb/db/memtable.cc +108 -0
  27. data/leveldb/db/memtable.h +85 -0
  28. data/leveldb/db/repair.cc +384 -0
  29. data/leveldb/db/skiplist.h +378 -0
  30. data/leveldb/db/skiplist_test.cc +378 -0
  31. data/leveldb/db/snapshot.h +66 -0
  32. data/leveldb/db/table_cache.cc +95 -0
  33. data/leveldb/db/table_cache.h +50 -0
  34. data/leveldb/db/version_edit.cc +268 -0
  35. data/leveldb/db/version_edit.h +106 -0
  36. data/leveldb/db/version_edit_test.cc +46 -0
  37. data/leveldb/db/version_set.cc +1060 -0
  38. data/leveldb/db/version_set.h +306 -0
  39. data/leveldb/db/write_batch.cc +138 -0
  40. data/leveldb/db/write_batch_internal.h +45 -0
  41. data/leveldb/db/write_batch_test.cc +89 -0
  42. data/leveldb/include/leveldb/cache.h +99 -0
  43. data/leveldb/include/leveldb/comparator.h +63 -0
  44. data/leveldb/include/leveldb/db.h +148 -0
  45. data/leveldb/include/leveldb/env.h +302 -0
  46. data/leveldb/include/leveldb/iterator.h +100 -0
  47. data/leveldb/include/leveldb/options.h +198 -0
  48. data/leveldb/include/leveldb/slice.h +109 -0
  49. data/leveldb/include/leveldb/status.h +100 -0
  50. data/leveldb/include/leveldb/table.h +70 -0
  51. data/leveldb/include/leveldb/table_builder.h +91 -0
  52. data/leveldb/include/leveldb/write_batch.h +64 -0
  53. data/leveldb/port/port.h +23 -0
  54. data/leveldb/port/port_android.cc +64 -0
  55. data/leveldb/port/port_android.h +150 -0
  56. data/leveldb/port/port_chromium.cc +80 -0
  57. data/leveldb/port/port_chromium.h +97 -0
  58. data/leveldb/port/port_example.h +115 -0
  59. data/leveldb/port/port_osx.cc +50 -0
  60. data/leveldb/port/port_osx.h +125 -0
  61. data/leveldb/port/port_posix.cc +50 -0
  62. data/leveldb/port/port_posix.h +94 -0
  63. data/leveldb/port/sha1_portable.cc +298 -0
  64. data/leveldb/port/sha1_portable.h +25 -0
  65. data/leveldb/port/sha1_test.cc +39 -0
  66. data/leveldb/port/win/stdint.h +24 -0
  67. data/leveldb/table/block.cc +263 -0
  68. data/leveldb/table/block.h +43 -0
  69. data/leveldb/table/block_builder.cc +109 -0
  70. data/leveldb/table/block_builder.h +57 -0
  71. data/leveldb/table/format.cc +131 -0
  72. data/leveldb/table/format.h +103 -0
  73. data/leveldb/table/iterator.cc +67 -0
  74. data/leveldb/table/iterator_wrapper.h +63 -0
  75. data/leveldb/table/merger.cc +197 -0
  76. data/leveldb/table/merger.h +26 -0
  77. data/leveldb/table/table.cc +175 -0
  78. data/leveldb/table/table_builder.cc +227 -0
  79. data/leveldb/table/table_test.cc +845 -0
  80. data/leveldb/table/two_level_iterator.cc +182 -0
  81. data/leveldb/table/two_level_iterator.h +34 -0
  82. data/leveldb/util/arena.cc +68 -0
  83. data/leveldb/util/arena.h +68 -0
  84. data/leveldb/util/arena_test.cc +68 -0
  85. data/leveldb/util/cache.cc +255 -0
  86. data/leveldb/util/cache_test.cc +169 -0
  87. data/leveldb/util/coding.cc +194 -0
  88. data/leveldb/util/coding.h +104 -0
  89. data/leveldb/util/coding_test.cc +173 -0
  90. data/leveldb/util/comparator.cc +72 -0
  91. data/leveldb/util/crc32c.cc +332 -0
  92. data/leveldb/util/crc32c.h +45 -0
  93. data/leveldb/util/crc32c_test.cc +72 -0
  94. data/leveldb/util/env.cc +77 -0
  95. data/leveldb/util/env_chromium.cc +612 -0
  96. data/leveldb/util/env_posix.cc +606 -0
  97. data/leveldb/util/env_test.cc +102 -0
  98. data/leveldb/util/hash.cc +45 -0
  99. data/leveldb/util/hash.h +19 -0
  100. data/leveldb/util/histogram.cc +128 -0
  101. data/leveldb/util/histogram.h +41 -0
  102. data/leveldb/util/logging.cc +81 -0
  103. data/leveldb/util/logging.h +47 -0
  104. data/leveldb/util/mutexlock.h +39 -0
  105. data/leveldb/util/options.cc +28 -0
  106. data/leveldb/util/random.h +59 -0
  107. data/leveldb/util/status.cc +75 -0
  108. data/leveldb/util/testharness.cc +65 -0
  109. data/leveldb/util/testharness.h +129 -0
  110. data/leveldb/util/testutil.cc +51 -0
  111. data/leveldb/util/testutil.h +53 -0
  112. data/lib/leveldb.rb +36 -0
  113. 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_