File indexing completed on 2025-01-31 10:12:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef GOOGLE_PROTOBUF_STRING_BLOCK_H__
0011 #define GOOGLE_PROTOBUF_STRING_BLOCK_H__
0012
0013 #include <algorithm>
0014 #include <cstddef>
0015 #include <cstdint>
0016 #include <string>
0017
0018 #include "absl/base/attributes.h"
0019 #include "absl/log/absl_check.h"
0020 #include "google/protobuf/arena_align.h"
0021 #include "google/protobuf/port.h"
0022
0023
0024 #include "google/protobuf/port_def.inc"
0025
0026 namespace google {
0027 namespace protobuf {
0028 namespace internal {
0029
0030
0031
0032
0033
0034
0035
0036 class alignas(std::string) StringBlock {
0037 public:
0038 StringBlock() = delete;
0039 StringBlock(const StringBlock&) = delete;
0040 StringBlock& operator=(const StringBlock&) = delete;
0041
0042
0043
0044
0045 static size_t NextSize(StringBlock* block);
0046
0047
0048
0049 static StringBlock* New(StringBlock* next);
0050
0051
0052
0053 static StringBlock* Emplace(void* p, size_t n, StringBlock* next);
0054
0055
0056
0057 static size_t Delete(StringBlock* block);
0058
0059 StringBlock* next() const;
0060
0061
0062
0063
0064
0065 ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* AtOffset(size_t offset);
0066
0067
0068 ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* begin();
0069
0070
0071 ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* end();
0072
0073
0074 size_t allocated_size() const { return allocated_size_; }
0075
0076
0077 bool heap_allocated() const { return heap_allocated_; }
0078
0079
0080
0081
0082 size_t effective_size() const;
0083
0084 private:
0085 using size_type = uint16_t;
0086
0087 static_assert(alignof(std::string) <= sizeof(void*), "");
0088 static_assert(alignof(std::string) <= ArenaAlignDefault::align, "");
0089
0090 ~StringBlock() = default;
0091
0092 explicit StringBlock(StringBlock* next, bool heap_allocated, size_type size,
0093 size_type next_size) noexcept
0094 : next_(next),
0095 allocated_size_(size),
0096 next_size_(next_size),
0097 heap_allocated_(heap_allocated) {}
0098
0099 static constexpr size_type min_size() { return size_type{256}; }
0100 static constexpr size_type max_size() { return size_type{8192}; }
0101
0102
0103
0104 static constexpr size_type RoundedSize(size_type size);
0105
0106
0107 size_t next_size() const { return next_size_; }
0108
0109 StringBlock* const next_;
0110 const size_type allocated_size_;
0111 const size_type next_size_;
0112 const bool heap_allocated_;
0113 };
0114
0115 constexpr StringBlock::size_type StringBlock::RoundedSize(size_type size) {
0116 return size - (size - sizeof(StringBlock)) % sizeof(std::string);
0117 }
0118
0119 inline size_t StringBlock::NextSize(StringBlock* block) {
0120 return block ? block->next_size() : min_size();
0121 }
0122
0123 inline StringBlock* StringBlock::Emplace(void* p, size_t n, StringBlock* next) {
0124 const auto count = static_cast<size_type>(n);
0125 ABSL_DCHECK_EQ(count, NextSize(next));
0126 size_type doubled = count * 2;
0127 size_type next_size = next ? std::min(doubled, max_size()) : min_size();
0128 return new (p) StringBlock(next, false, RoundedSize(count), next_size);
0129 }
0130
0131 inline StringBlock* StringBlock::New(StringBlock* next) {
0132
0133
0134
0135 size_type size = min_size();
0136 size_type next_size = min_size();
0137 if (next) {
0138 size = next->next_size_;
0139 next_size = std::min<size_type>(size * 2, max_size());
0140 }
0141 size = RoundedSize(size);
0142 void* p = ::operator new(size);
0143 return new (p) StringBlock(next, true, size, next_size);
0144 }
0145
0146 inline size_t StringBlock::Delete(StringBlock* block) {
0147 ABSL_DCHECK(block != nullptr);
0148 if (!block->heap_allocated_) return size_t{0};
0149 size_t size = block->allocated_size();
0150 internal::SizedDelete(block, size);
0151 return size;
0152 }
0153
0154 inline StringBlock* StringBlock::next() const { return next_; }
0155
0156 inline size_t StringBlock::effective_size() const {
0157 return allocated_size_ - sizeof(StringBlock);
0158 }
0159
0160 ABSL_ATTRIBUTE_RETURNS_NONNULL inline std::string* StringBlock::AtOffset(
0161 size_t offset) {
0162 ABSL_DCHECK_LE(offset, effective_size());
0163 return reinterpret_cast<std::string*>(reinterpret_cast<char*>(this + 1) +
0164 offset);
0165 }
0166
0167 ABSL_ATTRIBUTE_RETURNS_NONNULL inline std::string* StringBlock::begin() {
0168 return AtOffset(0);
0169 }
0170
0171 ABSL_ATTRIBUTE_RETURNS_NONNULL inline std::string* StringBlock::end() {
0172 return AtOffset(effective_size());
0173 }
0174
0175 }
0176 }
0177 }
0178
0179 #include "google/protobuf/port_undef.inc"
0180
0181 #endif