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