YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/byte_buffer.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#ifndef YB_UTIL_BYTE_BUFFER_H
15
#define YB_UTIL_BYTE_BUFFER_H
16
17
#include <cstddef>
18
#include <string>
19
20
#include "yb/util/slice.h"
21
22
namespace yb {
23
24
// Utility class to store arbitrary amount of byte with inplace buffer of specified size.
25
template <size_t SmallLen>
26
class ByteBuffer {
27
 public:
28
  static_assert(SmallLen >= sizeof(void*), "Too small buffer");
29
30
702M
  ByteBuffer() : size_(0) {}
31
32
431k
  explicit ByteBuffer(const std::string& str) {
33
431k
    Assign(str.c_str(), str.size());
34
431k
  }
35
36
  void operator=(const std::string& str) {
37
    Assign(str.c_str(), str.size());
38
  }
39
40
818M
  explicit ByteBuffer(const Slice& slice) {
41
818M
    Assign(slice.cdata(), slice.cend());
42
818M
  }
43
44
107
  void operator=(const Slice& slice) {
45
107
    Assign(slice.cdata(), slice.cend());
46
107
  }
47
48
1.04G
  ByteBuffer(const ByteBuffer<SmallLen>& rhs) {
49
1.04G
    Assign(rhs.ptr(), rhs.size_);
50
1.04G
  }
51
52
88.0M
  void operator=(const ByteBuffer<SmallLen>& rhs) {
53
88.0M
    Assign(rhs.ptr(), rhs.size_);
54
88.0M
  }
55
56
38.0M
  ByteBuffer(ByteBuffer<SmallLen>&& rhs) {
57
38.0M
    if (!rhs.big()) {
58
37.9M
      memcpy(small_buffer_, rhs.small_buffer_, rhs.size_);
59
37.9M
    } else {
60
108k
      capacity_ = rhs.capacity_;
61
108k
      big_buffer_ = rhs.big_buffer_;
62
108k
      rhs.capacity_ = SmallLen;
63
108k
    }
64
65
38.0M
    size_ = rhs.size_;
66
38.0M
    rhs.size_ = 0;
67
38.0M
  }
68
69
20.6M
  void operator=(ByteBuffer<SmallLen>&& rhs) {
70
20.6M
    if (!rhs.big()) {
71
20.6M
      memcpy(ptr(), rhs.small_buffer_, rhs.size_);
72
20.6M
    } else {
73
24.4k
      if (
big()827
) {
74
24.4k
        free(big_buffer_);
75
24.4k
      }
76
827
      capacity_ = rhs.capacity_;
77
827
      big_buffer_ = rhs.big_buffer_;
78
827
      rhs.capacity_ = SmallLen;
79
827
    }
80
81
20.6M
    size_ = rhs.size_;
82
20.6M
    rhs.size_ = 0;
83
20.6M
  }
84
85
2.61G
  ~ByteBuffer() {
86
2.61G
    if (big()) {
87
156M
      free(big_buffer_);
88
156M
    }
89
2.61G
  }
90
91
11.0G
  bool empty() const {
92
11.0G
    return size_ == 0;
93
11.0G
  }
94
95
3.58G
  size_t size() const {
96
3.58G
    return size_;
97
3.58G
  }
98
99
453M
  void Clear() {
100
453M
    size_ = 0;
101
453M
  }
102
103
153M
  char& Back() {
104
153M
    return ptr()[size_ - 1];
105
153M
  }
106
107
  char Back() const {
108
    return ptr()[size_ - 1];
109
  }
110
111
272
  char& operator[](size_t len) {
112
272
    return ptr()[len];
113
272
  }
114
115
  char operator[](size_t len) const {
116
    return ptr()[len];
117
  }
118
119
315M
  void PopBack() {
120
315M
    --size_;
121
315M
  }
122
123
1.56G
  void Truncate(size_t new_size) {
124
1.56G
    size_ = new_size;
125
1.56G
  }
126
127
  void Assign(const Slice& slice) {
128
    Assign(slice.cdata(), slice.cend());
129
  }
130
131
818M
  void Assign(const char* a, const char* b) {
132
818M
    Assign(a, b - a);
133
818M
  }
134
135
2.19G
  void Assign(const char* a, size_t size) {
136
2.19G
    DoAppend(0, a, size);
137
2.19G
  }
138
139
1.69G
  void Append(const Slice& slice) {
140
1.69G
    Append(slice.cdata(), slice.cend());
141
1.69G
  }
142
143
  template <size_t OtherSmallLen>
144
0
  void Append(const ByteBuffer<OtherSmallLen>& rhs) {
145
0
    Append(rhs.ptr(), rhs.size_);
146
0
  }
147
148
1.71G
  void Append(const char* a, const char* b) {
149
1.71G
    Append(a, b - a);
150
1.71G
  }
151
152
3.05G
  void Append(const char* a, size_t size) {
153
3.05G
    DoAppend(size_, a, size);
154
3.05G
  }
155
156
1.20G
  void Reserve(size_t capacity) {
157
1.20G
    EnsureCapacity(capacity, size_);
158
1.20G
  }
159
160
2.90G
  void PushBack(char ch) {
161
2.90G
    *(EnsureCapacity(size_ + 1, size_) + size_) = ch;
162
2.90G
    ++size_;
163
2.90G
  }
164
165
81.9M
  std::string ToStringBuffer() const {
166
81.9M
    return AsSlice().ToBuffer();
167
81.9M
  }
168
169
0
  std::string ToString() const {
170
0
    return AsSlice().ToDebugHexString();
171
0
  }
172
173
8.10G
  Slice AsSlice() const {
174
8.10G
    return Slice(ptr(), size_);
175
8.10G
  }
176
177
  // STL container compatibility
178
453M
  void clear() {
179
453M
    Clear();
180
453M
  }
181
182
  template <class... Args>
183
3.06G
  void append(Args&&... args) {
184
3.06G
    Append(std::forward<Args>(args)...);
185
3.06G
  }
Unexecuted instantiation: void yb::ByteBuffer<64ul>::append<yb::ByteBuffer<64ul> const&>(yb::ByteBuffer<64ul> const&)
void yb::ByteBuffer<64ul>::append<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
183
46.3M
  void append(Args&&... args) {
184
46.3M
    Append(std::forward<Args>(args)...);
185
46.3M
  }
void yb::ByteBuffer<64ul>::append<yb::Slice const&>(yb::Slice const&)
Line
Count
Source
183
1.65G
  void append(Args&&... args) {
184
1.65G
    Append(std::forward<Args>(args)...);
185
1.65G
  }
void yb::ByteBuffer<64ul>::append<char (&) [8], unsigned long>(char (&) [8], unsigned long&&)
Line
Count
Source
183
5.54M
  void append(Args&&... args) {
184
5.54M
    Append(std::forward<Args>(args)...);
185
5.54M
  }
void yb::ByteBuffer<64ul>::append<char (&) [4], unsigned long>(char (&) [4], unsigned long&&)
Line
Count
Source
183
77.8M
  void append(Args&&... args) {
184
77.8M
    Append(std::forward<Args>(args)...);
185
77.8M
  }
void yb::ByteBuffer<64ul>::append<char (&) [30], char*>(char (&) [30], char*&&)
Line
Count
Source
183
11.2M
  void append(Args&&... args) {
184
11.2M
    Append(std::forward<Args>(args)...);
185
11.2M
  }
void yb::ByteBuffer<64ul>::append<char (&) [16], unsigned long&>(char (&) [16], unsigned long&)
Line
Count
Source
183
821M
  void append(Args&&... args) {
184
821M
    Append(std::forward<Args>(args)...);
185
821M
  }
void yb::ByteBuffer<64ul>::append<char (&) [2], unsigned long>(char (&) [2], unsigned long&&)
Line
Count
Source
183
47.4M
  void append(Args&&... args) {
184
47.4M
    Append(std::forward<Args>(args)...);
185
47.4M
  }
void yb::ByteBuffer<64ul>::append<char const*, unsigned long>(char const*&&, unsigned long&&)
Line
Count
Source
183
196M
  void append(Args&&... args) {
184
196M
    Append(std::forward<Args>(args)...);
185
196M
  }
void yb::ByteBuffer<64ul>::append<char const*&, unsigned long&>(char const*&, unsigned long&)
Line
Count
Source
183
201M
  void append(Args&&... args) {
184
201M
    Append(std::forward<Args>(args)...);
185
201M
  }
186
187
  template <class... Args>
188
236M
  void assign(Args&&... args) {
189
236M
    Assign(std::forward<Args>(args)...);
190
236M
  }
Unexecuted instantiation: void yb::ByteBuffer<64ul>::assign<char const*&, unsigned long&>(char const*&, unsigned long&)
void yb::ByteBuffer<64ul>::assign<char const*, unsigned long>(char const*&&, unsigned long&&)
Line
Count
Source
188
236M
  void assign(Args&&... args) {
189
236M
    Assign(std::forward<Args>(args)...);
190
236M
  }
191
192
1.20G
  void reserve(size_t capacity) {
193
1.20G
    Reserve(capacity);
194
1.20G
  }
195
196
2.90G
  void push_back(char ch) {
197
2.90G
    PushBack(ch);
198
2.90G
  }
199
200
153M
  char& back() {
201
153M
    return Back();
202
153M
  }
203
204
  char back() const {
205
    return Back();
206
  }
207
208
315M
  void pop_back() {
209
315M
    PopBack();
210
315M
  }
211
212
 private:
213
5.22G
  void DoAppend(size_t keep_size, const char* a, size_t len) {
214
5.22G
    size_t new_size = keep_size + len;
215
5.22G
    memcpy(EnsureCapacity(new_size, keep_size) + keep_size, a, len);
216
5.22G
    size_ = new_size;
217
5.22G
  }
218
219
  // Ensures that buffer could contain at least capacity bytes.
220
  // In case of relocation, keep_size bytes will be copied.
221
9.28G
  char* EnsureCapacity(size_t capacity, size_t keep_size) {
222
9.28G
    if (capacity <= capacity_) {
223
9.13G
      return ptr();
224
9.13G
    }
225
226
153M
    bool was_big = big();
227
222M
    while ((capacity_ <<= 1ULL) < capacity) 
{}69.5M
228
153M
    char* new_buffer = static_cast<char*>(malloc(capacity_));
229
153M
    char*& big_buffer = big_buffer_;
230
153M
    if (was_big) {
231
151k
      memcpy(new_buffer, big_buffer, keep_size);
232
151k
      free(big_buffer);
233
153M
    } else {
234
153M
      memcpy(new_buffer, small_buffer_, keep_size);
235
153M
    }
236
153M
    return big_buffer = new_buffer;
237
9.28G
  }
238
239
21.2G
  bool big() const {
240
21.2G
    return capacity_ > SmallLen;
241
21.2G
  }
242
243
9.30G
  char* ptr() {
244
9.30G
    return !big() ? 
small_buffer_5.17G
:
big_buffer_4.13G
;
245
9.30G
  }
246
247
9.23G
  const char* ptr() const {
248
9.23G
    return !big() ? 
small_buffer_5.91G
:
big_buffer_3.31G
;
249
9.23G
  }
250
251
  size_t capacity_ = SmallLen;
252
  size_t size_;
253
  union {
254
    char small_buffer_[SmallLen];
255
    char* big_buffer_;
256
  };
257
};
258
259
template <size_t SmallLenLhs, size_t SmallLenRhs>
260
875M
bool operator<(const ByteBuffer<SmallLenLhs>& lhs, const ByteBuffer<SmallLenRhs>& rhs) {
261
875M
  return lhs.AsSlice().compare(rhs.AsSlice()) < 0;
262
875M
}
263
264
template <size_t SmallLenLhs, size_t SmallLenRhs>
265
210M
bool operator==(const ByteBuffer<SmallLenLhs>& lhs, const ByteBuffer<SmallLenRhs>& rhs) {
266
210M
  return lhs.AsSlice() == rhs.AsSlice();
267
210M
}
268
269
struct ByteBufferHash {
270
  typedef std::size_t result_type;
271
272
  template <size_t SmallLen>
273
202M
  result_type operator()(const ByteBuffer<SmallLen>& buffer) const {
274
202M
    return buffer.AsSlice().hash();
275
202M
  }
276
};
277
278
} // namespace yb
279
280
#endif // YB_UTIL_BYTE_BUFFER_H