Coverage Report

Created: 2023-06-07 06:06

/src/LPM/external.protobuf/include/google/protobuf/string_block.h
Line
Count
Source (jump to first uncovered line)
1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2023 Google Inc.  All rights reserved.
3
// https://developers.google.com/protocol-buffers/
4
//
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
7
// met:
8
//
9
//     * Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
11
//     * Redistributions in binary form must reproduce the above
12
// copyright notice, this list of conditions and the following disclaimer
13
// in the documentation and/or other materials provided with the
14
// distribution.
15
//     * Neither the name of Google Inc. nor the names of its
16
// contributors may be used to endorse or promote products derived from
17
// this software without specific prior written permission.
18
//
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
//
31
// This file defines the internal StringBlock class
32
33
#ifndef GOOGLE_PROTOBUF_STRING_BLOCK_H__
34
#define GOOGLE_PROTOBUF_STRING_BLOCK_H__
35
36
#include <algorithm>
37
#include <cstddef>
38
#include <cstdint>
39
#include <string>
40
41
#include "absl/base/attributes.h"
42
#include "absl/log/absl_check.h"
43
#include "google/protobuf/arena_align.h"
44
#include "google/protobuf/port.h"
45
46
// Must be included last.
47
#include "google/protobuf/port_def.inc"
48
49
namespace google {
50
namespace protobuf {
51
namespace internal {
52
53
// StringBlock provides heap allocated, dynamically sized blocks (mini arenas)
54
// for allocating std::string instances. StringBlocks are allocated through
55
// the `New` function, and must be freed using the `Delete` function.
56
// StringBlocks are automatically sized from 256B to 8KB depending on the
57
// `next` instance provided in the `New` function to keep the average maximum
58
// unused space limited to 25%, or up to 4KB.
59
class alignas(std::string) StringBlock {
60
 public:
61
  StringBlock() = delete;
62
  StringBlock(const StringBlock&) = delete;
63
  StringBlock& operator=(const StringBlock&) = delete;
64
65
  // Allocates a new StringBlock pointing to `next`, which can be null.
66
  // The size of the returned block depends on the allocated size of `next`.
67
  static StringBlock* New(StringBlock* next);
68
69
  // Deletes `block`. `block` must not be null.
70
  static size_t Delete(StringBlock* block);
71
72
  StringBlock* next() const;
73
74
  // Returns the string instance at offset `offset`.
75
  // `offset` must be a multiple of sizeof(std::string), and be less than or
76
  // equal to `effective_size()`. `AtOffset(effective_size())` returns the
77
  // end of the allocated string instances and must not be de-referenced.
78
  ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* AtOffset(size_t offset);
79
80
  // Returns a pointer to the first string instance in this block.
81
  ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* begin();
82
83
  // Returns a pointer directly beyond the last string instance in this block.
84
  ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* end();
85
86
  // Returns the total allocation size of this instance.
87
0
  size_t allocated_size() const { return allocated_size_; }
88
89
  // Returns the effective size available for allocation string instances.
90
  // This value is guaranteed to be a multiple of sizeof(std::string), and
91
  // guaranteed to never be zero.
92
  size_t effective_size() const;
93
94
 private:
95
  static_assert(alignof(std::string) <= sizeof(void*), "");
96
  static_assert(alignof(std::string) <= ArenaAlignDefault::align, "");
97
98
  ~StringBlock() = default;
99
100
  explicit StringBlock(StringBlock* next, uint32_t size,
101
                       uint32_t next_size) noexcept
102
0
      : next_(next), allocated_size_(size), next_size_(next_size) {}
103
104
0
  static constexpr uint32_t min_size() { return size_t{256}; }
105
0
  static constexpr uint32_t max_size() { return size_t{8192}; }
106
107
  // Returns the size of the next block.
108
0
  size_t next_size() const { return next_size_; }
109
110
  StringBlock* const next_;
111
  const uint32_t allocated_size_;
112
  const uint32_t next_size_;
113
};
114
115
0
inline StringBlock* StringBlock::New(StringBlock* next) {
116
0
  // Compute required size, rounding down to a multiple of sizeof(std:string)
117
0
  // so that we can optimize the allocation path. I.e., we incur a (constant
118
0
  // size) MOD() operation cost here to avoid any MUL() later on.
119
0
  uint32_t size = min_size();
120
0
  uint32_t next_size = min_size();
121
0
  if (next) {
122
0
    size = next->next_size_;
123
0
    next_size = std::min(size * 2, max_size());
124
0
  }
125
0
  size -= (size - sizeof(StringBlock)) % sizeof(std::string);
126
0
  void* p = ::operator new(size);
127
0
  return new (p) StringBlock(next, size, next_size);
128
0
}
129
130
0
inline size_t StringBlock::Delete(StringBlock* block) {
131
0
  ABSL_DCHECK(block != nullptr);
132
0
  size_t size = block->allocated_size();
133
0
  internal::SizedDelete(block, size);
134
0
  return size;
135
0
}
136
137
0
inline StringBlock* StringBlock::next() const { return next_; }
138
139
0
inline size_t StringBlock::effective_size() const {
140
0
  return allocated_size_ - sizeof(StringBlock);
141
0
}
142
143
ABSL_ATTRIBUTE_RETURNS_NONNULL inline std::string* StringBlock::AtOffset(
144
0
    size_t offset) {
145
0
  ABSL_DCHECK_LE(offset, effective_size());
146
0
  return reinterpret_cast<std::string*>(reinterpret_cast<char*>(this + 1) +
147
0
                                        offset);
148
0
}
149
150
0
ABSL_ATTRIBUTE_RETURNS_NONNULL inline std::string* StringBlock::begin() {
151
0
  return AtOffset(0);
152
0
}
153
154
0
ABSL_ATTRIBUTE_RETURNS_NONNULL inline std::string* StringBlock::end() {
155
0
  return AtOffset(effective_size());
156
0
}
157
158
}  // namespace internal
159
}  // namespace protobuf
160
}  // namespace google
161
162
#include "google/protobuf/port_undef.inc"
163
164
#endif  // GOOGLE_PROTOBUF_STRING_BLOCK_H__