]>
git.proxmox.com Git - ceph.git/blob - 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.
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
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.
26 #include <string_view> // RocksDB now requires C++17 support
28 #include "rocksdb/cleanable.h"
30 namespace ROCKSDB_NAMESPACE
{
34 // Create an empty slice.
35 Slice() : data_(""), size_(0) {}
37 // Create a slice that refers to d[0,n-1].
38 Slice(const char* d
, size_t n
) : data_(d
), size_(n
) {}
40 // Create a slice that refers to the contents of "s"
42 Slice(const std::string
& s
) : data_(s
.data()), size_(s
.size()) {}
44 // Create a slice that refers to the same contents as "sv"
46 Slice(const std::string_view
& sv
) : data_(sv
.data()), size_(sv
.size()) {}
48 // Create a slice that refers to s[0,strlen(s)-1]
50 Slice(const char* s
) : data_(s
) { size_
= (s
== nullptr) ? 0 : strlen(s
); }
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
);
56 // Return a pointer to the beginning of the referenced data
57 const char* data() const { return data_
; }
59 // Return the length (in bytes) of the referenced data
60 size_t size() const { return size_
; }
62 // Return true iff the length of the referenced data is zero
63 bool empty() const { return size_
== 0; }
65 // Return the ith byte in the referenced data.
66 // REQUIRES: n < size()
67 char operator[](size_t n
) const {
72 // Change this slice to refer to an empty array
78 // Drop the first "n" bytes from this slice.
79 void remove_prefix(size_t n
) {
85 void remove_suffix(size_t n
) {
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;
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_
);
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;
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;
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));
117 bool ends_with(const Slice
& x
) const {
118 return ((size_
>= x
.size_
) &&
119 (memcmp(data_
+ size_
- x
.size_
, x
.data_
, x
.size_
) == 0));
122 // Compare two slices and returns the first byte where they differ
123 size_t difference_offset(const Slice
& b
) const;
125 // private: make these public for rocksdbjni access
129 // Intentionally copyable
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.
138 class PinnableSlice
: public Slice
, public Cleanable
{
140 PinnableSlice() { buf_
= &self_space_
; }
141 explicit PinnableSlice(std::string
* buf
) { buf_
= buf
; }
143 PinnableSlice(PinnableSlice
&& other
);
144 PinnableSlice
& operator=(PinnableSlice
&& other
);
146 // No copy constructor and copy assignment allowed.
147 PinnableSlice(PinnableSlice
&) = delete;
148 PinnableSlice
& operator=(PinnableSlice
&) = delete;
150 inline void PinSlice(const Slice
& s
, CleanupFunction f
, void* arg1
,
156 RegisterCleanup(f
, arg1
, arg2
);
160 inline void PinSlice(const Slice
& s
, Cleanable
* cleanable
) {
165 if (cleanable
!= nullptr) {
166 cleanable
->DelegateCleanupsTo(this);
171 inline void PinSelf(const Slice
& slice
) {
173 buf_
->assign(slice
.data(), slice
.size());
174 data_
= buf_
->data();
175 size_
= buf_
->size();
179 inline void PinSelf() {
181 data_
= buf_
->data();
182 size_
= buf_
->size();
186 void remove_suffix(size_t n
) {
191 buf_
->erase(size() - n
, n
);
196 void remove_prefix(size_t n
) {
213 inline std::string
* GetSelf() { return buf_
; }
215 inline bool IsPinned() const { return pinned_
; }
218 friend class PinnableSlice4Test
;
219 std::string self_space_
;
221 bool pinned_
= false;
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'.
227 SliceParts(const Slice
* _parts
, int _num_parts
)
228 : parts(_parts
), num_parts(_num_parts
) {}
229 SliceParts() : parts(nullptr), num_parts(0) {}
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));
240 inline bool operator!=(const Slice
& x
, const Slice
& y
) { return !(x
== y
); }
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
);
249 else if (size_
> b
.size_
)
255 inline size_t Slice::difference_offset(const Slice
& b
) const {
257 const size_t len
= (size_
< b
.size_
) ? size_
: b
.size_
;
258 for (; off
< len
; off
++) {
259 if (data_
[off
] != b
.data_
[off
]) break;
264 } // namespace ROCKSDB_NAMESPACE