]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/include/rocksdb/slice.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / include / rocksdb / slice.h
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file. See the AUTHORS file for names of contributors.
8 //
9 // Slice is a simple structure containing a pointer into some external
10 // storage and a size. The user of a Slice must ensure that the slice
11 // is not used after the corresponding external storage has been
12 // deallocated.
13 //
14 // Multiple threads can invoke const methods on a Slice without
15 // external synchronization, but if any of the threads may call a
16 // non-const method, all threads accessing the same Slice must use
17 // external synchronization.
18
19 #pragma once
20
21 #include <cassert>
22 #include <cstddef>
23 #include <cstdio>
24 #include <cstring>
25 #include <string>
26 #include <string_view> // RocksDB now requires C++17 support
27
28 #include "rocksdb/cleanable.h"
29
30 namespace ROCKSDB_NAMESPACE {
31
32 class Slice {
33 public:
34 // Create an empty slice.
35 Slice() : data_(""), size_(0) {}
36
37 // Create a slice that refers to d[0,n-1].
38 Slice(const char* d, size_t n) : data_(d), size_(n) {}
39
40 // Create a slice that refers to the contents of "s"
41 /* implicit */
42 Slice(const std::string& s) : data_(s.data()), size_(s.size()) {}
43
44 // Create a slice that refers to the same contents as "sv"
45 /* implicit */
46 Slice(const std::string_view& sv) : data_(sv.data()), size_(sv.size()) {}
47
48 // Create a slice that refers to s[0,strlen(s)-1]
49 /* implicit */
50 Slice(const char* s) : data_(s) { size_ = (s == nullptr) ? 0 : strlen(s); }
51
52 // Create a single slice from SliceParts using buf as storage.
53 // buf must exist as long as the returned Slice exists.
54 Slice(const struct SliceParts& parts, std::string* buf);
55
56 // Return a pointer to the beginning of the referenced data
57 const char* data() const { return data_; }
58
59 // Return the length (in bytes) of the referenced data
60 size_t size() const { return size_; }
61
62 // Return true iff the length of the referenced data is zero
63 bool empty() const { return size_ == 0; }
64
65 // Return the ith byte in the referenced data.
66 // REQUIRES: n < size()
67 char operator[](size_t n) const {
68 assert(n < size());
69 return data_[n];
70 }
71
72 // Change this slice to refer to an empty array
73 void clear() {
74 data_ = "";
75 size_ = 0;
76 }
77
78 // Drop the first "n" bytes from this slice.
79 void remove_prefix(size_t n) {
80 assert(n <= size());
81 data_ += n;
82 size_ -= n;
83 }
84
85 void remove_suffix(size_t n) {
86 assert(n <= size());
87 size_ -= n;
88 }
89
90 // Return a string that contains the copy of the referenced data.
91 // when hex is true, returns a string of twice the length hex encoded (0-9A-F)
92 std::string ToString(bool hex = false) const;
93
94 // Return a string_view that references the same data as this slice.
95 std::string_view ToStringView() const {
96 return std::string_view(data_, size_);
97 }
98
99 // Decodes the current slice interpreted as an hexadecimal string into result,
100 // if successful returns true, if this isn't a valid hex string
101 // (e.g not coming from Slice::ToString(true)) DecodeHex returns false.
102 // This slice is expected to have an even number of 0-9A-F characters
103 // also accepts lowercase (a-f)
104 bool DecodeHex(std::string* result) const;
105
106 // Three-way comparison. Returns value:
107 // < 0 iff "*this" < "b",
108 // == 0 iff "*this" == "b",
109 // > 0 iff "*this" > "b"
110 int compare(const Slice& b) const;
111
112 // Return true iff "x" is a prefix of "*this"
113 bool starts_with(const Slice& x) const {
114 return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
115 }
116
117 bool ends_with(const Slice& x) const {
118 return ((size_ >= x.size_) &&
119 (memcmp(data_ + size_ - x.size_, x.data_, x.size_) == 0));
120 }
121
122 // Compare two slices and returns the first byte where they differ
123 size_t difference_offset(const Slice& b) const;
124
125 // private: make these public for rocksdbjni access
126 const char* data_;
127 size_t size_;
128
129 // Intentionally copyable
130 };
131
132 /**
133 * A Slice that can be pinned with some cleanup tasks, which will be run upon
134 * ::Reset() or object destruction, whichever is invoked first. This can be used
135 * to avoid memcpy by having the PinnableSlice object referring to the data
136 * that is locked in the memory and release them after the data is consumed.
137 */
138 class PinnableSlice : public Slice, public Cleanable {
139 public:
140 PinnableSlice() { buf_ = &self_space_; }
141 explicit PinnableSlice(std::string* buf) { buf_ = buf; }
142
143 PinnableSlice(PinnableSlice&& other);
144 PinnableSlice& operator=(PinnableSlice&& other);
145
146 // No copy constructor and copy assignment allowed.
147 PinnableSlice(PinnableSlice&) = delete;
148 PinnableSlice& operator=(PinnableSlice&) = delete;
149
150 inline void PinSlice(const Slice& s, CleanupFunction f, void* arg1,
151 void* arg2) {
152 assert(!pinned_);
153 pinned_ = true;
154 data_ = s.data();
155 size_ = s.size();
156 RegisterCleanup(f, arg1, arg2);
157 assert(pinned_);
158 }
159
160 inline void PinSlice(const Slice& s, Cleanable* cleanable) {
161 assert(!pinned_);
162 pinned_ = true;
163 data_ = s.data();
164 size_ = s.size();
165 if (cleanable != nullptr) {
166 cleanable->DelegateCleanupsTo(this);
167 }
168 assert(pinned_);
169 }
170
171 inline void PinSelf(const Slice& slice) {
172 assert(!pinned_);
173 buf_->assign(slice.data(), slice.size());
174 data_ = buf_->data();
175 size_ = buf_->size();
176 assert(!pinned_);
177 }
178
179 inline void PinSelf() {
180 assert(!pinned_);
181 data_ = buf_->data();
182 size_ = buf_->size();
183 assert(!pinned_);
184 }
185
186 void remove_suffix(size_t n) {
187 assert(n <= size());
188 if (pinned_) {
189 size_ -= n;
190 } else {
191 buf_->erase(size() - n, n);
192 PinSelf();
193 }
194 }
195
196 void remove_prefix(size_t n) {
197 assert(n <= size());
198 if (pinned_) {
199 data_ += n;
200 size_ -= n;
201 } else {
202 buf_->erase(0, n);
203 PinSelf();
204 }
205 }
206
207 void Reset() {
208 Cleanable::Reset();
209 pinned_ = false;
210 size_ = 0;
211 }
212
213 inline std::string* GetSelf() { return buf_; }
214
215 inline bool IsPinned() const { return pinned_; }
216
217 private:
218 friend class PinnableSlice4Test;
219 std::string self_space_;
220 std::string* buf_;
221 bool pinned_ = false;
222 };
223
224 // A set of Slices that are virtually concatenated together. 'parts' points
225 // to an array of Slices. The number of elements in the array is 'num_parts'.
226 struct SliceParts {
227 SliceParts(const Slice* _parts, int _num_parts)
228 : parts(_parts), num_parts(_num_parts) {}
229 SliceParts() : parts(nullptr), num_parts(0) {}
230
231 const Slice* parts;
232 int num_parts;
233 };
234
235 inline bool operator==(const Slice& x, const Slice& y) {
236 return ((x.size() == y.size()) &&
237 (memcmp(x.data(), y.data(), x.size()) == 0));
238 }
239
240 inline bool operator!=(const Slice& x, const Slice& y) { return !(x == y); }
241
242 inline int Slice::compare(const Slice& b) const {
243 assert(data_ != nullptr && b.data_ != nullptr);
244 const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
245 int r = memcmp(data_, b.data_, min_len);
246 if (r == 0) {
247 if (size_ < b.size_)
248 r = -1;
249 else if (size_ > b.size_)
250 r = +1;
251 }
252 return r;
253 }
254
255 inline size_t Slice::difference_offset(const Slice& b) const {
256 size_t off = 0;
257 const size_t len = (size_ < b.size_) ? size_ : b.size_;
258 for (; off < len; off++) {
259 if (data_[off] != b.data_[off]) break;
260 }
261 return off;
262 }
263
264 } // namespace ROCKSDB_NAMESPACE