/proc/self/cwd/common/internal/byte_string.cc
Line | Count | Source |
1 | | // Copyright 2024 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "common/internal/byte_string.h" |
16 | | |
17 | | #include <cstddef> |
18 | | #include <cstdint> |
19 | | #include <cstring> |
20 | | #include <string> |
21 | | #include <tuple> |
22 | | #include <utility> |
23 | | |
24 | | #include "absl/base/nullability.h" |
25 | | #include "absl/base/optimization.h" |
26 | | #include "absl/functional/overload.h" |
27 | | #include "absl/hash/hash.h" |
28 | | #include "absl/log/absl_check.h" |
29 | | #include "absl/strings/cord.h" |
30 | | #include "absl/strings/match.h" |
31 | | #include "absl/strings/string_view.h" |
32 | | #include "absl/types/optional.h" |
33 | | #include "common/allocator.h" |
34 | | #include "common/internal/metadata.h" |
35 | | #include "common/internal/reference_count.h" |
36 | | #include "common/memory.h" |
37 | | #include "google/protobuf/arena.h" |
38 | | |
39 | | namespace cel::common_internal { |
40 | | |
41 | | namespace { |
42 | | |
43 | 0 | char* CopyCordToArray(const absl::Cord& cord, char* data) { |
44 | 0 | for (auto chunk : cord.Chunks()) { |
45 | 0 | std::memcpy(data, chunk.data(), chunk.size()); |
46 | 0 | data += chunk.size(); |
47 | 0 | } |
48 | 0 | return data; |
49 | 0 | } |
50 | | |
51 | | template <typename T> |
52 | | T ConsumeAndDestroy(T& object) { |
53 | | T consumed = std::move(object); |
54 | | object.~T(); // NOLINT(bugprone-use-after-move) |
55 | | return consumed; |
56 | | } |
57 | | |
58 | | } // namespace |
59 | | |
60 | | ByteString ByteString::Concat(const ByteString& lhs, const ByteString& rhs, |
61 | 2.72k | google::protobuf::Arena* absl_nonnull arena) { |
62 | 2.72k | ABSL_DCHECK(arena != nullptr); |
63 | | |
64 | 2.72k | if (lhs.empty()) { |
65 | 308 | return rhs; |
66 | 308 | } |
67 | 2.42k | if (rhs.empty()) { |
68 | 1.39k | return lhs; |
69 | 1.39k | } |
70 | | |
71 | 1.02k | if (lhs.GetKind() == ByteStringKind::kLarge || |
72 | 1.02k | rhs.GetKind() == ByteStringKind::kLarge) { |
73 | | // If either the left or right are absl::Cord, use absl::Cord. |
74 | 0 | absl::Cord result; |
75 | 0 | result.Append(lhs.ToCord()); |
76 | 0 | result.Append(rhs.ToCord()); |
77 | 0 | return ByteString(std::move(result)); |
78 | 0 | } |
79 | | |
80 | 1.02k | const size_t lhs_size = lhs.size(); |
81 | 1.02k | const size_t rhs_size = rhs.size(); |
82 | 1.02k | const size_t result_size = lhs_size + rhs_size; |
83 | 1.02k | ByteString result; |
84 | 1.02k | if (result_size <= kSmallByteStringCapacity) { |
85 | | // If the resulting string fits in inline storage, do it. |
86 | 225 | result.rep_.small.size = result_size; |
87 | 225 | result.rep_.small.arena = arena; |
88 | 225 | lhs.CopyToArray(result.rep_.small.data); |
89 | 225 | rhs.CopyToArray(result.rep_.small.data + lhs_size); |
90 | 802 | } else { |
91 | | // Otherwise allocate on the arena. |
92 | 802 | char* result_data = |
93 | 802 | reinterpret_cast<char*>(arena->AllocateAligned(result_size)); |
94 | 802 | lhs.CopyToArray(result_data); |
95 | 802 | rhs.CopyToArray(result_data + lhs_size); |
96 | 802 | result.rep_.medium.data = result_data; |
97 | 802 | result.rep_.medium.size = result_size; |
98 | 802 | result.rep_.medium.owner = |
99 | 802 | reinterpret_cast<uintptr_t>(arena) | kMetadataOwnerArenaBit; |
100 | 802 | result.rep_.header.kind = ByteStringKind::kMedium; |
101 | 802 | } |
102 | 1.02k | return result; |
103 | 1.02k | } |
104 | | |
105 | 30.3k | ByteString::ByteString(Allocator<> allocator, absl::string_view string) { |
106 | 30.3k | ABSL_DCHECK_LE(string.size(), max_size()); |
107 | 30.3k | auto* arena = allocator.arena(); |
108 | 30.3k | if (string.size() <= kSmallByteStringCapacity) { |
109 | 24.8k | SetSmall(arena, string); |
110 | 24.8k | } else { |
111 | 5.46k | SetMedium(arena, string); |
112 | 5.46k | } |
113 | 30.3k | } |
114 | | |
115 | 0 | ByteString::ByteString(Allocator<> allocator, const std::string& string) { |
116 | 0 | ABSL_DCHECK_LE(string.size(), max_size()); |
117 | 0 | auto* arena = allocator.arena(); |
118 | 0 | if (string.size() <= kSmallByteStringCapacity) { |
119 | 0 | SetSmall(arena, string); |
120 | 0 | } else { |
121 | 0 | SetMedium(arena, string); |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | 6 | ByteString::ByteString(Allocator<> allocator, std::string&& string) { |
126 | 6 | ABSL_DCHECK_LE(string.size(), max_size()); |
127 | 6 | auto* arena = allocator.arena(); |
128 | 6 | if (string.size() <= kSmallByteStringCapacity) { |
129 | 4 | SetSmall(arena, string); |
130 | 4 | } else { |
131 | 2 | SetMedium(arena, std::move(string)); |
132 | 2 | } |
133 | 6 | } |
134 | | |
135 | 0 | ByteString::ByteString(Allocator<> allocator, const absl::Cord& cord) { |
136 | 0 | ABSL_DCHECK_LE(cord.size(), max_size()); |
137 | 0 | auto* arena = allocator.arena(); |
138 | 0 | if (cord.size() <= kSmallByteStringCapacity) { |
139 | 0 | SetSmall(arena, cord); |
140 | 0 | } else if (arena != nullptr) { |
141 | 0 | SetMedium(arena, cord); |
142 | 0 | } else { |
143 | 0 | SetLarge(cord); |
144 | 0 | } |
145 | 0 | } |
146 | | |
147 | 128 | ByteString ByteString::Borrowed(Borrower borrower, absl::string_view string) { |
148 | 256 | ABSL_DCHECK(borrower != Borrower::None()) << "Borrowing from Owner::None()"; |
149 | 128 | auto* arena = borrower.arena(); |
150 | 128 | if (string.size() <= kSmallByteStringCapacity || arena != nullptr) { |
151 | 128 | return ByteString(arena, string); |
152 | 128 | } |
153 | 0 | const auto* refcount = BorrowerRelease(borrower); |
154 | | // A nullptr refcount indicates somebody called us to borrow something that |
155 | | // has no owner. If this is the case, we fallback to assuming operator |
156 | | // new/delete and convert it to a reference count. |
157 | 0 | if (refcount == nullptr) { |
158 | 0 | std::tie(refcount, string) = MakeReferenceCountedString(string); |
159 | 0 | } else { |
160 | 0 | StrongRef(*refcount); |
161 | 0 | } |
162 | 0 | return ByteString(refcount, string); |
163 | 128 | } |
164 | | |
165 | 0 | ByteString ByteString::Borrowed(Borrower borrower, const absl::Cord& cord) { |
166 | 0 | ABSL_DCHECK(borrower != Borrower::None()) << "Borrowing from Owner::None()"; |
167 | 0 | return ByteString(borrower.arena(), cord); |
168 | 0 | } |
169 | | |
170 | | ByteString::ByteString(const ReferenceCount* absl_nonnull refcount, |
171 | 0 | absl::string_view string) { |
172 | 0 | ABSL_DCHECK_LE(string.size(), max_size()); |
173 | 0 | SetMedium(string, reinterpret_cast<uintptr_t>(refcount) | |
174 | 0 | kMetadataOwnerReferenceCountBit); |
175 | 0 | } |
176 | | |
177 | | ByteString::ByteString(ByteString::ExternalStringTag, |
178 | 0 | absl::string_view string) { |
179 | 0 | if (string.size() <= kSmallByteStringCapacity) { |
180 | 0 | SetSmall(nullptr, string); |
181 | 0 | } else { |
182 | 0 | SetExternalMedium(string); |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | 0 | ByteString ByteString::FromExternal(absl::string_view string) { |
187 | 0 | return ByteString(ExternalStringTag{}, string); |
188 | 0 | } |
189 | | |
190 | 0 | google::protobuf::Arena* absl_nullable ByteString::GetArena() const { |
191 | 0 | switch (GetKind()) { |
192 | 0 | case ByteStringKind::kSmall: |
193 | 0 | return GetSmallArena(); |
194 | 0 | case ByteStringKind::kMedium: |
195 | 0 | return GetMediumArena(); |
196 | 0 | case ByteStringKind::kLarge: |
197 | 0 | return nullptr; |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | 5.86k | bool ByteString::empty() const { |
202 | 5.86k | switch (GetKind()) { |
203 | 3.52k | case ByteStringKind::kSmall: |
204 | 3.52k | return rep_.small.size == 0; |
205 | 2.34k | case ByteStringKind::kMedium: |
206 | 2.34k | return rep_.medium.size == 0; |
207 | 0 | case ByteStringKind::kLarge: |
208 | 0 | return GetLarge().empty(); |
209 | 5.86k | } |
210 | 5.86k | } |
211 | | |
212 | 2.05k | size_t ByteString::size() const { |
213 | 2.05k | switch (GetKind()) { |
214 | 1.11k | case ByteStringKind::kSmall: |
215 | 1.11k | return rep_.small.size; |
216 | 937 | case ByteStringKind::kMedium: |
217 | 937 | return rep_.medium.size; |
218 | 0 | case ByteStringKind::kLarge: |
219 | 0 | return GetLarge().size(); |
220 | 2.05k | } |
221 | 2.05k | } |
222 | | |
223 | 0 | absl::string_view ByteString::Flatten() { |
224 | 0 | switch (GetKind()) { |
225 | 0 | case ByteStringKind::kSmall: |
226 | 0 | return GetSmall(); |
227 | 0 | case ByteStringKind::kMedium: |
228 | 0 | return GetMedium(); |
229 | 0 | case ByteStringKind::kLarge: |
230 | 0 | return GetLarge().Flatten(); |
231 | 0 | } |
232 | 0 | } |
233 | | |
234 | 0 | absl::optional<absl::string_view> ByteString::TryFlat() const { |
235 | 0 | switch (GetKind()) { |
236 | 0 | case ByteStringKind::kSmall: |
237 | 0 | return GetSmall(); |
238 | 0 | case ByteStringKind::kMedium: |
239 | 0 | return GetMedium(); |
240 | 0 | case ByteStringKind::kLarge: |
241 | 0 | return GetLarge().TryFlat(); |
242 | 0 | } |
243 | 0 | } |
244 | | |
245 | 3.27k | bool ByteString::Equals(absl::string_view rhs) const { |
246 | 3.27k | return Visit(absl::Overload( |
247 | 3.27k | [&rhs](absl::string_view lhs) -> bool { return lhs == rhs; }, |
248 | 3.27k | [&rhs](const absl::Cord& lhs) -> bool { return lhs == rhs; })); |
249 | 3.27k | } |
250 | | |
251 | 0 | bool ByteString::Equals(const absl::Cord& rhs) const { |
252 | 0 | return Visit(absl::Overload( |
253 | 0 | [&rhs](absl::string_view lhs) -> bool { return lhs == rhs; }, |
254 | 0 | [&rhs](const absl::Cord& lhs) -> bool { return lhs == rhs; })); |
255 | 0 | } |
256 | | |
257 | 775 | int ByteString::Compare(absl::string_view rhs) const { |
258 | 775 | return Visit(absl::Overload( |
259 | 775 | [&rhs](absl::string_view lhs) -> int { return lhs.compare(rhs); }, |
260 | 775 | [&rhs](const absl::Cord& lhs) -> int { return lhs.Compare(rhs); })); |
261 | 775 | } |
262 | | |
263 | 0 | int ByteString::Compare(const absl::Cord& rhs) const { |
264 | 0 | return Visit(absl::Overload( |
265 | 0 | [&rhs](absl::string_view lhs) -> int { return -rhs.Compare(lhs); }, |
266 | 0 | [&rhs](const absl::Cord& lhs) -> int { return lhs.Compare(rhs); })); |
267 | 0 | } |
268 | | |
269 | 0 | bool ByteString::StartsWith(absl::string_view rhs) const { |
270 | 0 | return Visit(absl::Overload( |
271 | 0 | [&rhs](absl::string_view lhs) -> bool { |
272 | 0 | return absl::StartsWith(lhs, rhs); |
273 | 0 | }, |
274 | 0 | [&rhs](const absl::Cord& lhs) -> bool { return lhs.StartsWith(rhs); })); |
275 | 0 | } |
276 | | |
277 | 0 | bool ByteString::StartsWith(const absl::Cord& rhs) const { |
278 | 0 | return Visit(absl::Overload( |
279 | 0 | [&rhs](absl::string_view lhs) -> bool { |
280 | 0 | return lhs.size() >= rhs.size() && lhs.substr(0, rhs.size()) == rhs; |
281 | 0 | }, |
282 | 0 | [&rhs](const absl::Cord& lhs) -> bool { return lhs.StartsWith(rhs); })); |
283 | 0 | } |
284 | | |
285 | 0 | bool ByteString::EndsWith(absl::string_view rhs) const { |
286 | 0 | return Visit(absl::Overload( |
287 | 0 | [&rhs](absl::string_view lhs) -> bool { |
288 | 0 | return absl::EndsWith(lhs, rhs); |
289 | 0 | }, |
290 | 0 | [&rhs](const absl::Cord& lhs) -> bool { return lhs.EndsWith(rhs); })); |
291 | 0 | } |
292 | | |
293 | 0 | bool ByteString::EndsWith(const absl::Cord& rhs) const { |
294 | 0 | return Visit(absl::Overload( |
295 | 0 | [&rhs](absl::string_view lhs) -> bool { |
296 | 0 | return lhs.size() >= rhs.size() && |
297 | 0 | lhs.substr(lhs.size() - rhs.size()) == rhs; |
298 | 0 | }, |
299 | 0 | [&rhs](const absl::Cord& lhs) -> bool { return lhs.EndsWith(rhs); })); |
300 | 0 | } |
301 | | |
302 | | absl::optional<size_t> ByteString::Find(absl::string_view needle, |
303 | 0 | size_t pos) const { |
304 | 0 | ABSL_DCHECK_LE(pos, size()); |
305 | |
|
306 | 0 | return Visit(absl::Overload( |
307 | 0 | [&needle, pos](absl::string_view lhs) -> absl::optional<size_t> { |
308 | 0 | absl::string_view::size_type i = lhs.find(needle, pos); |
309 | 0 | if (i == absl::string_view::npos) { |
310 | 0 | return absl::nullopt; |
311 | 0 | } |
312 | 0 | return i; |
313 | 0 | }, |
314 | 0 | [&needle, pos](const absl::Cord& lhs) -> absl::optional<size_t> { |
315 | 0 | absl::Cord cord = lhs.Subcord(pos, lhs.size() - pos); |
316 | 0 | absl::Cord::CharIterator it = cord.Find(needle); |
317 | 0 | if (it == cord.char_end()) { |
318 | 0 | return absl::nullopt; |
319 | 0 | } |
320 | 0 | return pos + |
321 | 0 | static_cast<size_t>(absl::Cord::Distance(cord.char_begin(), it)); |
322 | 0 | })); |
323 | 0 | } |
324 | | |
325 | | absl::optional<size_t> ByteString::Find(const absl::Cord& needle, |
326 | 0 | size_t pos) const { |
327 | 0 | ABSL_DCHECK_LE(pos, size()); |
328 | |
|
329 | 0 | return Visit(absl::Overload( |
330 | 0 | [&needle, pos](absl::string_view lhs) -> absl::optional<size_t> { |
331 | 0 | if (auto flat_needle = needle.TryFlat(); flat_needle) { |
332 | 0 | absl::string_view::size_type i = lhs.find(*flat_needle, pos); |
333 | 0 | if (i == absl::string_view::npos) { |
334 | 0 | return absl::nullopt; |
335 | 0 | } |
336 | 0 | return i; |
337 | 0 | } |
338 | | // Needle is fragmented, we have to do a linear scan. |
339 | 0 | const size_t needle_size = needle.size(); |
340 | 0 | if (pos + needle_size > lhs.size()) { |
341 | 0 | return absl::nullopt; |
342 | 0 | } |
343 | 0 | if (ABSL_PREDICT_FALSE(needle_size == 0)) { |
344 | 0 | return pos; |
345 | 0 | } |
346 | | // Optimization: find the first chunk of the needle, then compare the |
347 | | // rest. If the first chunk is empty, `lhs.find` will return |
348 | | // `current_pos`, which correctly degrades to a linear scan. |
349 | 0 | absl::string_view first_chunk = *needle.Chunks().begin(); |
350 | 0 | absl::Cord rest_of_needle = needle.Subcord( |
351 | 0 | first_chunk.size(), needle_size - first_chunk.size()); |
352 | 0 | size_t current_pos = pos; |
353 | 0 | while (true) { |
354 | 0 | size_t found_pos = lhs.find(first_chunk, current_pos); |
355 | 0 | if (found_pos == absl::string_view::npos || |
356 | 0 | found_pos > lhs.size() - needle_size) { |
357 | 0 | return absl::nullopt; |
358 | 0 | } |
359 | 0 | if (lhs.substr(found_pos + first_chunk.size(), |
360 | 0 | rest_of_needle.size()) == rest_of_needle) { |
361 | 0 | return found_pos; |
362 | 0 | } |
363 | 0 | current_pos = found_pos + 1; |
364 | 0 | } |
365 | 0 | }, |
366 | 0 | [&needle, pos](const absl::Cord& lhs) -> absl::optional<size_t> { |
367 | 0 | absl::Cord cord = lhs.Subcord(pos, lhs.size() - pos); |
368 | 0 | absl::Cord::CharIterator it = cord.Find(needle); |
369 | 0 | if (it == cord.char_end()) { |
370 | 0 | return absl::nullopt; |
371 | 0 | } |
372 | 0 | return pos + |
373 | 0 | static_cast<size_t>(absl::Cord::Distance(cord.char_begin(), it)); |
374 | 0 | })); |
375 | 0 | } |
376 | | |
377 | 0 | ByteString ByteString::Substring(size_t pos, size_t npos) const { |
378 | 0 | ABSL_DCHECK_LE(npos, size()); |
379 | 0 | ABSL_DCHECK_LE(pos, npos); |
380 | |
|
381 | 0 | switch (GetKind()) { |
382 | 0 | case ByteStringKind::kSmall: { |
383 | 0 | ByteString result; |
384 | 0 | result.rep_.header.kind = ByteStringKind::kSmall; |
385 | 0 | result.rep_.small.size = npos - pos; |
386 | 0 | std::memcpy(result.rep_.small.data, rep_.small.data + pos, |
387 | 0 | result.rep_.small.size); |
388 | 0 | result.rep_.small.arena = GetSmallArena(); |
389 | 0 | return result; |
390 | 0 | } |
391 | 0 | case ByteStringKind::kMedium: { |
392 | 0 | ByteString result(*this); |
393 | 0 | result.rep_.medium.data += pos; |
394 | 0 | result.rep_.medium.size = npos - pos; |
395 | 0 | return result; |
396 | 0 | } |
397 | 0 | case ByteStringKind::kLarge: |
398 | 0 | return ByteString(GetLarge().Subcord(pos, npos - pos)); |
399 | 0 | } |
400 | 0 | } |
401 | | |
402 | 0 | void ByteString::RemovePrefix(size_t n) { |
403 | 0 | ABSL_DCHECK_LE(n, size()); |
404 | 0 | if (n == 0) { |
405 | 0 | return; |
406 | 0 | } |
407 | 0 | switch (GetKind()) { |
408 | 0 | case ByteStringKind::kSmall: |
409 | 0 | std::memmove(rep_.small.data, rep_.small.data + n, rep_.small.size - n); |
410 | 0 | rep_.small.size -= n; |
411 | 0 | break; |
412 | 0 | case ByteStringKind::kMedium: |
413 | 0 | rep_.medium.data += n; |
414 | 0 | rep_.medium.size -= n; |
415 | 0 | if (rep_.medium.size <= kSmallByteStringCapacity) { |
416 | 0 | const auto* refcount = GetMediumReferenceCount(); |
417 | 0 | SetSmall(GetMediumArena(), GetMedium()); |
418 | 0 | StrongUnref(refcount); |
419 | 0 | } |
420 | 0 | break; |
421 | 0 | case ByteStringKind::kLarge: { |
422 | 0 | auto& large = GetLarge(); |
423 | 0 | const auto large_size = large.size(); |
424 | 0 | const auto new_large_pos = n; |
425 | 0 | const auto new_large_size = large_size - n; |
426 | 0 | large = large.Subcord(new_large_pos, new_large_size); |
427 | 0 | if (new_large_size <= kSmallByteStringCapacity) { |
428 | 0 | auto large_copy = std::move(large); |
429 | 0 | DestroyLarge(); |
430 | 0 | SetSmall(nullptr, large_copy); |
431 | 0 | } |
432 | 0 | } break; |
433 | 0 | } |
434 | 0 | } |
435 | | |
436 | 0 | void ByteString::RemoveSuffix(size_t n) { |
437 | 0 | ABSL_DCHECK_LE(n, size()); |
438 | 0 | if (n == 0) { |
439 | 0 | return; |
440 | 0 | } |
441 | 0 | switch (GetKind()) { |
442 | 0 | case ByteStringKind::kSmall: |
443 | 0 | rep_.small.size -= n; |
444 | 0 | break; |
445 | 0 | case ByteStringKind::kMedium: |
446 | 0 | rep_.medium.size -= n; |
447 | 0 | if (rep_.medium.size <= kSmallByteStringCapacity) { |
448 | 0 | const auto* refcount = GetMediumReferenceCount(); |
449 | 0 | SetSmall(GetMediumArena(), GetMedium()); |
450 | 0 | StrongUnref(refcount); |
451 | 0 | } |
452 | 0 | break; |
453 | 0 | case ByteStringKind::kLarge: { |
454 | 0 | auto& large = GetLarge(); |
455 | 0 | const auto large_size = large.size(); |
456 | 0 | const auto new_large_pos = 0; |
457 | 0 | const auto new_large_size = large_size - n; |
458 | 0 | large = large.Subcord(new_large_pos, new_large_size); |
459 | 0 | if (new_large_size <= kSmallByteStringCapacity) { |
460 | 0 | auto large_copy = std::move(large); |
461 | 0 | DestroyLarge(); |
462 | 0 | SetSmall(nullptr, large_copy); |
463 | 0 | } |
464 | 0 | } break; |
465 | 0 | } |
466 | 0 | } |
467 | | |
468 | 2.05k | void ByteString::CopyToArray(char* absl_nonnull out) const { |
469 | 2.05k | ABSL_DCHECK(out != nullptr); |
470 | | |
471 | 2.05k | switch (GetKind()) { |
472 | 1.11k | case ByteStringKind::kSmall: { |
473 | 1.11k | absl::string_view small = GetSmall(); |
474 | 1.11k | std::memcpy(out, small.data(), small.size()); |
475 | 1.11k | } break; |
476 | 937 | case ByteStringKind::kMedium: { |
477 | 937 | absl::string_view medium = GetMedium(); |
478 | 937 | std::memcpy(out, medium.data(), medium.size()); |
479 | 937 | } break; |
480 | 0 | case ByteStringKind::kLarge: { |
481 | 0 | const absl::Cord& large = GetLarge(); |
482 | 0 | (CopyCordToArray)(large, out); |
483 | 0 | } break; |
484 | 2.05k | } |
485 | 2.05k | } |
486 | | |
487 | 19.4k | std::string ByteString::ToString() const { |
488 | 19.4k | switch (GetKind()) { |
489 | 17.0k | case ByteStringKind::kSmall: |
490 | 17.0k | return std::string(GetSmall()); |
491 | 2.44k | case ByteStringKind::kMedium: |
492 | 2.44k | return std::string(GetMedium()); |
493 | 0 | case ByteStringKind::kLarge: |
494 | 0 | return static_cast<std::string>(GetLarge()); |
495 | 19.4k | } |
496 | 19.4k | } |
497 | | |
498 | 0 | void ByteString::CopyToString(std::string* absl_nonnull out) const { |
499 | 0 | ABSL_DCHECK(out != nullptr); |
500 | |
|
501 | 0 | switch (GetKind()) { |
502 | 0 | case ByteStringKind::kSmall: |
503 | 0 | out->assign(GetSmall()); |
504 | 0 | break; |
505 | 0 | case ByteStringKind::kMedium: |
506 | 0 | out->assign(GetMedium()); |
507 | 0 | break; |
508 | 0 | case ByteStringKind::kLarge: |
509 | 0 | absl::CopyCordToString(GetLarge(), out); |
510 | 0 | break; |
511 | 0 | } |
512 | 0 | } |
513 | | |
514 | 0 | void ByteString::AppendToString(std::string* absl_nonnull out) const { |
515 | 0 | ABSL_DCHECK(out != nullptr); |
516 | |
|
517 | 0 | switch (GetKind()) { |
518 | 0 | case ByteStringKind::kSmall: |
519 | 0 | out->append(GetSmall()); |
520 | 0 | break; |
521 | 0 | case ByteStringKind::kMedium: |
522 | 0 | out->append(GetMedium()); |
523 | 0 | break; |
524 | 0 | case ByteStringKind::kLarge: |
525 | 0 | absl::AppendCordToString(GetLarge(), out); |
526 | 0 | break; |
527 | 0 | } |
528 | 0 | } |
529 | | |
530 | | namespace { |
531 | | |
532 | | struct ReferenceCountReleaser { |
533 | | const ReferenceCount* absl_nonnull refcount; |
534 | | |
535 | 0 | void operator()() const { StrongUnref(*refcount); } |
536 | | }; |
537 | | |
538 | | } // namespace |
539 | | |
540 | 0 | absl::Cord ByteString::ToCord() const& { |
541 | 0 | switch (GetKind()) { |
542 | 0 | case ByteStringKind::kSmall: |
543 | 0 | return absl::Cord(GetSmall()); |
544 | 0 | case ByteStringKind::kMedium: { |
545 | 0 | const auto* refcount = GetMediumReferenceCount(); |
546 | 0 | if (refcount != nullptr) { |
547 | 0 | StrongRef(*refcount); |
548 | 0 | return absl::MakeCordFromExternal(GetMedium(), |
549 | 0 | ReferenceCountReleaser{refcount}); |
550 | 0 | } |
551 | 0 | return absl::Cord(GetMedium()); |
552 | 0 | } |
553 | 0 | case ByteStringKind::kLarge: |
554 | 0 | return GetLarge(); |
555 | 0 | } |
556 | 0 | } |
557 | | |
558 | 0 | absl::Cord ByteString::ToCord() && { |
559 | 0 | switch (GetKind()) { |
560 | 0 | case ByteStringKind::kSmall: |
561 | 0 | return absl::Cord(GetSmall()); |
562 | 0 | case ByteStringKind::kMedium: { |
563 | 0 | const auto* refcount = GetMediumReferenceCount(); |
564 | 0 | if (refcount != nullptr) { |
565 | 0 | auto medium = GetMedium(); |
566 | 0 | SetSmallEmpty(nullptr); |
567 | 0 | return absl::MakeCordFromExternal(medium, |
568 | 0 | ReferenceCountReleaser{refcount}); |
569 | 0 | } |
570 | 0 | return absl::Cord(GetMedium()); |
571 | 0 | } |
572 | 0 | case ByteStringKind::kLarge: |
573 | 0 | return GetLarge(); |
574 | 0 | } |
575 | 0 | } |
576 | | |
577 | 0 | void ByteString::CopyToCord(absl::Cord* absl_nonnull out) const { |
578 | 0 | ABSL_DCHECK(out != nullptr); |
579 | |
|
580 | 0 | switch (GetKind()) { |
581 | 0 | case ByteStringKind::kSmall: |
582 | 0 | *out = absl::Cord(GetSmall()); |
583 | 0 | break; |
584 | 0 | case ByteStringKind::kMedium: { |
585 | 0 | const auto* refcount = GetMediumReferenceCount(); |
586 | 0 | if (refcount != nullptr) { |
587 | 0 | StrongRef(*refcount); |
588 | 0 | *out = absl::MakeCordFromExternal(GetMedium(), |
589 | 0 | ReferenceCountReleaser{refcount}); |
590 | 0 | } else { |
591 | 0 | *out = absl::Cord(GetMedium()); |
592 | 0 | } |
593 | 0 | } break; |
594 | 0 | case ByteStringKind::kLarge: |
595 | 0 | *out = GetLarge(); |
596 | 0 | break; |
597 | 0 | } |
598 | 0 | } |
599 | | |
600 | 0 | void ByteString::AppendToCord(absl::Cord* absl_nonnull out) const { |
601 | 0 | ABSL_DCHECK(out != nullptr); |
602 | |
|
603 | 0 | switch (GetKind()) { |
604 | 0 | case ByteStringKind::kSmall: |
605 | 0 | out->Append(GetSmall()); |
606 | 0 | break; |
607 | 0 | case ByteStringKind::kMedium: { |
608 | 0 | const auto* refcount = GetMediumReferenceCount(); |
609 | 0 | if (refcount != nullptr) { |
610 | 0 | StrongRef(*refcount); |
611 | 0 | out->Append(absl::MakeCordFromExternal( |
612 | 0 | GetMedium(), ReferenceCountReleaser{refcount})); |
613 | 0 | } else { |
614 | 0 | out->Append(GetMedium()); |
615 | 0 | } |
616 | 0 | } break; |
617 | 0 | case ByteStringKind::kLarge: |
618 | 0 | out->Append(GetLarge()); |
619 | 0 | break; |
620 | 0 | } |
621 | 0 | } |
622 | | |
623 | | absl::string_view ByteString::ToStringView( |
624 | 0 | std::string* absl_nonnull scratch) const { |
625 | 0 | ABSL_DCHECK(scratch != nullptr); |
626 | |
|
627 | 0 | switch (GetKind()) { |
628 | 0 | case ByteStringKind::kSmall: |
629 | 0 | return GetSmall(); |
630 | 0 | case ByteStringKind::kMedium: |
631 | 0 | return GetMedium(); |
632 | 0 | case ByteStringKind::kLarge: |
633 | 0 | if (auto flat = GetLarge().TryFlat(); flat) { |
634 | 0 | return *flat; |
635 | 0 | } |
636 | 0 | absl::CopyCordToString(GetLarge(), scratch); |
637 | 0 | return absl::string_view(*scratch); |
638 | 0 | } |
639 | 0 | } |
640 | | |
641 | 0 | absl::string_view ByteString::AsStringView() const { |
642 | 0 | const ByteStringKind kind = GetKind(); |
643 | 0 | ABSL_CHECK(kind == ByteStringKind::kSmall || // Crash OK |
644 | 0 | kind == ByteStringKind::kMedium); |
645 | 0 | switch (kind) { |
646 | 0 | case ByteStringKind::kSmall: |
647 | 0 | return GetSmall(); |
648 | 0 | case ByteStringKind::kMedium: |
649 | 0 | return GetMedium(); |
650 | 0 | case ByteStringKind::kLarge: |
651 | 0 | ABSL_UNREACHABLE(); |
652 | 0 | } |
653 | 0 | } |
654 | | |
655 | | google::protobuf::Arena* absl_nullable ByteString::GetMediumArena( |
656 | 284 | const MediumByteStringRep& rep) { |
657 | 284 | if ((rep.owner & kMetadataOwnerBits) == kMetadataOwnerArenaBit) { |
658 | 56 | return reinterpret_cast<google::protobuf::Arena*>(rep.owner & |
659 | 56 | kMetadataOwnerPointerMask); |
660 | 56 | } |
661 | 228 | return nullptr; |
662 | 284 | } |
663 | | |
664 | | const ReferenceCount* absl_nullable ByteString::GetMediumReferenceCount( |
665 | 97.7k | const MediumByteStringRep& rep) { |
666 | 97.7k | if ((rep.owner & kMetadataOwnerBits) == kMetadataOwnerReferenceCountBit) { |
667 | 35.9k | return reinterpret_cast<const ReferenceCount*>(rep.owner & |
668 | 35.9k | kMetadataOwnerPointerMask); |
669 | 35.9k | } |
670 | 61.8k | return nullptr; |
671 | 97.7k | } |
672 | | |
673 | | void ByteString::Construct(const ByteString& other, |
674 | 14.5k | absl::optional<Allocator<>> allocator) { |
675 | 14.5k | switch (other.GetKind()) { |
676 | 2.38k | case ByteStringKind::kSmall: |
677 | 2.38k | rep_.small = other.rep_.small; |
678 | 2.38k | if (allocator.has_value()) { |
679 | 0 | rep_.small.arena = allocator->arena(); |
680 | 0 | } |
681 | 2.38k | break; |
682 | 12.1k | case ByteStringKind::kMedium: |
683 | 12.1k | if (allocator.has_value() && |
684 | 0 | allocator->arena() != other.GetMediumArena()) { |
685 | 0 | SetMedium(allocator->arena(), other.GetMedium()); |
686 | 12.1k | } else { |
687 | 12.1k | rep_.medium = other.rep_.medium; |
688 | 12.1k | StrongRef(GetMediumReferenceCount()); |
689 | 12.1k | } |
690 | 12.1k | break; |
691 | 0 | case ByteStringKind::kLarge: |
692 | 0 | if (allocator.has_value() && allocator->arena() != nullptr) { |
693 | 0 | SetMedium(allocator->arena(), other.GetLarge()); |
694 | 0 | } else { |
695 | 0 | SetLarge(other.GetLarge()); |
696 | 0 | } |
697 | 0 | break; |
698 | 14.5k | } |
699 | 14.5k | } |
700 | | |
701 | | void ByteString::Construct(ByteString& other, |
702 | 103k | absl::optional<Allocator<>> allocator) { |
703 | 103k | switch (other.GetKind()) { |
704 | 44.5k | case ByteStringKind::kSmall: |
705 | 44.5k | rep_.small = other.rep_.small; |
706 | 44.5k | if (allocator.has_value()) { |
707 | 0 | rep_.small.arena = allocator->arena(); |
708 | 0 | } |
709 | 44.5k | break; |
710 | 59.0k | case ByteStringKind::kMedium: |
711 | 59.0k | if (allocator.has_value() && |
712 | 0 | allocator->arena() != other.GetMediumArena()) { |
713 | 0 | SetMedium(allocator->arena(), other.GetMedium()); |
714 | 59.0k | } else { |
715 | 59.0k | rep_.medium = other.rep_.medium; |
716 | 59.0k | other.rep_.medium.owner = 0; |
717 | 59.0k | } |
718 | 59.0k | break; |
719 | 0 | case ByteStringKind::kLarge: |
720 | 0 | if (allocator.has_value() && allocator->arena() != nullptr) { |
721 | 0 | SetMedium(allocator->arena(), other.GetLarge()); |
722 | 0 | } else { |
723 | 0 | SetLarge(std::move(other.GetLarge())); |
724 | 0 | } |
725 | 0 | break; |
726 | 103k | } |
727 | 103k | } |
728 | | |
729 | 324 | void ByteString::CopyFrom(const ByteString& other) { |
730 | 324 | ABSL_DCHECK_NE(&other, this); |
731 | | |
732 | 324 | switch (other.GetKind()) { |
733 | 239 | case ByteStringKind::kSmall: |
734 | 239 | switch (GetKind()) { |
735 | 239 | case ByteStringKind::kSmall: |
736 | 239 | break; |
737 | 0 | case ByteStringKind::kMedium: |
738 | 0 | DestroyMedium(); |
739 | 0 | break; |
740 | 0 | case ByteStringKind::kLarge: |
741 | 0 | DestroyLarge(); |
742 | 0 | break; |
743 | 239 | } |
744 | 239 | rep_.small = other.rep_.small; |
745 | 239 | break; |
746 | 85 | case ByteStringKind::kMedium: |
747 | 85 | switch (GetKind()) { |
748 | 85 | case ByteStringKind::kSmall: |
749 | 85 | rep_.medium = other.rep_.medium; |
750 | 85 | StrongRef(GetMediumReferenceCount()); |
751 | 85 | break; |
752 | 0 | case ByteStringKind::kMedium: |
753 | 0 | StrongRef(other.GetMediumReferenceCount()); |
754 | 0 | DestroyMedium(); |
755 | 0 | rep_.medium = other.rep_.medium; |
756 | 0 | break; |
757 | 0 | case ByteStringKind::kLarge: |
758 | 0 | DestroyLarge(); |
759 | 0 | rep_.medium = other.rep_.medium; |
760 | 0 | StrongRef(GetMediumReferenceCount()); |
761 | 0 | break; |
762 | 85 | } |
763 | 85 | break; |
764 | 85 | case ByteStringKind::kLarge: |
765 | 0 | switch (GetKind()) { |
766 | 0 | case ByteStringKind::kSmall: |
767 | 0 | SetLarge(other.GetLarge()); |
768 | 0 | break; |
769 | 0 | case ByteStringKind::kMedium: |
770 | 0 | DestroyMedium(); |
771 | 0 | SetLarge(other.GetLarge()); |
772 | 0 | break; |
773 | 0 | case ByteStringKind::kLarge: |
774 | 0 | GetLarge() = other.GetLarge(); |
775 | 0 | break; |
776 | 0 | } |
777 | 0 | break; |
778 | 324 | } |
779 | 324 | } |
780 | | |
781 | 430 | void ByteString::MoveFrom(ByteString& other) { |
782 | 430 | ABSL_DCHECK_NE(&other, this); |
783 | | |
784 | 430 | switch (other.GetKind()) { |
785 | 0 | case ByteStringKind::kSmall: |
786 | 0 | switch (GetKind()) { |
787 | 0 | case ByteStringKind::kSmall: |
788 | 0 | break; |
789 | 0 | case ByteStringKind::kMedium: |
790 | 0 | DestroyMedium(); |
791 | 0 | break; |
792 | 0 | case ByteStringKind::kLarge: |
793 | 0 | DestroyLarge(); |
794 | 0 | break; |
795 | 0 | } |
796 | 0 | rep_.small = other.rep_.small; |
797 | 0 | break; |
798 | 430 | case ByteStringKind::kMedium: |
799 | 430 | switch (GetKind()) { |
800 | 0 | case ByteStringKind::kSmall: |
801 | 0 | rep_.medium = other.rep_.medium; |
802 | 0 | break; |
803 | 430 | case ByteStringKind::kMedium: |
804 | 430 | DestroyMedium(); |
805 | 430 | rep_.medium = other.rep_.medium; |
806 | 430 | break; |
807 | 0 | case ByteStringKind::kLarge: |
808 | 0 | DestroyLarge(); |
809 | 0 | rep_.medium = other.rep_.medium; |
810 | 0 | break; |
811 | 430 | } |
812 | 430 | other.rep_.medium.owner = 0; |
813 | 430 | break; |
814 | 0 | case ByteStringKind::kLarge: |
815 | 0 | switch (GetKind()) { |
816 | 0 | case ByteStringKind::kSmall: |
817 | 0 | SetLarge(std::move(other.GetLarge())); |
818 | 0 | break; |
819 | 0 | case ByteStringKind::kMedium: |
820 | 0 | DestroyMedium(); |
821 | 0 | SetLarge(std::move(other.GetLarge())); |
822 | 0 | break; |
823 | 0 | case ByteStringKind::kLarge: |
824 | 0 | GetLarge() = std::move(other.GetLarge()); |
825 | 0 | break; |
826 | 0 | } |
827 | 0 | break; |
828 | 430 | } |
829 | 430 | } |
830 | | |
831 | 0 | ByteString ByteString::Clone(google::protobuf::Arena* absl_nonnull arena) const { |
832 | 0 | ABSL_DCHECK(arena != nullptr); |
833 | |
|
834 | 0 | switch (GetKind()) { |
835 | 0 | case ByteStringKind::kSmall: |
836 | 0 | return ByteString(arena, GetSmall()); |
837 | 0 | case ByteStringKind::kMedium: { |
838 | 0 | google::protobuf::Arena* absl_nullable other_arena = GetMediumArena(); |
839 | 0 | if (arena != nullptr) { |
840 | 0 | if (arena == other_arena) { |
841 | 0 | return *this; |
842 | 0 | } |
843 | 0 | return ByteString(arena, GetMedium()); |
844 | 0 | } |
845 | 0 | if (other_arena != nullptr) { |
846 | 0 | return ByteString(arena, GetMedium()); |
847 | 0 | } |
848 | 0 | return *this; |
849 | 0 | } |
850 | 0 | case ByteStringKind::kLarge: |
851 | 0 | return ByteString(arena, GetLarge()); |
852 | 0 | } |
853 | 0 | } |
854 | | |
855 | 1.54k | void ByteString::HashValue(absl::HashState state) const { |
856 | 1.54k | switch (GetKind()) { |
857 | 1.06k | case ByteStringKind::kSmall: |
858 | 1.06k | absl::HashState::combine(std::move(state), GetSmall()); |
859 | 1.06k | break; |
860 | 479 | case ByteStringKind::kMedium: |
861 | 479 | absl::HashState::combine(std::move(state), GetMedium()); |
862 | 479 | break; |
863 | 0 | case ByteStringKind::kLarge: |
864 | 0 | absl::HashState::combine(std::move(state), GetLarge()); |
865 | 0 | break; |
866 | 1.54k | } |
867 | 1.54k | } |
868 | | |
869 | 0 | void ByteString::Swap(ByteString& other) { |
870 | 0 | ABSL_DCHECK_NE(&other, this); |
871 | 0 | using std::swap; |
872 | |
|
873 | 0 | switch (other.GetKind()) { |
874 | 0 | case ByteStringKind::kSmall: |
875 | 0 | switch (GetKind()) { |
876 | 0 | case ByteStringKind::kSmall: |
877 | | // small <=> small |
878 | 0 | swap(rep_.small, other.rep_.small); |
879 | 0 | break; |
880 | 0 | case ByteStringKind::kMedium: |
881 | | // medium <=> small |
882 | 0 | swap(rep_, other.rep_); |
883 | 0 | break; |
884 | 0 | case ByteStringKind::kLarge: { |
885 | 0 | absl::Cord cord = std::move(GetLarge()); |
886 | 0 | DestroyLarge(); |
887 | 0 | rep_ = other.rep_; |
888 | 0 | other.SetLarge(std::move(cord)); |
889 | 0 | } break; |
890 | 0 | } |
891 | 0 | break; |
892 | 0 | case ByteStringKind::kMedium: |
893 | 0 | switch (GetKind()) { |
894 | 0 | case ByteStringKind::kSmall: |
895 | 0 | swap(rep_, other.rep_); |
896 | 0 | break; |
897 | 0 | case ByteStringKind::kMedium: |
898 | 0 | swap(rep_.medium, other.rep_.medium); |
899 | 0 | break; |
900 | 0 | case ByteStringKind::kLarge: { |
901 | 0 | absl::Cord cord = std::move(GetLarge()); |
902 | 0 | DestroyLarge(); |
903 | 0 | rep_ = other.rep_; |
904 | 0 | other.SetLarge(std::move(cord)); |
905 | 0 | } break; |
906 | 0 | } |
907 | 0 | break; |
908 | 0 | case ByteStringKind::kLarge: |
909 | 0 | switch (GetKind()) { |
910 | 0 | case ByteStringKind::kSmall: { |
911 | 0 | absl::Cord cord = std::move(other.GetLarge()); |
912 | 0 | other.DestroyLarge(); |
913 | 0 | other.rep_.small = rep_.small; |
914 | 0 | SetLarge(std::move(cord)); |
915 | 0 | } break; |
916 | 0 | case ByteStringKind::kMedium: { |
917 | 0 | absl::Cord cord = std::move(other.GetLarge()); |
918 | 0 | other.DestroyLarge(); |
919 | 0 | other.rep_.medium = rep_.medium; |
920 | 0 | SetLarge(std::move(cord)); |
921 | 0 | } break; |
922 | 0 | case ByteStringKind::kLarge: |
923 | 0 | swap(GetLarge(), other.GetLarge()); |
924 | 0 | break; |
925 | 0 | } |
926 | 0 | break; |
927 | 0 | } |
928 | 0 | } |
929 | | |
930 | 136k | void ByteString::Destroy() { |
931 | 136k | switch (GetKind()) { |
932 | 60.8k | case ByteStringKind::kSmall: |
933 | 60.8k | break; |
934 | 75.9k | case ByteStringKind::kMedium: |
935 | 75.9k | DestroyMedium(); |
936 | 75.9k | break; |
937 | 0 | case ByteStringKind::kLarge: |
938 | 0 | DestroyLarge(); |
939 | 0 | break; |
940 | 136k | } |
941 | 136k | } |
942 | | |
943 | | void ByteString::SetSmall(google::protobuf::Arena* absl_nullable arena, |
944 | 24.8k | absl::string_view string) { |
945 | 24.8k | ABSL_DCHECK_LE(string.size(), kSmallByteStringCapacity); |
946 | 24.8k | rep_.header.kind = ByteStringKind::kSmall; |
947 | 24.8k | rep_.small.size = string.size(); |
948 | 24.8k | rep_.small.arena = arena; |
949 | 24.8k | std::memcpy(rep_.small.data, string.data(), rep_.small.size); |
950 | 24.8k | } |
951 | | |
952 | | void ByteString::SetSmall(google::protobuf::Arena* absl_nullable arena, |
953 | 0 | const absl::Cord& cord) { |
954 | 0 | ABSL_DCHECK_LE(cord.size(), kSmallByteStringCapacity); |
955 | 0 | rep_.header.kind = ByteStringKind::kSmall; |
956 | 0 | rep_.small.size = cord.size(); |
957 | 0 | rep_.small.arena = arena; |
958 | 0 | (CopyCordToArray)(cord, rep_.small.data); |
959 | 0 | } |
960 | | |
961 | | void ByteString::SetMedium(google::protobuf::Arena* absl_nullable arena, |
962 | 5.46k | absl::string_view string) { |
963 | 5.46k | ABSL_DCHECK_GT(string.size(), kSmallByteStringCapacity); |
964 | 5.46k | rep_.header.kind = ByteStringKind::kMedium; |
965 | 5.46k | rep_.medium.size = string.size(); |
966 | 5.46k | if (arena != nullptr) { |
967 | 0 | char* data = static_cast<char*>( |
968 | 0 | arena->AllocateAligned(rep_.medium.size, alignof(char))); |
969 | 0 | std::memcpy(data, string.data(), rep_.medium.size); |
970 | 0 | rep_.medium.data = data; |
971 | 0 | rep_.medium.owner = |
972 | 0 | reinterpret_cast<uintptr_t>(arena) | kMetadataOwnerArenaBit; |
973 | 5.46k | } else { |
974 | 5.46k | auto pair = MakeReferenceCountedString(string); |
975 | 5.46k | rep_.medium.data = pair.second.data(); |
976 | 5.46k | rep_.medium.owner = reinterpret_cast<uintptr_t>(pair.first) | |
977 | 5.46k | kMetadataOwnerReferenceCountBit; |
978 | 5.46k | } |
979 | 5.46k | } |
980 | | |
981 | 0 | void ByteString::SetExternalMedium(absl::string_view string) { |
982 | 0 | ABSL_DCHECK_GT(string.size(), kSmallByteStringCapacity); |
983 | 0 | rep_.header.kind = ByteStringKind::kMedium; |
984 | 0 | rep_.medium.size = string.size(); |
985 | 0 | rep_.medium.data = string.data(); |
986 | 0 | rep_.medium.owner = 0; |
987 | 0 | } |
988 | | |
989 | | void ByteString::SetMedium(google::protobuf::Arena* absl_nullable arena, |
990 | 2 | std::string&& string) { |
991 | 2 | ABSL_DCHECK_GT(string.size(), kSmallByteStringCapacity); |
992 | 2 | rep_.header.kind = ByteStringKind::kMedium; |
993 | 2 | rep_.medium.size = string.size(); |
994 | 2 | if (arena != nullptr) { |
995 | 0 | auto* data = google::protobuf::Arena::Create<std::string>(arena, std::move(string)); |
996 | 0 | rep_.medium.data = data->data(); |
997 | 0 | rep_.medium.owner = |
998 | 0 | reinterpret_cast<uintptr_t>(arena) | kMetadataOwnerArenaBit; |
999 | 2 | } else { |
1000 | 2 | auto pair = MakeReferenceCountedString(std::move(string)); |
1001 | 2 | rep_.medium.data = pair.second.data(); |
1002 | 2 | rep_.medium.owner = reinterpret_cast<uintptr_t>(pair.first) | |
1003 | 2 | kMetadataOwnerReferenceCountBit; |
1004 | 2 | } |
1005 | 2 | } |
1006 | | |
1007 | | void ByteString::SetMedium(google::protobuf::Arena* absl_nonnull arena, |
1008 | 0 | const absl::Cord& cord) { |
1009 | 0 | ABSL_DCHECK_GT(cord.size(), kSmallByteStringCapacity); |
1010 | 0 | rep_.header.kind = ByteStringKind::kMedium; |
1011 | 0 | rep_.medium.size = cord.size(); |
1012 | 0 | char* data = static_cast<char*>( |
1013 | 0 | arena->AllocateAligned(rep_.medium.size, alignof(char))); |
1014 | 0 | (CopyCordToArray)(cord, data); |
1015 | 0 | rep_.medium.data = data; |
1016 | 0 | rep_.medium.owner = |
1017 | 0 | reinterpret_cast<uintptr_t>(arena) | kMetadataOwnerArenaBit; |
1018 | 0 | } |
1019 | | |
1020 | | void ByteString::SetMedium(absl::string_view string, uintptr_t owner) { |
1021 | | ABSL_DCHECK_GT(string.size(), kSmallByteStringCapacity); |
1022 | | ABSL_DCHECK_NE(owner, 0); |
1023 | | rep_.header.kind = ByteStringKind::kMedium; |
1024 | | rep_.medium.size = string.size(); |
1025 | | rep_.medium.data = string.data(); |
1026 | | rep_.medium.owner = owner; |
1027 | | } |
1028 | | |
1029 | 0 | void ByteString::SetLarge(const absl::Cord& cord) { |
1030 | 0 | ABSL_DCHECK_GT(cord.size(), kSmallByteStringCapacity); |
1031 | 0 | rep_.header.kind = ByteStringKind::kLarge; |
1032 | 0 | ::new (static_cast<void*>(&rep_.large.data[0])) absl::Cord(cord); |
1033 | 0 | } |
1034 | | |
1035 | 0 | void ByteString::SetLarge(absl::Cord&& cord) { |
1036 | 0 | ABSL_DCHECK_GT(cord.size(), kSmallByteStringCapacity); |
1037 | 0 | rep_.header.kind = ByteStringKind::kLarge; |
1038 | 0 | ::new (static_cast<void*>(&rep_.large.data[0])) absl::Cord(std::move(cord)); |
1039 | 0 | } |
1040 | | |
1041 | | absl::string_view LegacyByteString(const ByteString& string, bool stable, |
1042 | 718 | google::protobuf::Arena* absl_nonnull arena) { |
1043 | 718 | ABSL_DCHECK(arena != nullptr); |
1044 | 718 | if (string.empty()) { |
1045 | 37 | return absl::string_view(); |
1046 | 37 | } |
1047 | 681 | const ByteStringKind kind = string.GetKind(); |
1048 | 681 | if (kind == ByteStringKind::kMedium && string.GetMediumArena() == arena) { |
1049 | 28 | google::protobuf::Arena* absl_nullable other_arena = string.GetMediumArena(); |
1050 | 28 | if (other_arena == arena || other_arena == nullptr) { |
1051 | | // Legacy values do not preserve arena. For speed, we assume the arena is |
1052 | | // compatible. |
1053 | 28 | return string.GetMedium(); |
1054 | 28 | } |
1055 | 28 | } |
1056 | 653 | if (stable && kind == ByteStringKind::kSmall) { |
1057 | 0 | return string.GetSmall(); |
1058 | 0 | } |
1059 | 653 | std::string* absl_nonnull result = google::protobuf::Arena::Create<std::string>(arena); |
1060 | 653 | switch (kind) { |
1061 | 425 | case ByteStringKind::kSmall: |
1062 | 425 | result->assign(string.GetSmall()); |
1063 | 425 | break; |
1064 | 228 | case ByteStringKind::kMedium: |
1065 | 228 | result->assign(string.GetMedium()); |
1066 | 228 | break; |
1067 | 0 | case ByteStringKind::kLarge: |
1068 | 0 | absl::CopyCordToString(string.GetLarge(), result); |
1069 | 0 | break; |
1070 | 653 | } |
1071 | 653 | return absl::string_view(*result); |
1072 | 653 | } |
1073 | | |
1074 | | } // namespace cel::common_internal |