| 58 | } // namespace |
| 59 | |
| 60 | ByteString ByteString::Concat(const ByteString& lhs, const ByteString& rhs, |
| 61 | google::protobuf::Arena* absl_nonnull arena) { |
| 62 | ABSL_DCHECK(arena != nullptr); |
| 63 | |
| 64 | if (lhs.empty()) { |
| 65 | return rhs; |
| 66 | } |
| 67 | if (rhs.empty()) { |
| 68 | return lhs; |
| 69 | } |
| 70 | |
| 71 | if (lhs.GetKind() == ByteStringKind::kLarge || |
| 72 | rhs.GetKind() == ByteStringKind::kLarge) { |
| 73 | // If either the left or right are absl::Cord, use absl::Cord. |
| 74 | absl::Cord result; |
| 75 | result.Append(lhs.ToCord()); |
| 76 | result.Append(rhs.ToCord()); |
| 77 | return ByteString(std::move(result)); |
| 78 | } |
| 79 | |
| 80 | const size_t lhs_size = lhs.size(); |
| 81 | const size_t rhs_size = rhs.size(); |
| 82 | const size_t result_size = lhs_size + rhs_size; |
| 83 | ByteString result; |
| 84 | if (result_size <= kSmallByteStringCapacity) { |
| 85 | // If the resulting string fits in inline storage, do it. |
| 86 | result.rep_.small.size = result_size; |
| 87 | result.rep_.small.arena = arena; |
| 88 | lhs.CopyToArray(result.rep_.small.data); |
| 89 | rhs.CopyToArray(result.rep_.small.data + lhs_size); |
| 90 | } else { |
| 91 | // Otherwise allocate on the arena. |
| 92 | char* result_data = |
| 93 | reinterpret_cast<char*>(arena->AllocateAligned(result_size)); |
| 94 | lhs.CopyToArray(result_data); |
| 95 | rhs.CopyToArray(result_data + lhs_size); |
| 96 | result.rep_.medium.data = result_data; |
| 97 | result.rep_.medium.size = result_size; |
| 98 | result.rep_.medium.owner = |
| 99 | reinterpret_cast<uintptr_t>(arena) | kMetadataOwnerArenaBit; |
| 100 | result.rep_.header.kind = ByteStringKind::kMedium; |
| 101 | } |
| 102 | return result; |
| 103 | } |
| 104 | |
| 105 | ByteString::ByteString(Allocator<> allocator, absl::string_view string) { |
| 106 | ABSL_DCHECK_LE(string.size(), max_size()); |
nothing calls this directly
no test coverage detected