temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
[email protected] | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 2 | // Copyright 2008 Google Inc. All rights reserved. |
Feng Xiao | e428862 | 2014-10-01 16:26:23 -0700 | [diff] [blame] | 3 | // https://developers.google.com/protocol-buffers/ |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 4 | // |
[email protected] | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 5 | // Redistribution and use in source and binary forms, with or without |
| 6 | // modification, are permitted provided that the following conditions are |
| 7 | // met: |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 8 | // |
[email protected] | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 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. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 18 | // |
[email protected] | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 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. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 30 | |
| 31 | // Author: [email protected] (Kenton Varda) |
| 32 | // Based on original Protocol Buffers design by |
| 33 | // Sanjay Ghemawat, Jeff Dean, and others. |
| 34 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 35 | #include <google/protobuf/extension_set.h> |
| 36 | |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 37 | #include <tuple> |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 38 | #include <unordered_map> |
Adam Cozzette | 92a7e77 | 2017-12-01 10:05:10 -0800 | [diff] [blame] | 39 | #include <utility> |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 40 | #include <google/protobuf/stubs/common.h> |
Adam Cozzette | 0894e07 | 2018-11-09 11:28:22 -0800 | [diff] [blame] | 41 | #include <google/protobuf/extension_set_inl.h> |
| 42 | #include <google/protobuf/parse_context.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 43 | #include <google/protobuf/io/coded_stream.h> |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 44 | #include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
| 45 | #include <google/protobuf/message_lite.h> |
| 46 | #include <google/protobuf/metadata_lite.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 47 | #include <google/protobuf/repeated_field.h> |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 48 | #include <google/protobuf/stubs/map_util.h> |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 49 | #include <google/protobuf/stubs/hash.h> |
| 50 | |
| 51 | #include <google/protobuf/port_def.inc> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 52 | |
| 53 | namespace google { |
| 54 | namespace protobuf { |
| 55 | namespace internal { |
| 56 | |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 57 | namespace { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 58 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 59 | inline WireFormatLite::FieldType real_type(FieldType type) { |
| 60 | GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); |
| 61 | return static_cast<WireFormatLite::FieldType>(type); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 62 | } |
| 63 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 64 | inline WireFormatLite::CppType cpp_type(FieldType type) { |
| 65 | return WireFormatLite::FieldTypeToCppType(real_type(type)); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 66 | } |
| 67 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 68 | inline bool is_packable(WireFormatLite::WireType type) { |
| 69 | switch (type) { |
| 70 | case WireFormatLite::WIRETYPE_VARINT: |
| 71 | case WireFormatLite::WIRETYPE_FIXED64: |
| 72 | case WireFormatLite::WIRETYPE_FIXED32: |
| 73 | return true; |
| 74 | case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: |
| 75 | case WireFormatLite::WIRETYPE_START_GROUP: |
| 76 | case WireFormatLite::WIRETYPE_END_GROUP: |
| 77 | return false; |
| 78 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 79 | // Do not add a default statement. Let the compiler complain when someone |
| 80 | // adds a new wire type. |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 81 | } |
Feng Xiao | 9173ba2 | 2014-12-02 15:28:11 -0800 | [diff] [blame] | 82 | GOOGLE_LOG(FATAL) << "can't reach here."; |
| 83 | return false; |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 84 | } |
| 85 | |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 86 | // Registry stuff. |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 87 | struct ExtensionHasher { |
| 88 | std::size_t operator()(const std::pair<const MessageLite*, int>& p) const { |
| 89 | return std::hash<const MessageLite*>{}(p.first) ^ |
| 90 | std::hash<int>{}(p.second); |
| 91 | } |
| 92 | }; |
| 93 | |
| 94 | typedef std::unordered_map<std::pair<const MessageLite*, int>, ExtensionInfo, |
| 95 | ExtensionHasher> |
| 96 | ExtensionRegistry; |
[email protected] | 63e646b | 2009-05-06 19:27:03 +0000 | [diff] [blame] | 97 | |
Adam Cozzette | a9abc78 | 2018-07-06 14:12:33 -0700 | [diff] [blame] | 98 | static const ExtensionRegistry* global_registry = nullptr; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 99 | |
| 100 | // This function is only called at startup, so there is no need for thread- |
| 101 | // safety. |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 102 | void Register(const MessageLite* containing_type, int number, |
| 103 | ExtensionInfo info) { |
Adam Cozzette | a9abc78 | 2018-07-06 14:12:33 -0700 | [diff] [blame] | 104 | static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry); |
| 105 | global_registry = local_static_registry; |
| 106 | if (!InsertIfNotPresent(local_static_registry, |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 107 | std::make_pair(containing_type, number), info)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 108 | GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 109 | << containing_type->GetTypeName() << "\", field number " |
| 110 | << number << "."; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 111 | } |
| 112 | } |
| 113 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 114 | const ExtensionInfo* FindRegisteredExtension(const MessageLite* containing_type, |
| 115 | int number) { |
Adam Cozzette | a9abc78 | 2018-07-06 14:12:33 -0700 | [diff] [blame] | 116 | return global_registry == nullptr |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 117 | ? nullptr |
| 118 | : FindOrNull(*global_registry, |
| 119 | std::make_pair(containing_type, number)); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | } // namespace |
| 123 | |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 124 | ExtensionFinder::~ExtensionFinder() {} |
| 125 | |
| 126 | bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) { |
| 127 | const ExtensionInfo* extension = |
| 128 | FindRegisteredExtension(containing_type_, number); |
| 129 | if (extension == NULL) { |
| 130 | return false; |
| 131 | } else { |
| 132 | *output = *extension; |
| 133 | return true; |
| 134 | } |
| 135 | } |
| 136 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 137 | void ExtensionSet::RegisterExtension(const MessageLite* containing_type, |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 138 | int number, FieldType type, |
| 139 | bool is_repeated, bool is_packed) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 140 | GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM); |
| 141 | GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE); |
| 142 | GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 143 | ExtensionInfo info(type, is_repeated, is_packed); |
| 144 | Register(containing_type, number, info); |
| 145 | } |
| 146 | |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 147 | static bool CallNoArgValidityFunc(const void* arg, int number) { |
[email protected] | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 148 | // Note: Must use C-style cast here rather than reinterpret_cast because |
| 149 | // the C++ standard at one point did not allow casts between function and |
| 150 | // data pointers and some compilers enforce this for C++-style casts. No |
| 151 | // compiler enforces it for C-style casts since lots of C-style code has |
| 152 | // relied on these kinds of casts for a long time, despite being |
| 153 | // technically undefined. See: |
| 154 | // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195 |
[email protected] | f2a7329 | 2009-12-21 19:44:57 +0000 | [diff] [blame] | 155 | // Also note: Some compilers do not allow function pointers to be "const". |
| 156 | // Which makes sense, I suppose, because it's meaningless. |
| 157 | return ((EnumValidityFunc*)arg)(number); |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 158 | } |
| 159 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 160 | void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type, |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 161 | int number, FieldType type, |
| 162 | bool is_repeated, bool is_packed, |
| 163 | EnumValidityFunc* is_valid) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 164 | GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 165 | ExtensionInfo info(type, is_repeated, is_packed); |
[email protected] | f9c5978 | 2009-12-22 18:04:23 +0000 | [diff] [blame] | 166 | info.enum_validity_check.func = CallNoArgValidityFunc; |
[email protected] | 91218af | 2009-12-18 07:20:43 +0000 | [diff] [blame] | 167 | // See comment in CallNoArgValidityFunc() about why we use a c-style cast. |
[email protected] | f9c5978 | 2009-12-22 18:04:23 +0000 | [diff] [blame] | 168 | info.enum_validity_check.arg = (void*)is_valid; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 169 | Register(containing_type, number, info); |
| 170 | } |
| 171 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 172 | void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type, |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 173 | int number, FieldType type, |
| 174 | bool is_repeated, bool is_packed, |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 175 | const MessageLite* prototype) { |
| 176 | GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE || |
| 177 | type == WireFormatLite::TYPE_GROUP); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 178 | ExtensionInfo info(type, is_repeated, is_packed); |
Adam Cozzette | 0894e07 | 2018-11-09 11:28:22 -0800 | [diff] [blame] | 179 | info.message_info = {prototype}; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 180 | Register(containing_type, number, info); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 181 | } |
| 182 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 183 | // =================================================================== |
| 184 | // Constructors and basic methods. |
| 185 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 186 | ExtensionSet::ExtensionSet(Arena* arena) |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 187 | : arena_(arena), |
| 188 | flat_capacity_(0), |
| 189 | flat_size_(0), |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 190 | map_{flat_capacity_ == 0 |
| 191 | ? NULL |
| 192 | : Arena::CreateArray<KeyValue>(arena_, flat_capacity_)} {} |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 193 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 194 | ExtensionSet::~ExtensionSet() { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 195 | // Deletes all allocated extensions. |
| 196 | if (arena_ == NULL) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 197 | ForEach([](int /* number */, Extension& ext) { ext.Free(); }); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 198 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 199 | delete map_.large; |
| 200 | } else { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 201 | DeleteFlatMap(map_.flat, flat_capacity_); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 202 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 203 | } |
| 204 | } |
| 205 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 206 | void ExtensionSet::DeleteFlatMap(const ExtensionSet::KeyValue* flat, |
| 207 | uint16 flat_capacity) { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 208 | #ifdef __cpp_sized_deallocation |
| 209 | // Arena::CreateArray already requires a trivially destructible type, but |
| 210 | // ensure this constraint is not violated in the future. |
| 211 | static_assert(std::is_trivially_destructible<KeyValue>::value, |
| 212 | "CreateArray requires a trivially destructible type"); |
| 213 | // A const-cast is needed, but this is safe as we are about to deallocate the |
| 214 | // array. |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 215 | ::operator delete[](const_cast<ExtensionSet::KeyValue*>(flat), |
| 216 | sizeof(*flat) * flat_capacity); |
| 217 | #else // !__cpp_sized_deallocation |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 218 | delete[] flat; |
| 219 | #endif // !__cpp_sized_deallocation |
| 220 | } |
| 221 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 222 | // Defined in extension_set_heavy.cc. |
| 223 | // void ExtensionSet::AppendToList(const Descriptor* containing_type, |
| 224 | // const DescriptorPool* pool, |
| 225 | // vector<const FieldDescriptor*>* output) const |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 226 | |
| 227 | bool ExtensionSet::Has(int number) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 228 | const Extension* ext = FindOrNull(number); |
| 229 | if (ext == NULL) return false; |
| 230 | GOOGLE_DCHECK(!ext->is_repeated); |
| 231 | return !ext->is_cleared; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 232 | } |
| 233 | |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 234 | int ExtensionSet::NumExtensions() const { |
| 235 | int result = 0; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 236 | ForEach([&result](int /* number */, const Extension& ext) { |
| 237 | if (!ext.is_cleared) { |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 238 | ++result; |
| 239 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 240 | }); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 241 | return result; |
| 242 | } |
| 243 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 244 | int ExtensionSet::ExtensionSize(int number) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 245 | const Extension* ext = FindOrNull(number); |
| 246 | return ext == NULL ? 0 : ext->GetSize(); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 247 | } |
| 248 | |
[email protected] | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 249 | FieldType ExtensionSet::ExtensionType(int number) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 250 | const Extension* ext = FindOrNull(number); |
| 251 | if (ext == NULL) { |
[email protected] | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 252 | GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; |
| 253 | return 0; |
| 254 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 255 | if (ext->is_cleared) { |
[email protected] | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 256 | GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; |
| 257 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 258 | return ext->type; |
[email protected] | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 259 | } |
| 260 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 261 | void ExtensionSet::ClearExtension(int number) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 262 | Extension* ext = FindOrNull(number); |
| 263 | if (ext == NULL) return; |
| 264 | ext->Clear(); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 265 | } |
| 266 | |
| 267 | // =================================================================== |
| 268 | // Field accessors |
| 269 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 270 | namespace { |
| 271 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 272 | enum { REPEATED_FIELD, OPTIONAL_FIELD }; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 273 | |
| 274 | } // namespace |
| 275 | |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 276 | #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ |
| 277 | GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED_FIELD : OPTIONAL_FIELD, LABEL); \ |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 278 | GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE) |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 279 | |
| 280 | // ------------------------------------------------------------------- |
| 281 | // Primitives |
| 282 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 283 | #define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \ |
| 284 | \ |
| 285 | LOWERCASE ExtensionSet::Get##CAMELCASE(int number, LOWERCASE default_value) \ |
| 286 | const { \ |
| 287 | const Extension* extension = FindOrNull(number); \ |
| 288 | if (extension == NULL || extension->is_cleared) { \ |
| 289 | return default_value; \ |
| 290 | } else { \ |
| 291 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ |
| 292 | return extension->LOWERCASE##_value; \ |
| 293 | } \ |
| 294 | } \ |
| 295 | \ |
| 296 | void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \ |
| 297 | LOWERCASE value, \ |
| 298 | const FieldDescriptor* descriptor) { \ |
| 299 | Extension* extension; \ |
| 300 | if (MaybeNewExtension(number, descriptor, &extension)) { \ |
| 301 | extension->type = type; \ |
| 302 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), \ |
| 303 | WireFormatLite::CPPTYPE_##UPPERCASE); \ |
| 304 | extension->is_repeated = false; \ |
| 305 | } else { \ |
| 306 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ |
| 307 | } \ |
| 308 | extension->is_cleared = false; \ |
| 309 | extension->LOWERCASE##_value = value; \ |
| 310 | } \ |
| 311 | \ |
| 312 | LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) \ |
| 313 | const { \ |
| 314 | const Extension* extension = FindOrNull(number); \ |
| 315 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; \ |
| 316 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ |
| 317 | return extension->repeated_##LOWERCASE##_value->Get(index); \ |
| 318 | } \ |
| 319 | \ |
| 320 | void ExtensionSet::SetRepeated##CAMELCASE(int number, int index, \ |
| 321 | LOWERCASE value) { \ |
| 322 | Extension* extension = FindOrNull(number); \ |
| 323 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; \ |
| 324 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ |
| 325 | extension->repeated_##LOWERCASE##_value->Set(index, value); \ |
| 326 | } \ |
| 327 | \ |
| 328 | void ExtensionSet::Add##CAMELCASE(int number, FieldType type, bool packed, \ |
| 329 | LOWERCASE value, \ |
| 330 | const FieldDescriptor* descriptor) { \ |
| 331 | Extension* extension; \ |
| 332 | if (MaybeNewExtension(number, descriptor, &extension)) { \ |
| 333 | extension->type = type; \ |
| 334 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), \ |
| 335 | WireFormatLite::CPPTYPE_##UPPERCASE); \ |
| 336 | extension->is_repeated = true; \ |
| 337 | extension->is_packed = packed; \ |
| 338 | extension->repeated_##LOWERCASE##_value = \ |
| 339 | Arena::CreateMessage<RepeatedField<LOWERCASE>>(arena_); \ |
| 340 | } else { \ |
| 341 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ |
| 342 | GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ |
| 343 | } \ |
| 344 | extension->repeated_##LOWERCASE##_value->Add(value); \ |
| 345 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 346 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 347 | PRIMITIVE_ACCESSORS(INT32, int32, Int32) |
| 348 | PRIMITIVE_ACCESSORS(INT64, int64, Int64) |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 349 | PRIMITIVE_ACCESSORS(UINT32, uint32, UInt32) |
| 350 | PRIMITIVE_ACCESSORS(UINT64, uint64, UInt64) |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 351 | PRIMITIVE_ACCESSORS(FLOAT, float, Float) |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 352 | PRIMITIVE_ACCESSORS(DOUBLE, double, Double) |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 353 | PRIMITIVE_ACCESSORS(BOOL, bool, Bool) |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 354 | |
| 355 | #undef PRIMITIVE_ACCESSORS |
| 356 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 357 | const void* ExtensionSet::GetRawRepeatedField(int number, |
| 358 | const void* default_value) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 359 | const Extension* extension = FindOrNull(number); |
| 360 | if (extension == NULL) { |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 361 | return default_value; |
| 362 | } |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 363 | // We assume that all the RepeatedField<>* pointers have the same |
| 364 | // size and alignment within the anonymous union in Extension. |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 365 | return extension->repeated_int32_value; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 366 | } |
| 367 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 368 | void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, |
| 369 | bool packed, |
| 370 | const FieldDescriptor* desc) { |
| 371 | Extension* extension; |
| 372 | |
| 373 | // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this |
| 374 | // extension. |
| 375 | if (MaybeNewExtension(number, desc, &extension)) { |
| 376 | extension->is_repeated = true; |
| 377 | extension->type = field_type; |
| 378 | extension->is_packed = packed; |
| 379 | |
| 380 | switch (WireFormatLite::FieldTypeToCppType( |
| 381 | static_cast<WireFormatLite::FieldType>(field_type))) { |
| 382 | case WireFormatLite::CPPTYPE_INT32: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 383 | extension->repeated_int32_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 384 | Arena::CreateMessage<RepeatedField<int32>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 385 | break; |
| 386 | case WireFormatLite::CPPTYPE_INT64: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 387 | extension->repeated_int64_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 388 | Arena::CreateMessage<RepeatedField<int64>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 389 | break; |
| 390 | case WireFormatLite::CPPTYPE_UINT32: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 391 | extension->repeated_uint32_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 392 | Arena::CreateMessage<RepeatedField<uint32>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 393 | break; |
| 394 | case WireFormatLite::CPPTYPE_UINT64: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 395 | extension->repeated_uint64_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 396 | Arena::CreateMessage<RepeatedField<uint64>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 397 | break; |
| 398 | case WireFormatLite::CPPTYPE_DOUBLE: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 399 | extension->repeated_double_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 400 | Arena::CreateMessage<RepeatedField<double>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 401 | break; |
| 402 | case WireFormatLite::CPPTYPE_FLOAT: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 403 | extension->repeated_float_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 404 | Arena::CreateMessage<RepeatedField<float>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 405 | break; |
| 406 | case WireFormatLite::CPPTYPE_BOOL: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 407 | extension->repeated_bool_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 408 | Arena::CreateMessage<RepeatedField<bool>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 409 | break; |
| 410 | case WireFormatLite::CPPTYPE_ENUM: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 411 | extension->repeated_enum_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 412 | Arena::CreateMessage<RepeatedField<int>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 413 | break; |
| 414 | case WireFormatLite::CPPTYPE_STRING: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 415 | extension->repeated_string_value = |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 416 | Arena::CreateMessage<RepeatedPtrField<std::string>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 417 | break; |
| 418 | case WireFormatLite::CPPTYPE_MESSAGE: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 419 | extension->repeated_message_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 420 | Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 421 | break; |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | // We assume that all the RepeatedField<>* pointers have the same |
| 426 | // size and alignment within the anonymous union in Extension. |
| 427 | return extension->repeated_int32_value; |
| 428 | } |
| 429 | |
| 430 | // Compatible version using old call signature. Does not create extensions when |
| 431 | // the don't already exist; instead, just GOOGLE_CHECK-fails. |
| 432 | void* ExtensionSet::MutableRawRepeatedField(int number) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 433 | Extension* extension = FindOrNull(number); |
| 434 | GOOGLE_CHECK(extension != NULL) << "Extension not found."; |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 435 | // We assume that all the RepeatedField<>* pointers have the same |
| 436 | // size and alignment within the anonymous union in Extension. |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 437 | return extension->repeated_int32_value; |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 438 | } |
| 439 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 440 | // ------------------------------------------------------------------- |
| 441 | // Enums |
| 442 | |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 443 | int ExtensionSet::GetEnum(int number, int default_value) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 444 | const Extension* extension = FindOrNull(number); |
| 445 | if (extension == NULL || extension->is_cleared) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 446 | // Not present. Return the default value. |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 447 | return default_value; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 448 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 449 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 450 | return extension->enum_value; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 451 | } |
| 452 | } |
| 453 | |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 454 | void ExtensionSet::SetEnum(int number, FieldType type, int value, |
| 455 | const FieldDescriptor* descriptor) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 456 | Extension* extension; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 457 | if (MaybeNewExtension(number, descriptor, &extension)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 458 | extension->type = type; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 459 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 460 | extension->is_repeated = false; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 461 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 462 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 463 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 464 | extension->is_cleared = false; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 465 | extension->enum_value = value; |
| 466 | } |
| 467 | |
| 468 | int ExtensionSet::GetRepeatedEnum(int number, int index) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 469 | const Extension* extension = FindOrNull(number); |
| 470 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 471 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 472 | return extension->repeated_enum_value->Get(index); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 473 | } |
| 474 | |
| 475 | void ExtensionSet::SetRepeatedEnum(int number, int index, int value) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 476 | Extension* extension = FindOrNull(number); |
| 477 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 478 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 479 | extension->repeated_enum_value->Set(index, value); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 480 | } |
| 481 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 482 | void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value, |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 483 | const FieldDescriptor* descriptor) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 484 | Extension* extension; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 485 | if (MaybeNewExtension(number, descriptor, &extension)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 486 | extension->type = type; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 487 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 488 | extension->is_repeated = true; |
| 489 | extension->is_packed = packed; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 490 | extension->repeated_enum_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 491 | Arena::CreateMessage<RepeatedField<int>>(arena_); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 492 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 493 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 494 | GOOGLE_DCHECK_EQ(extension->is_packed, packed); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 495 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 496 | extension->repeated_enum_value->Add(value); |
| 497 | } |
| 498 | |
| 499 | // ------------------------------------------------------------------- |
| 500 | // Strings |
| 501 | |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 502 | const std::string& ExtensionSet::GetString( |
| 503 | int number, const std::string& default_value) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 504 | const Extension* extension = FindOrNull(number); |
| 505 | if (extension == NULL || extension->is_cleared) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 506 | // Not present. Return the default value. |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 507 | return default_value; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 508 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 509 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 510 | return *extension->string_value; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 511 | } |
| 512 | } |
| 513 | |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 514 | std::string* ExtensionSet::MutableString(int number, FieldType type, |
| 515 | const FieldDescriptor* descriptor) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 516 | Extension* extension; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 517 | if (MaybeNewExtension(number, descriptor, &extension)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 518 | extension->type = type; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 519 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 520 | extension->is_repeated = false; |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 521 | extension->string_value = Arena::Create<std::string>(arena_); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 522 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 523 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 524 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 525 | extension->is_cleared = false; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 526 | return extension->string_value; |
| 527 | } |
| 528 | |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 529 | const std::string& ExtensionSet::GetRepeatedString(int number, |
| 530 | int index) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 531 | const Extension* extension = FindOrNull(number); |
| 532 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 533 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 534 | return extension->repeated_string_value->Get(index); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 535 | } |
| 536 | |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 537 | std::string* ExtensionSet::MutableRepeatedString(int number, int index) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 538 | Extension* extension = FindOrNull(number); |
| 539 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 540 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 541 | return extension->repeated_string_value->Mutable(index); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 542 | } |
| 543 | |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 544 | std::string* ExtensionSet::AddString(int number, FieldType type, |
| 545 | const FieldDescriptor* descriptor) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 546 | Extension* extension; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 547 | if (MaybeNewExtension(number, descriptor, &extension)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 548 | extension->type = type; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 549 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 550 | extension->is_repeated = true; |
| 551 | extension->is_packed = false; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 552 | extension->repeated_string_value = |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 553 | Arena::CreateMessage<RepeatedPtrField<std::string>>(arena_); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 554 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 555 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 556 | } |
| 557 | return extension->repeated_string_value->Add(); |
| 558 | } |
| 559 | |
| 560 | // ------------------------------------------------------------------- |
| 561 | // Messages |
| 562 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 563 | const MessageLite& ExtensionSet::GetMessage( |
| 564 | int number, const MessageLite& default_value) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 565 | const Extension* extension = FindOrNull(number); |
| 566 | if (extension == NULL) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 567 | // Not present. Return the default value. |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 568 | return default_value; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 569 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 570 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 571 | if (extension->is_lazy) { |
| 572 | return extension->lazymessage_value->GetMessage(default_value); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 573 | } else { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 574 | return *extension->message_value; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 575 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 576 | } |
| 577 | } |
| 578 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 579 | // Defined in extension_set_heavy.cc. |
| 580 | // const MessageLite& ExtensionSet::GetMessage(int number, |
| 581 | // const Descriptor* message_type, |
| 582 | // MessageFactory* factory) const |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 583 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 584 | MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 585 | const MessageLite& prototype, |
| 586 | const FieldDescriptor* descriptor) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 587 | Extension* extension; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 588 | if (MaybeNewExtension(number, descriptor, &extension)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 589 | extension->type = type; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 590 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 591 | extension->is_repeated = false; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 592 | extension->is_lazy = false; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 593 | extension->message_value = prototype.New(arena_); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 594 | extension->is_cleared = false; |
| 595 | return extension->message_value; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 596 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 597 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 598 | extension->is_cleared = false; |
| 599 | if (extension->is_lazy) { |
| 600 | return extension->lazymessage_value->MutableMessage(prototype); |
| 601 | } else { |
| 602 | return extension->message_value; |
| 603 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 604 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 605 | } |
| 606 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 607 | // Defined in extension_set_heavy.cc. |
| 608 | // MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, |
| 609 | // const Descriptor* message_type, |
| 610 | // MessageFactory* factory) |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 611 | |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 612 | void ExtensionSet::SetAllocatedMessage(int number, FieldType type, |
| 613 | const FieldDescriptor* descriptor, |
| 614 | MessageLite* message) { |
| 615 | if (message == NULL) { |
| 616 | ClearExtension(number); |
| 617 | return; |
| 618 | } |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 619 | #ifdef PROTOBUF_INTERNAL_USE_MUST_USE_RESULT |
| 620 | GOOGLE_DCHECK(message->GetOwningArena() == nullptr || |
| 621 | message->GetOwningArena() == arena_); |
| 622 | #endif // PROTOBUF_INTERNAL_USE_MUST_USE_RESULT |
Joshua Haberman | f5fd897 | 2021-04-30 16:12:50 -0700 | [diff] [blame] | 623 | Arena* message_arena = message->GetOwningArena(); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 624 | Extension* extension; |
| 625 | if (MaybeNewExtension(number, descriptor, &extension)) { |
| 626 | extension->type = type; |
| 627 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); |
| 628 | extension->is_repeated = false; |
| 629 | extension->is_lazy = false; |
Jisi Liu | 46e8ff6 | 2015-10-05 11:59:43 -0700 | [diff] [blame] | 630 | if (message_arena == arena_) { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 631 | extension->message_value = message; |
Jisi Liu | 46e8ff6 | 2015-10-05 11:59:43 -0700 | [diff] [blame] | 632 | } else if (message_arena == NULL) { |
| 633 | extension->message_value = message; |
| 634 | arena_->Own(message); // not NULL because not equal to message_arena |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 635 | } else { |
| 636 | extension->message_value = message->New(arena_); |
| 637 | extension->message_value->CheckTypeAndMergeFrom(*message); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 638 | } |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 639 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 640 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 641 | if (extension->is_lazy) { |
| 642 | extension->lazymessage_value->SetAllocatedMessage(message); |
| 643 | } else { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 644 | if (arena_ == NULL) { |
| 645 | delete extension->message_value; |
| 646 | } |
Jisi Liu | 46e8ff6 | 2015-10-05 11:59:43 -0700 | [diff] [blame] | 647 | if (message_arena == arena_) { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 648 | extension->message_value = message; |
Jisi Liu | 46e8ff6 | 2015-10-05 11:59:43 -0700 | [diff] [blame] | 649 | } else if (message_arena == NULL) { |
| 650 | extension->message_value = message; |
| 651 | arena_->Own(message); // not NULL because not equal to message_arena |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 652 | } else { |
| 653 | extension->message_value = message->New(arena_); |
| 654 | extension->message_value->CheckTypeAndMergeFrom(*message); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 655 | } |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 656 | } |
| 657 | } |
| 658 | extension->is_cleared = false; |
| 659 | } |
| 660 | |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 661 | void ExtensionSet::UnsafeArenaSetAllocatedMessage( |
| 662 | int number, FieldType type, const FieldDescriptor* descriptor, |
| 663 | MessageLite* message) { |
| 664 | if (message == NULL) { |
| 665 | ClearExtension(number); |
| 666 | return; |
| 667 | } |
| 668 | Extension* extension; |
| 669 | if (MaybeNewExtension(number, descriptor, &extension)) { |
| 670 | extension->type = type; |
| 671 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); |
| 672 | extension->is_repeated = false; |
| 673 | extension->is_lazy = false; |
| 674 | extension->message_value = message; |
| 675 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 676 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); |
Bo Yang | 5db2173 | 2015-05-21 14:28:59 -0700 | [diff] [blame] | 677 | if (extension->is_lazy) { |
| 678 | extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message); |
| 679 | } else { |
| 680 | if (arena_ == NULL) { |
| 681 | delete extension->message_value; |
| 682 | } |
| 683 | extension->message_value = message; |
| 684 | } |
| 685 | } |
| 686 | extension->is_cleared = false; |
| 687 | } |
| 688 | |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 689 | MessageLite* ExtensionSet::ReleaseMessage(int number, |
| 690 | const MessageLite& prototype) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 691 | Extension* extension = FindOrNull(number); |
| 692 | if (extension == NULL) { |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 693 | // Not present. Return NULL. |
| 694 | return NULL; |
| 695 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 696 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 697 | MessageLite* ret = NULL; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 698 | if (extension->is_lazy) { |
| 699 | ret = extension->lazymessage_value->ReleaseMessage(prototype); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 700 | if (arena_ == NULL) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 701 | delete extension->lazymessage_value; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 702 | } |
| 703 | } else { |
| 704 | if (arena_ == NULL) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 705 | ret = extension->message_value; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 706 | } else { |
| 707 | // ReleaseMessage() always returns a heap-allocated message, and we are |
| 708 | // on an arena, so we need to make a copy of this message to return. |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 709 | ret = extension->message_value->New(); |
| 710 | ret->CheckTypeAndMergeFrom(*extension->message_value); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 711 | } |
| 712 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 713 | Erase(number); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 714 | return ret; |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( |
| 719 | int number, const MessageLite& prototype) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 720 | Extension* extension = FindOrNull(number); |
| 721 | if (extension == NULL) { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 722 | // Not present. Return NULL. |
| 723 | return NULL; |
| 724 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 725 | GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 726 | MessageLite* ret = NULL; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 727 | if (extension->is_lazy) { |
| 728 | ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 729 | if (arena_ == NULL) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 730 | delete extension->lazymessage_value; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 731 | } |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 732 | } else { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 733 | ret = extension->message_value; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 734 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 735 | Erase(number); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 736 | return ret; |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | // Defined in extension_set_heavy.cc. |
| 741 | // MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, |
| 742 | // MessageFactory* factory); |
| 743 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 744 | const MessageLite& ExtensionSet::GetRepeatedMessage(int number, |
| 745 | int index) const { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 746 | const Extension* extension = FindOrNull(number); |
| 747 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 748 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 749 | return extension->repeated_message_value->Get(index); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 750 | } |
| 751 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 752 | MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 753 | Extension* extension = FindOrNull(number); |
| 754 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 755 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 756 | return extension->repeated_message_value->Mutable(index); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 757 | } |
| 758 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 759 | MessageLite* ExtensionSet::AddMessage(int number, FieldType type, |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 760 | const MessageLite& prototype, |
| 761 | const FieldDescriptor* descriptor) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 762 | Extension* extension; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 763 | if (MaybeNewExtension(number, descriptor, &extension)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 764 | extension->type = type; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 765 | GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 766 | extension->is_repeated = true; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 767 | extension->repeated_message_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 768 | Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 769 | } else { |
Hao Nguyen | 2f864fd | 2019-03-20 11:45:01 -0700 | [diff] [blame] | 770 | GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 771 | } |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 772 | |
| 773 | // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot |
| 774 | // allocate an abstract object, so we have to be tricky. |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 775 | MessageLite* result = reinterpret_cast<internal::RepeatedPtrFieldBase*>( |
| 776 | extension->repeated_message_value) |
| 777 | ->AddFromCleared<GenericTypeHandler<MessageLite>>(); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 778 | if (result == NULL) { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 779 | result = prototype.New(arena_); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 780 | extension->repeated_message_value->AddAllocated(result); |
| 781 | } |
| 782 | return result; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 783 | } |
| 784 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 785 | // Defined in extension_set_heavy.cc. |
| 786 | // MessageLite* ExtensionSet::AddMessage(int number, FieldType type, |
| 787 | // const Descriptor* message_type, |
| 788 | // MessageFactory* factory) |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 789 | |
| 790 | #undef GOOGLE_DCHECK_TYPE |
| 791 | |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 792 | void ExtensionSet::RemoveLast(int number) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 793 | Extension* extension = FindOrNull(number); |
| 794 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 795 | GOOGLE_DCHECK(extension->is_repeated); |
| 796 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 797 | switch (cpp_type(extension->type)) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 798 | case WireFormatLite::CPPTYPE_INT32: |
| 799 | extension->repeated_int32_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 800 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 801 | case WireFormatLite::CPPTYPE_INT64: |
| 802 | extension->repeated_int64_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 803 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 804 | case WireFormatLite::CPPTYPE_UINT32: |
| 805 | extension->repeated_uint32_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 806 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 807 | case WireFormatLite::CPPTYPE_UINT64: |
| 808 | extension->repeated_uint64_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 809 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 810 | case WireFormatLite::CPPTYPE_FLOAT: |
| 811 | extension->repeated_float_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 812 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 813 | case WireFormatLite::CPPTYPE_DOUBLE: |
| 814 | extension->repeated_double_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 815 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 816 | case WireFormatLite::CPPTYPE_BOOL: |
| 817 | extension->repeated_bool_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 818 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 819 | case WireFormatLite::CPPTYPE_ENUM: |
| 820 | extension->repeated_enum_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 821 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 822 | case WireFormatLite::CPPTYPE_STRING: |
| 823 | extension->repeated_string_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 824 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 825 | case WireFormatLite::CPPTYPE_MESSAGE: |
| 826 | extension->repeated_message_value->RemoveLast(); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 827 | break; |
| 828 | } |
| 829 | } |
| 830 | |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 831 | MessageLite* ExtensionSet::ReleaseLast(int number) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 832 | Extension* extension = FindOrNull(number); |
| 833 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 834 | GOOGLE_DCHECK(extension->is_repeated); |
| 835 | GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); |
| 836 | return extension->repeated_message_value->ReleaseLast(); |
| 837 | } |
| 838 | |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 839 | void ExtensionSet::SwapElements(int number, int index1, int index2) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 840 | Extension* extension = FindOrNull(number); |
| 841 | GOOGLE_CHECK(extension != NULL) << "Index out-of-bounds (field is empty)."; |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 842 | GOOGLE_DCHECK(extension->is_repeated); |
| 843 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 844 | switch (cpp_type(extension->type)) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 845 | case WireFormatLite::CPPTYPE_INT32: |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 846 | extension->repeated_int32_value->SwapElements(index1, index2); |
| 847 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 848 | case WireFormatLite::CPPTYPE_INT64: |
| 849 | extension->repeated_int64_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 850 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 851 | case WireFormatLite::CPPTYPE_UINT32: |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 852 | extension->repeated_uint32_value->SwapElements(index1, index2); |
| 853 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 854 | case WireFormatLite::CPPTYPE_UINT64: |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 855 | extension->repeated_uint64_value->SwapElements(index1, index2); |
| 856 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 857 | case WireFormatLite::CPPTYPE_FLOAT: |
| 858 | extension->repeated_float_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 859 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 860 | case WireFormatLite::CPPTYPE_DOUBLE: |
| 861 | extension->repeated_double_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 862 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 863 | case WireFormatLite::CPPTYPE_BOOL: |
| 864 | extension->repeated_bool_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 865 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 866 | case WireFormatLite::CPPTYPE_ENUM: |
| 867 | extension->repeated_enum_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 868 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 869 | case WireFormatLite::CPPTYPE_STRING: |
| 870 | extension->repeated_string_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 871 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 872 | case WireFormatLite::CPPTYPE_MESSAGE: |
| 873 | extension->repeated_message_value->SwapElements(index1, index2); |
[email protected] | ceb561d | 2009-06-25 19:05:36 +0000 | [diff] [blame] | 874 | break; |
| 875 | } |
| 876 | } |
| 877 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 878 | // =================================================================== |
| 879 | |
| 880 | void ExtensionSet::Clear() { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 881 | ForEach([](int /* number */, Extension& ext) { ext.Clear(); }); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 882 | } |
| 883 | |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 884 | namespace { |
| 885 | // Computes the size of a std::set_union without constructing the union. |
| 886 | template <typename ItX, typename ItY> |
| 887 | size_t SizeOfUnion(ItX it_xs, ItX end_xs, ItY it_ys, ItY end_ys) { |
| 888 | size_t result = 0; |
| 889 | while (it_xs != end_xs && it_ys != end_ys) { |
| 890 | ++result; |
| 891 | if (it_xs->first < it_ys->first) { |
| 892 | ++it_xs; |
| 893 | } else if (it_xs->first == it_ys->first) { |
| 894 | ++it_xs; |
| 895 | ++it_ys; |
| 896 | } else { |
| 897 | ++it_ys; |
| 898 | } |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 899 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 900 | result += std::distance(it_xs, end_xs); |
| 901 | result += std::distance(it_ys, end_ys); |
| 902 | return result; |
| 903 | } |
| 904 | } // namespace |
| 905 | |
| 906 | void ExtensionSet::MergeFrom(const ExtensionSet& other) { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 907 | if (PROTOBUF_PREDICT_TRUE(!is_large())) { |
| 908 | if (PROTOBUF_PREDICT_TRUE(!other.is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 909 | GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), other.flat_begin(), |
| 910 | other.flat_end())); |
| 911 | } else { |
| 912 | GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), |
| 913 | other.map_.large->begin(), |
| 914 | other.map_.large->end())); |
| 915 | } |
| 916 | } |
| 917 | other.ForEach([this](int number, const Extension& ext) { |
| 918 | this->InternalExtensionMergeFrom(number, ext); |
| 919 | }); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 920 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 921 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 922 | void ExtensionSet::InternalExtensionMergeFrom( |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 923 | int number, const Extension& other_extension) { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 924 | if (other_extension.is_repeated) { |
| 925 | Extension* extension; |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 926 | bool is_new = |
| 927 | MaybeNewExtension(number, other_extension.descriptor, &extension); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 928 | if (is_new) { |
| 929 | // Extension did not already exist in set. |
| 930 | extension->type = other_extension.type; |
| 931 | extension->is_packed = other_extension.is_packed; |
| 932 | extension->is_repeated = true; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 933 | } else { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 934 | GOOGLE_DCHECK_EQ(extension->type, other_extension.type); |
| 935 | GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); |
| 936 | GOOGLE_DCHECK(extension->is_repeated); |
| 937 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 938 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 939 | switch (cpp_type(other_extension.type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 940 | #define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ |
| 941 | case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
| 942 | if (is_new) { \ |
| 943 | extension->repeated_##LOWERCASE##_value = \ |
| 944 | Arena::CreateMessage<REPEATED_TYPE>(arena_); \ |
| 945 | } \ |
| 946 | extension->repeated_##LOWERCASE##_value->MergeFrom( \ |
| 947 | *other_extension.repeated_##LOWERCASE##_value); \ |
| 948 | break; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 949 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 950 | HANDLE_TYPE(INT32, int32, RepeatedField<int32>); |
| 951 | HANDLE_TYPE(INT64, int64, RepeatedField<int64>); |
| 952 | HANDLE_TYPE(UINT32, uint32, RepeatedField<uint32>); |
| 953 | HANDLE_TYPE(UINT64, uint64, RepeatedField<uint64>); |
| 954 | HANDLE_TYPE(FLOAT, float, RepeatedField<float>); |
| 955 | HANDLE_TYPE(DOUBLE, double, RepeatedField<double>); |
| 956 | HANDLE_TYPE(BOOL, bool, RepeatedField<bool>); |
| 957 | HANDLE_TYPE(ENUM, enum, RepeatedField<int>); |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 958 | HANDLE_TYPE(STRING, string, RepeatedPtrField<std::string>); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 959 | #undef HANDLE_TYPE |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 960 | |
| 961 | case WireFormatLite::CPPTYPE_MESSAGE: |
| 962 | if (is_new) { |
| 963 | extension->repeated_message_value = |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 964 | Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 965 | } |
| 966 | // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because |
| 967 | // it would attempt to allocate new objects. |
| 968 | RepeatedPtrField<MessageLite>* other_repeated_message = |
| 969 | other_extension.repeated_message_value; |
| 970 | for (int i = 0; i < other_repeated_message->size(); i++) { |
| 971 | const MessageLite& other_message = other_repeated_message->Get(i); |
Adam Cozzette | 92a7e77 | 2017-12-01 10:05:10 -0800 | [diff] [blame] | 972 | MessageLite* target = |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 973 | reinterpret_cast<internal::RepeatedPtrFieldBase*>( |
Adam Cozzette | 92a7e77 | 2017-12-01 10:05:10 -0800 | [diff] [blame] | 974 | extension->repeated_message_value) |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 975 | ->AddFromCleared<GenericTypeHandler<MessageLite>>(); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 976 | if (target == NULL) { |
| 977 | target = other_message.New(arena_); |
| 978 | extension->repeated_message_value->AddAllocated(target); |
| 979 | } |
| 980 | target->CheckTypeAndMergeFrom(other_message); |
| 981 | } |
| 982 | break; |
| 983 | } |
| 984 | } else { |
| 985 | if (!other_extension.is_cleared) { |
| 986 | switch (cpp_type(other_extension.type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 987 | #define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ |
| 988 | case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
| 989 | Set##CAMELCASE(number, other_extension.type, \ |
| 990 | other_extension.LOWERCASE##_value, \ |
| 991 | other_extension.descriptor); \ |
| 992 | break; |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 993 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 994 | HANDLE_TYPE(INT32, int32, Int32); |
| 995 | HANDLE_TYPE(INT64, int64, Int64); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 996 | HANDLE_TYPE(UINT32, uint32, UInt32); |
| 997 | HANDLE_TYPE(UINT64, uint64, UInt64); |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 998 | HANDLE_TYPE(FLOAT, float, Float); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 999 | HANDLE_TYPE(DOUBLE, double, Double); |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1000 | HANDLE_TYPE(BOOL, bool, Bool); |
| 1001 | HANDLE_TYPE(ENUM, enum, Enum); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1002 | #undef HANDLE_TYPE |
| 1003 | case WireFormatLite::CPPTYPE_STRING: |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1004 | SetString(number, other_extension.type, *other_extension.string_value, |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1005 | other_extension.descriptor); |
| 1006 | break; |
| 1007 | case WireFormatLite::CPPTYPE_MESSAGE: { |
| 1008 | Extension* extension; |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1009 | bool is_new = |
| 1010 | MaybeNewExtension(number, other_extension.descriptor, &extension); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1011 | if (is_new) { |
| 1012 | extension->type = other_extension.type; |
| 1013 | extension->is_packed = other_extension.is_packed; |
| 1014 | extension->is_repeated = false; |
| 1015 | if (other_extension.is_lazy) { |
| 1016 | extension->is_lazy = true; |
| 1017 | extension->lazymessage_value = |
| 1018 | other_extension.lazymessage_value->New(arena_); |
| 1019 | extension->lazymessage_value->MergeFrom( |
| 1020 | *other_extension.lazymessage_value); |
| 1021 | } else { |
| 1022 | extension->is_lazy = false; |
| 1023 | extension->message_value = |
| 1024 | other_extension.message_value->New(arena_); |
| 1025 | extension->message_value->CheckTypeAndMergeFrom( |
| 1026 | *other_extension.message_value); |
| 1027 | } |
| 1028 | } else { |
| 1029 | GOOGLE_DCHECK_EQ(extension->type, other_extension.type); |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1030 | GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1031 | GOOGLE_DCHECK(!extension->is_repeated); |
| 1032 | if (other_extension.is_lazy) { |
| 1033 | if (extension->is_lazy) { |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1034 | extension->lazymessage_value->MergeFrom( |
| 1035 | *other_extension.lazymessage_value); |
| 1036 | } else { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1037 | extension->message_value->CheckTypeAndMergeFrom( |
| 1038 | other_extension.lazymessage_value->GetMessage( |
| 1039 | *extension->message_value)); |
| 1040 | } |
| 1041 | } else { |
| 1042 | if (extension->is_lazy) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1043 | extension->lazymessage_value |
| 1044 | ->MutableMessage(*other_extension.message_value) |
| 1045 | ->CheckTypeAndMergeFrom(*other_extension.message_value); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1046 | } else { |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1047 | extension->message_value->CheckTypeAndMergeFrom( |
| 1048 | *other_extension.message_value); |
| 1049 | } |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1050 | } |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1051 | } |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1052 | extension->is_cleared = false; |
| 1053 | break; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1054 | } |
| 1055 | } |
| 1056 | } |
| 1057 | } |
| 1058 | } |
| 1059 | |
[email protected] | 26bd9ee | 2008-11-21 00:06:27 +0000 | [diff] [blame] | 1060 | void ExtensionSet::Swap(ExtensionSet* x) { |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1061 | #ifdef PROTOBUF_FORCE_COPY_IN_SWAP |
| 1062 | if (GetArena() != nullptr && GetArena() == x->GetArena()) { |
| 1063 | #else // PROTOBUF_FORCE_COPY_IN_SWAP |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 1064 | if (GetArena() == x->GetArena()) { |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1065 | #endif // !PROTOBUF_FORCE_COPY_IN_SWAP |
Joshua Haberman | ce56063 | 2021-04-15 15:53:17 -0700 | [diff] [blame] | 1066 | InternalSwap(x); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1067 | } else { |
| 1068 | // TODO(cfallin, rohananil): We maybe able to optimize a case where we are |
| 1069 | // swapping from heap to arena-allocated extension set, by just Own()'ing |
| 1070 | // the extensions. |
| 1071 | ExtensionSet extension_set; |
| 1072 | extension_set.MergeFrom(*x); |
| 1073 | x->Clear(); |
| 1074 | x->MergeFrom(*this); |
| 1075 | Clear(); |
| 1076 | MergeFrom(extension_set); |
| 1077 | } |
[email protected] | 26bd9ee | 2008-11-21 00:06:27 +0000 | [diff] [blame] | 1078 | } |
| 1079 | |
Joshua Haberman | ce56063 | 2021-04-15 15:53:17 -0700 | [diff] [blame] | 1080 | void ExtensionSet::InternalSwap(ExtensionSet* other) { |
| 1081 | using std::swap; |
Joshua Haberman | f5fd897 | 2021-04-30 16:12:50 -0700 | [diff] [blame] | 1082 | swap(arena_, other->arena_); |
Joshua Haberman | ce56063 | 2021-04-15 15:53:17 -0700 | [diff] [blame] | 1083 | swap(flat_capacity_, other->flat_capacity_); |
| 1084 | swap(flat_size_, other->flat_size_); |
| 1085 | swap(map_, other->map_); |
| 1086 | } |
| 1087 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1088 | void ExtensionSet::SwapExtension(ExtensionSet* other, int number) { |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1089 | if (this == other) return; |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1090 | |
| 1091 | if (GetArena() == other->GetArena()) { |
| 1092 | UnsafeShallowSwapExtension(other, number); |
| 1093 | return; |
| 1094 | } |
| 1095 | |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1096 | Extension* this_ext = FindOrNull(number); |
| 1097 | Extension* other_ext = other->FindOrNull(number); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1098 | |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1099 | if (this_ext == other_ext) return; |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1100 | |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1101 | if (this_ext != nullptr && other_ext != nullptr) { |
| 1102 | // TODO(cfallin, rohananil): We could further optimize these cases, |
| 1103 | // especially avoid creation of ExtensionSet, and move MergeFrom logic |
| 1104 | // into Extensions itself (which takes arena as an argument). |
| 1105 | // We do it this way to reuse the copy-across-arenas logic already |
| 1106 | // implemented in ExtensionSet's MergeFrom. |
| 1107 | ExtensionSet temp; |
| 1108 | temp.InternalExtensionMergeFrom(number, *other_ext); |
| 1109 | Extension* temp_ext = temp.FindOrNull(number); |
| 1110 | other_ext->Clear(); |
| 1111 | other->InternalExtensionMergeFrom(number, *this_ext); |
| 1112 | this_ext->Clear(); |
| 1113 | InternalExtensionMergeFrom(number, *temp_ext); |
| 1114 | } else if (this_ext == nullptr) { |
| 1115 | InternalExtensionMergeFrom(number, *other_ext); |
| 1116 | if (other->GetArena() == nullptr) other_ext->Free(); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1117 | other->Erase(number); |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1118 | } else { |
| 1119 | other->InternalExtensionMergeFrom(number, *this_ext); |
| 1120 | if (GetArena() == nullptr) this_ext->Free(); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1121 | Erase(number); |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1122 | } |
| 1123 | } |
| 1124 | |
| 1125 | void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) { |
| 1126 | if (this == other) return; |
| 1127 | |
| 1128 | Extension* this_ext = FindOrNull(number); |
| 1129 | Extension* other_ext = other->FindOrNull(number); |
| 1130 | |
| 1131 | if (this_ext == other_ext) return; |
| 1132 | |
| 1133 | GOOGLE_DCHECK_EQ(GetArena(), other->GetArena()); |
| 1134 | |
| 1135 | if (this_ext != nullptr && other_ext != nullptr) { |
| 1136 | std::swap(*this_ext, *other_ext); |
| 1137 | } else if (this_ext == nullptr) { |
| 1138 | *Insert(number).first = *other_ext; |
| 1139 | other->Erase(number); |
| 1140 | } else { |
| 1141 | *other->Insert(number).first = *this_ext; |
| 1142 | Erase(number); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1143 | } |
| 1144 | } |
| 1145 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1146 | bool ExtensionSet::IsInitialized() const { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1147 | // Extensions are never required. However, we need to check that all |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1148 | // embedded messages are initialized. |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1149 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1150 | for (const auto& kv : *map_.large) { |
| 1151 | if (!kv.second.IsInitialized()) return false; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1152 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1153 | return true; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1154 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1155 | for (const KeyValue* it = flat_begin(); it != flat_end(); ++it) { |
| 1156 | if (!it->second.IsInitialized()) return false; |
| 1157 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1158 | return true; |
| 1159 | } |
| 1160 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1161 | bool ExtensionSet::FindExtensionInfoFromTag(uint32 tag, |
| 1162 | ExtensionFinder* extension_finder, |
| 1163 | int* field_number, |
| 1164 | ExtensionInfo* extension, |
| 1165 | bool* was_packed_on_wire) { |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1166 | *field_number = WireFormatLite::GetTagFieldNumber(tag); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1167 | WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1168 | return FindExtensionInfoFromFieldNumber(wire_type, *field_number, |
| 1169 | extension_finder, extension, |
| 1170 | was_packed_on_wire); |
| 1171 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1172 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1173 | bool ExtensionSet::FindExtensionInfoFromFieldNumber( |
| 1174 | int wire_type, int field_number, ExtensionFinder* extension_finder, |
| 1175 | ExtensionInfo* extension, bool* was_packed_on_wire) { |
| 1176 | if (!extension_finder->Find(field_number, extension)) { |
| 1177 | return false; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1178 | } |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1179 | |
| 1180 | WireFormatLite::WireType expected_wire_type = |
| 1181 | WireFormatLite::WireTypeForFieldType(real_type(extension->type)); |
| 1182 | |
| 1183 | // Check if this is a packed field. |
| 1184 | *was_packed_on_wire = false; |
| 1185 | if (extension->is_repeated && |
| 1186 | wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED && |
| 1187 | is_packable(expected_wire_type)) { |
| 1188 | *was_packed_on_wire = true; |
| 1189 | return true; |
| 1190 | } |
| 1191 | // Otherwise the wire type must match. |
| 1192 | return expected_wire_type == wire_type; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1193 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1194 | |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1195 | bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, |
| 1196 | ExtensionFinder* extension_finder, |
| 1197 | FieldSkipper* field_skipper) { |
| 1198 | int number; |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1199 | bool was_packed_on_wire; |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1200 | ExtensionInfo extension; |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1201 | if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension, |
| 1202 | &was_packed_on_wire)) { |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1203 | return field_skipper->SkipField(input, tag); |
| 1204 | } else { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1205 | return ParseFieldWithExtensionInfo(number, was_packed_on_wire, extension, |
| 1206 | input, field_skipper); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1207 | } |
| 1208 | } |
| 1209 | |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 1210 | const char* ExtensionSet::ParseField(uint64 tag, const char* ptr, |
| 1211 | const MessageLite* containing_type, |
| 1212 | internal::InternalMetadata* metadata, |
| 1213 | internal::ParseContext* ctx) { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1214 | GeneratedExtensionFinder finder(containing_type); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1215 | int number = tag >> 3; |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1216 | bool was_packed_on_wire; |
| 1217 | ExtensionInfo extension; |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1218 | if (!FindExtensionInfoFromFieldNumber(tag & 7, number, &finder, &extension, |
| 1219 | &was_packed_on_wire)) { |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 1220 | return UnknownFieldParse( |
| 1221 | tag, metadata->mutable_unknown_fields<std::string>(), ptr, ctx); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1222 | } |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 1223 | return ParseFieldWithExtensionInfo<std::string>( |
| 1224 | number, was_packed_on_wire, extension, metadata, ptr, ctx); |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1225 | } |
Yilun Chong | d8c2501 | 2019-02-22 18:13:33 +0800 | [diff] [blame] | 1226 | |
| 1227 | const char* ExtensionSet::ParseMessageSetItem( |
| 1228 | const char* ptr, const MessageLite* containing_type, |
Joshua Haberman | b99994d | 2020-03-31 16:25:37 -0700 | [diff] [blame] | 1229 | internal::InternalMetadata* metadata, internal::ParseContext* ctx) { |
| 1230 | return ParseMessageSetItemTmpl<MessageLite, std::string>(ptr, containing_type, |
| 1231 | metadata, ctx); |
Yilun Chong | d8c2501 | 2019-02-22 18:13:33 +0800 | [diff] [blame] | 1232 | } |
| 1233 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1234 | bool ExtensionSet::ParseFieldWithExtensionInfo(int number, |
| 1235 | bool was_packed_on_wire, |
| 1236 | const ExtensionInfo& extension, |
| 1237 | io::CodedInputStream* input, |
| 1238 | FieldSkipper* field_skipper) { |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1239 | // Explicitly not read extension.is_packed, instead check whether the field |
| 1240 | // was encoded in packed form on the wire. |
| 1241 | if (was_packed_on_wire) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1242 | uint32 size; |
| 1243 | if (!input->ReadVarint32(&size)) return false; |
| 1244 | io::CodedInputStream::Limit limit = input->PushLimit(size); |
| 1245 | |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1246 | switch (extension.type) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1247 | #define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ |
| 1248 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1249 | while (input->BytesUntilLimit() > 0) { \ |
| 1250 | CPP_LOWERCASE value; \ |
| 1251 | if (!WireFormatLite::ReadPrimitive<CPP_LOWERCASE, \ |
| 1252 | WireFormatLite::TYPE_##UPPERCASE>( \ |
| 1253 | input, &value)) \ |
| 1254 | return false; \ |
| 1255 | Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ |
| 1256 | extension.is_packed, value, extension.descriptor); \ |
| 1257 | } \ |
| 1258 | break |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1259 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1260 | HANDLE_TYPE(INT32, Int32, int32); |
| 1261 | HANDLE_TYPE(INT64, Int64, int64); |
| 1262 | HANDLE_TYPE(UINT32, UInt32, uint32); |
| 1263 | HANDLE_TYPE(UINT64, UInt64, uint64); |
| 1264 | HANDLE_TYPE(SINT32, Int32, int32); |
| 1265 | HANDLE_TYPE(SINT64, Int64, int64); |
| 1266 | HANDLE_TYPE(FIXED32, UInt32, uint32); |
| 1267 | HANDLE_TYPE(FIXED64, UInt64, uint64); |
| 1268 | HANDLE_TYPE(SFIXED32, Int32, int32); |
| 1269 | HANDLE_TYPE(SFIXED64, Int64, int64); |
| 1270 | HANDLE_TYPE(FLOAT, Float, float); |
| 1271 | HANDLE_TYPE(DOUBLE, Double, double); |
| 1272 | HANDLE_TYPE(BOOL, Bool, bool); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1273 | #undef HANDLE_TYPE |
| 1274 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1275 | case WireFormatLite::TYPE_ENUM: |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1276 | while (input->BytesUntilLimit() > 0) { |
| 1277 | int value; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1278 | if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1279 | input, &value)) |
| 1280 | return false; |
[email protected] | f9c5978 | 2009-12-22 18:04:23 +0000 | [diff] [blame] | 1281 | if (extension.enum_validity_check.func( |
| 1282 | extension.enum_validity_check.arg, value)) { |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1283 | AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, |
| 1284 | value, extension.descriptor); |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame] | 1285 | } else { |
| 1286 | // Invalid value. Treat as unknown. |
| 1287 | field_skipper->SkipUnknownEnum(number, value); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1288 | } |
| 1289 | } |
| 1290 | break; |
| 1291 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1292 | case WireFormatLite::TYPE_STRING: |
| 1293 | case WireFormatLite::TYPE_BYTES: |
| 1294 | case WireFormatLite::TYPE_GROUP: |
| 1295 | case WireFormatLite::TYPE_MESSAGE: |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1296 | GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; |
| 1297 | break; |
| 1298 | } |
| 1299 | |
| 1300 | input->PopLimit(limit); |
| 1301 | } else { |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1302 | switch (extension.type) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1303 | #define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ |
| 1304 | case WireFormatLite::TYPE_##UPPERCASE: { \ |
| 1305 | CPP_LOWERCASE value; \ |
| 1306 | if (!WireFormatLite::ReadPrimitive<CPP_LOWERCASE, \ |
| 1307 | WireFormatLite::TYPE_##UPPERCASE>( \ |
| 1308 | input, &value)) \ |
| 1309 | return false; \ |
| 1310 | if (extension.is_repeated) { \ |
| 1311 | Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ |
| 1312 | extension.is_packed, value, extension.descriptor); \ |
| 1313 | } else { \ |
| 1314 | Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ |
| 1315 | extension.descriptor); \ |
| 1316 | } \ |
| 1317 | } break |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1318 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1319 | HANDLE_TYPE(INT32, Int32, int32); |
| 1320 | HANDLE_TYPE(INT64, Int64, int64); |
| 1321 | HANDLE_TYPE(UINT32, UInt32, uint32); |
| 1322 | HANDLE_TYPE(UINT64, UInt64, uint64); |
| 1323 | HANDLE_TYPE(SINT32, Int32, int32); |
| 1324 | HANDLE_TYPE(SINT64, Int64, int64); |
| 1325 | HANDLE_TYPE(FIXED32, UInt32, uint32); |
| 1326 | HANDLE_TYPE(FIXED64, UInt64, uint64); |
| 1327 | HANDLE_TYPE(SFIXED32, Int32, int32); |
| 1328 | HANDLE_TYPE(SFIXED64, Int64, int64); |
| 1329 | HANDLE_TYPE(FLOAT, Float, float); |
| 1330 | HANDLE_TYPE(DOUBLE, Double, double); |
| 1331 | HANDLE_TYPE(BOOL, Bool, bool); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1332 | #undef HANDLE_TYPE |
| 1333 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1334 | case WireFormatLite::TYPE_ENUM: { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1335 | int value; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1336 | if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1337 | input, &value)) |
| 1338 | return false; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1339 | |
[email protected] | f9c5978 | 2009-12-22 18:04:23 +0000 | [diff] [blame] | 1340 | if (!extension.enum_validity_check.func( |
| 1341 | extension.enum_validity_check.arg, value)) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1342 | // Invalid value. Treat as unknown. |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1343 | field_skipper->SkipUnknownEnum(number, value); |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1344 | } else if (extension.is_repeated) { |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1345 | AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1346 | extension.descriptor); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1347 | } else { |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1348 | SetEnum(number, WireFormatLite::TYPE_ENUM, value, |
| 1349 | extension.descriptor); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1350 | } |
| 1351 | break; |
| 1352 | } |
| 1353 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1354 | case WireFormatLite::TYPE_STRING: { |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 1355 | std::string* value = |
| 1356 | extension.is_repeated |
| 1357 | ? AddString(number, WireFormatLite::TYPE_STRING, |
| 1358 | extension.descriptor) |
| 1359 | : MutableString(number, WireFormatLite::TYPE_STRING, |
| 1360 | extension.descriptor); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1361 | if (!WireFormatLite::ReadString(input, value)) return false; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1362 | break; |
| 1363 | } |
| 1364 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1365 | case WireFormatLite::TYPE_BYTES: { |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 1366 | std::string* value = |
| 1367 | extension.is_repeated |
| 1368 | ? AddString(number, WireFormatLite::TYPE_BYTES, |
| 1369 | extension.descriptor) |
| 1370 | : MutableString(number, WireFormatLite::TYPE_BYTES, |
| 1371 | extension.descriptor); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1372 | if (!WireFormatLite::ReadBytes(input, value)) return false; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1373 | break; |
| 1374 | } |
| 1375 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1376 | case WireFormatLite::TYPE_GROUP: { |
Adam Cozzette | 0894e07 | 2018-11-09 11:28:22 -0800 | [diff] [blame] | 1377 | MessageLite* value = |
| 1378 | extension.is_repeated |
| 1379 | ? AddMessage(number, WireFormatLite::TYPE_GROUP, |
| 1380 | *extension.message_info.prototype, |
| 1381 | extension.descriptor) |
| 1382 | : MutableMessage(number, WireFormatLite::TYPE_GROUP, |
| 1383 | *extension.message_info.prototype, |
| 1384 | extension.descriptor); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1385 | if (!WireFormatLite::ReadGroup(number, input, value)) return false; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1386 | break; |
| 1387 | } |
| 1388 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1389 | case WireFormatLite::TYPE_MESSAGE: { |
Adam Cozzette | 0894e07 | 2018-11-09 11:28:22 -0800 | [diff] [blame] | 1390 | MessageLite* value = |
| 1391 | extension.is_repeated |
| 1392 | ? AddMessage(number, WireFormatLite::TYPE_MESSAGE, |
| 1393 | *extension.message_info.prototype, |
| 1394 | extension.descriptor) |
| 1395 | : MutableMessage(number, WireFormatLite::TYPE_MESSAGE, |
| 1396 | *extension.message_info.prototype, |
| 1397 | extension.descriptor); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1398 | if (!WireFormatLite::ReadMessage(input, value)) return false; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1399 | break; |
| 1400 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1401 | } |
| 1402 | } |
| 1403 | |
| 1404 | return true; |
| 1405 | } |
| 1406 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1407 | bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, |
| 1408 | const MessageLite* containing_type) { |
| 1409 | FieldSkipper skipper; |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1410 | GeneratedExtensionFinder finder(containing_type); |
| 1411 | return ParseField(tag, input, &finder, &skipper); |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1412 | } |
| 1413 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1414 | bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, |
| 1415 | const MessageLite* containing_type, |
| 1416 | io::CodedOutputStream* unknown_fields) { |
| 1417 | CodedOutputStreamFieldSkipper skipper(unknown_fields); |
| 1418 | GeneratedExtensionFinder finder(containing_type); |
| 1419 | return ParseField(tag, input, &finder, &skipper); |
| 1420 | } |
| 1421 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1422 | bool ExtensionSet::ParseMessageSetLite(io::CodedInputStream* input, |
| 1423 | ExtensionFinder* extension_finder, |
| 1424 | FieldSkipper* field_skipper) { |
| 1425 | while (true) { |
| 1426 | const uint32 tag = input->ReadTag(); |
| 1427 | switch (tag) { |
| 1428 | case 0: |
| 1429 | return true; |
| 1430 | case WireFormatLite::kMessageSetItemStartTag: |
| 1431 | if (!ParseMessageSetItemLite(input, extension_finder, field_skipper)) { |
| 1432 | return false; |
| 1433 | } |
| 1434 | break; |
| 1435 | default: |
| 1436 | if (!ParseField(tag, input, extension_finder, field_skipper)) { |
| 1437 | return false; |
| 1438 | } |
| 1439 | break; |
| 1440 | } |
| 1441 | } |
| 1442 | } |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1443 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1444 | bool ExtensionSet::ParseMessageSetItemLite(io::CodedInputStream* input, |
| 1445 | ExtensionFinder* extension_finder, |
| 1446 | FieldSkipper* field_skipper) { |
| 1447 | struct MSLite { |
| 1448 | bool ParseField(int type_id, io::CodedInputStream* input) { |
| 1449 | return me->ParseField( |
| 1450 | WireFormatLite::WIRETYPE_LENGTH_DELIMITED + 8 * type_id, input, |
| 1451 | extension_finder, field_skipper); |
| 1452 | } |
| 1453 | |
| 1454 | bool SkipField(uint32 tag, io::CodedInputStream* input) { |
| 1455 | return field_skipper->SkipField(input, tag); |
| 1456 | } |
| 1457 | |
| 1458 | ExtensionSet* me; |
| 1459 | ExtensionFinder* extension_finder; |
| 1460 | FieldSkipper* field_skipper; |
| 1461 | }; |
| 1462 | |
| 1463 | return ParseMessageSetItemImpl(input, |
| 1464 | MSLite{this, extension_finder, field_skipper}); |
| 1465 | } |
| 1466 | |
| 1467 | bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, |
| 1468 | const MessageLite* containing_type, |
Hao Nguyen | d0f91c8 | 2019-03-06 12:39:12 -0800 | [diff] [blame] | 1469 | std::string* unknown_fields) { |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1470 | io::StringOutputStream zcis(unknown_fields); |
| 1471 | io::CodedOutputStream output(&zcis); |
| 1472 | CodedOutputStreamFieldSkipper skipper(&output); |
| 1473 | GeneratedExtensionFinder finder(containing_type); |
| 1474 | return ParseMessageSetLite(input, &finder, &skipper); |
| 1475 | } |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1476 | |
Deanna Garcia | a001250 | 2021-01-22 00:24:30 +0000 | [diff] [blame] | 1477 | uint8* ExtensionSet::_InternalSerializeImpl( |
| 1478 | int start_field_number, int end_field_number, uint8* target, |
| 1479 | io::EpsCopyOutputStream* stream) const { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1480 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1481 | const auto& end = map_.large->end(); |
| 1482 | for (auto it = map_.large->lower_bound(start_field_number); |
| 1483 | it != end && it->first < end_field_number; ++it) { |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1484 | target = it->second.InternalSerializeFieldWithCachedSizesToArray( |
| 1485 | it->first, target, stream); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1486 | } |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1487 | return target; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1488 | } |
| 1489 | const KeyValue* end = flat_end(); |
| 1490 | for (const KeyValue* it = std::lower_bound( |
| 1491 | flat_begin(), end, start_field_number, KeyValue::FirstComparator()); |
| 1492 | it != end && it->first < end_field_number; ++it) { |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1493 | target = it->second.InternalSerializeFieldWithCachedSizesToArray( |
| 1494 | it->first, target, stream); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1495 | } |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1496 | return target; |
| 1497 | } |
| 1498 | |
| 1499 | uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray( |
| 1500 | uint8* target, io::EpsCopyOutputStream* stream) const { |
| 1501 | ForEach([&target, stream](int number, const Extension& ext) { |
| 1502 | target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray( |
| 1503 | number, target, stream); |
| 1504 | }); |
| 1505 | return target; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1506 | } |
| 1507 | |
Bo Yang | cc8ca5b | 2016-09-19 13:45:07 -0700 | [diff] [blame] | 1508 | size_t ExtensionSet::ByteSize() const { |
| 1509 | size_t total_size = 0; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1510 | ForEach([&total_size](int number, const Extension& ext) { |
| 1511 | total_size += ext.ByteSize(number); |
| 1512 | }); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1513 | return total_size; |
| 1514 | } |
| 1515 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1516 | // Defined in extension_set_heavy.cc. |
| 1517 | // int ExtensionSet::SpaceUsedExcludingSelf() const |
| 1518 | |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1519 | bool ExtensionSet::MaybeNewExtension(int number, |
| 1520 | const FieldDescriptor* descriptor, |
| 1521 | Extension** result) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1522 | bool extension_is_new = false; |
| 1523 | std::tie(*result, extension_is_new) = Insert(number); |
[email protected] | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1524 | (*result)->descriptor = descriptor; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1525 | return extension_is_new; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1526 | } |
| 1527 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1528 | // =================================================================== |
| 1529 | // Methods of ExtensionSet::Extension |
| 1530 | |
| 1531 | void ExtensionSet::Extension::Clear() { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1532 | if (is_repeated) { |
| 1533 | switch (cpp_type(type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1534 | #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ |
| 1535 | case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
| 1536 | repeated_##LOWERCASE##_value->Clear(); \ |
| 1537 | break |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1538 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1539 | HANDLE_TYPE(INT32, int32); |
| 1540 | HANDLE_TYPE(INT64, int64); |
| 1541 | HANDLE_TYPE(UINT32, uint32); |
| 1542 | HANDLE_TYPE(UINT64, uint64); |
| 1543 | HANDLE_TYPE(FLOAT, float); |
| 1544 | HANDLE_TYPE(DOUBLE, double); |
| 1545 | HANDLE_TYPE(BOOL, bool); |
| 1546 | HANDLE_TYPE(ENUM, enum); |
| 1547 | HANDLE_TYPE(STRING, string); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1548 | HANDLE_TYPE(MESSAGE, message); |
| 1549 | #undef HANDLE_TYPE |
| 1550 | } |
| 1551 | } else { |
| 1552 | if (!is_cleared) { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1553 | switch (cpp_type(type)) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1554 | case WireFormatLite::CPPTYPE_STRING: |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1555 | string_value->clear(); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1556 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1557 | case WireFormatLite::CPPTYPE_MESSAGE: |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1558 | if (is_lazy) { |
| 1559 | lazymessage_value->Clear(); |
| 1560 | } else { |
| 1561 | message_value->Clear(); |
| 1562 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1563 | break; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1564 | default: |
| 1565 | // No need to do anything. Get*() will return the default value |
| 1566 | // as long as is_cleared is true and Set*() will overwrite the |
| 1567 | // previous value. |
| 1568 | break; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1569 | } |
| 1570 | |
| 1571 | is_cleared = true; |
| 1572 | } |
| 1573 | } |
| 1574 | } |
| 1575 | |
Bo Yang | cc8ca5b | 2016-09-19 13:45:07 -0700 | [diff] [blame] | 1576 | size_t ExtensionSet::Extension::ByteSize(int number) const { |
| 1577 | size_t result = 0; |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1578 | |
| 1579 | if (is_repeated) { |
| 1580 | if (is_packed) { |
| 1581 | switch (real_type(type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1582 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 1583 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1584 | for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ |
| 1585 | result += WireFormatLite::CAMELCASE##Size( \ |
| 1586 | repeated_##LOWERCASE##_value->Get(i)); \ |
| 1587 | } \ |
| 1588 | break |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1589 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1590 | HANDLE_TYPE(INT32, Int32, int32); |
| 1591 | HANDLE_TYPE(INT64, Int64, int64); |
| 1592 | HANDLE_TYPE(UINT32, UInt32, uint32); |
| 1593 | HANDLE_TYPE(UINT64, UInt64, uint64); |
| 1594 | HANDLE_TYPE(SINT32, SInt32, int32); |
| 1595 | HANDLE_TYPE(SINT64, SInt64, int64); |
| 1596 | HANDLE_TYPE(ENUM, Enum, enum); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1597 | #undef HANDLE_TYPE |
| 1598 | |
| 1599 | // Stuff with fixed size. |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1600 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 1601 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1602 | result += WireFormatLite::k##CAMELCASE##Size * \ |
| 1603 | FromIntSize(repeated_##LOWERCASE##_value->size()); \ |
| 1604 | break |
| 1605 | HANDLE_TYPE(FIXED32, Fixed32, uint32); |
| 1606 | HANDLE_TYPE(FIXED64, Fixed64, uint64); |
| 1607 | HANDLE_TYPE(SFIXED32, SFixed32, int32); |
| 1608 | HANDLE_TYPE(SFIXED64, SFixed64, int64); |
| 1609 | HANDLE_TYPE(FLOAT, Float, float); |
| 1610 | HANDLE_TYPE(DOUBLE, Double, double); |
| 1611 | HANDLE_TYPE(BOOL, Bool, bool); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1612 | #undef HANDLE_TYPE |
| 1613 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1614 | case WireFormatLite::TYPE_STRING: |
| 1615 | case WireFormatLite::TYPE_BYTES: |
| 1616 | case WireFormatLite::TYPE_GROUP: |
| 1617 | case WireFormatLite::TYPE_MESSAGE: |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1618 | GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; |
| 1619 | break; |
| 1620 | } |
| 1621 | |
Bo Yang | cc8ca5b | 2016-09-19 13:45:07 -0700 | [diff] [blame] | 1622 | cached_size = ToCachedSize(result); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1623 | if (result > 0) { |
| 1624 | result += io::CodedOutputStream::VarintSize32(result); |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1625 | result += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( |
| 1626 | number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1627 | } |
| 1628 | } else { |
Bo Yang | cc8ca5b | 2016-09-19 13:45:07 -0700 | [diff] [blame] | 1629 | size_t tag_size = WireFormatLite::TagSize(number, real_type(type)); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1630 | |
| 1631 | switch (real_type(type)) { |
| 1632 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1633 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1634 | result += tag_size * FromIntSize(repeated_##LOWERCASE##_value->size()); \ |
| 1635 | for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ |
| 1636 | result += WireFormatLite::CAMELCASE##Size( \ |
| 1637 | repeated_##LOWERCASE##_value->Get(i)); \ |
| 1638 | } \ |
| 1639 | break |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1640 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1641 | HANDLE_TYPE(INT32, Int32, int32); |
| 1642 | HANDLE_TYPE(INT64, Int64, int64); |
| 1643 | HANDLE_TYPE(UINT32, UInt32, uint32); |
| 1644 | HANDLE_TYPE(UINT64, UInt64, uint64); |
| 1645 | HANDLE_TYPE(SINT32, SInt32, int32); |
| 1646 | HANDLE_TYPE(SINT64, SInt64, int64); |
| 1647 | HANDLE_TYPE(STRING, String, string); |
| 1648 | HANDLE_TYPE(BYTES, Bytes, string); |
| 1649 | HANDLE_TYPE(ENUM, Enum, enum); |
| 1650 | HANDLE_TYPE(GROUP, Group, message); |
| 1651 | HANDLE_TYPE(MESSAGE, Message, message); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1652 | #undef HANDLE_TYPE |
| 1653 | |
| 1654 | // Stuff with fixed size. |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1655 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 1656 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1657 | result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ |
| 1658 | FromIntSize(repeated_##LOWERCASE##_value->size()); \ |
| 1659 | break |
| 1660 | HANDLE_TYPE(FIXED32, Fixed32, uint32); |
| 1661 | HANDLE_TYPE(FIXED64, Fixed64, uint64); |
| 1662 | HANDLE_TYPE(SFIXED32, SFixed32, int32); |
| 1663 | HANDLE_TYPE(SFIXED64, SFixed64, int64); |
| 1664 | HANDLE_TYPE(FLOAT, Float, float); |
| 1665 | HANDLE_TYPE(DOUBLE, Double, double); |
| 1666 | HANDLE_TYPE(BOOL, Bool, bool); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1667 | #undef HANDLE_TYPE |
| 1668 | } |
| 1669 | } |
| 1670 | } else if (!is_cleared) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1671 | result += WireFormatLite::TagSize(number, real_type(type)); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1672 | switch (real_type(type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1673 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 1674 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1675 | result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \ |
| 1676 | break |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1677 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1678 | HANDLE_TYPE(INT32, Int32, int32_value); |
| 1679 | HANDLE_TYPE(INT64, Int64, int64_value); |
| 1680 | HANDLE_TYPE(UINT32, UInt32, uint32_value); |
| 1681 | HANDLE_TYPE(UINT64, UInt64, uint64_value); |
| 1682 | HANDLE_TYPE(SINT32, SInt32, int32_value); |
| 1683 | HANDLE_TYPE(SINT64, SInt64, int64_value); |
| 1684 | HANDLE_TYPE(STRING, String, *string_value); |
| 1685 | HANDLE_TYPE(BYTES, Bytes, *string_value); |
| 1686 | HANDLE_TYPE(ENUM, Enum, enum_value); |
| 1687 | HANDLE_TYPE(GROUP, Group, *message_value); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1688 | #undef HANDLE_TYPE |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1689 | case WireFormatLite::TYPE_MESSAGE: { |
| 1690 | if (is_lazy) { |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 1691 | size_t size = lazymessage_value->ByteSizeLong(); |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1692 | result += io::CodedOutputStream::VarintSize32(size) + size; |
| 1693 | } else { |
| 1694 | result += WireFormatLite::MessageSize(*message_value); |
| 1695 | } |
| 1696 | break; |
| 1697 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1698 | |
| 1699 | // Stuff with fixed size. |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1700 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ |
| 1701 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1702 | result += WireFormatLite::k##CAMELCASE##Size; \ |
| 1703 | break |
| 1704 | HANDLE_TYPE(FIXED32, Fixed32); |
| 1705 | HANDLE_TYPE(FIXED64, Fixed64); |
| 1706 | HANDLE_TYPE(SFIXED32, SFixed32); |
| 1707 | HANDLE_TYPE(SFIXED64, SFixed64); |
| 1708 | HANDLE_TYPE(FLOAT, Float); |
| 1709 | HANDLE_TYPE(DOUBLE, Double); |
| 1710 | HANDLE_TYPE(BOOL, Bool); |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1711 | #undef HANDLE_TYPE |
| 1712 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1713 | } |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1714 | |
| 1715 | return result; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1716 | } |
| 1717 | |
| 1718 | int ExtensionSet::Extension::GetSize() const { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1719 | GOOGLE_DCHECK(is_repeated); |
| 1720 | switch (cpp_type(type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1721 | #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ |
| 1722 | case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
| 1723 | return repeated_##LOWERCASE##_value->size() |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1724 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1725 | HANDLE_TYPE(INT32, int32); |
| 1726 | HANDLE_TYPE(INT64, int64); |
| 1727 | HANDLE_TYPE(UINT32, uint32); |
| 1728 | HANDLE_TYPE(UINT64, uint64); |
| 1729 | HANDLE_TYPE(FLOAT, float); |
| 1730 | HANDLE_TYPE(DOUBLE, double); |
| 1731 | HANDLE_TYPE(BOOL, bool); |
| 1732 | HANDLE_TYPE(ENUM, enum); |
| 1733 | HANDLE_TYPE(STRING, string); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1734 | HANDLE_TYPE(MESSAGE, message); |
| 1735 | #undef HANDLE_TYPE |
| 1736 | } |
| 1737 | |
| 1738 | GOOGLE_LOG(FATAL) << "Can't get here."; |
| 1739 | return 0; |
| 1740 | } |
| 1741 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1742 | // This function deletes all allocated objects. This function should be only |
Deanna Garcia | 380e352 | 2021-05-14 17:50:31 +0000 | [diff] [blame] | 1743 | // called if the Extension was created without an arena. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1744 | void ExtensionSet::Extension::Free() { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1745 | if (is_repeated) { |
| 1746 | switch (cpp_type(type)) { |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1747 | #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ |
| 1748 | case WireFormatLite::CPPTYPE_##UPPERCASE: \ |
| 1749 | delete repeated_##LOWERCASE##_value; \ |
| 1750 | break |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1751 | |
Hao Nguyen | 176f7db | 2019-04-09 06:23:32 -0700 | [diff] [blame] | 1752 | HANDLE_TYPE(INT32, int32); |
| 1753 | HANDLE_TYPE(INT64, int64); |
| 1754 | HANDLE_TYPE(UINT32, uint32); |
| 1755 | HANDLE_TYPE(UINT64, uint64); |
| 1756 | HANDLE_TYPE(FLOAT, float); |
| 1757 | HANDLE_TYPE(DOUBLE, double); |
| 1758 | HANDLE_TYPE(BOOL, bool); |
| 1759 | HANDLE_TYPE(ENUM, enum); |
| 1760 | HANDLE_TYPE(STRING, string); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1761 | HANDLE_TYPE(MESSAGE, message); |
| 1762 | #undef HANDLE_TYPE |
| 1763 | } |
| 1764 | } else { |
[email protected] | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 1765 | switch (cpp_type(type)) { |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1766 | case WireFormatLite::CPPTYPE_STRING: |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1767 | delete string_value; |
| 1768 | break; |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1769 | case WireFormatLite::CPPTYPE_MESSAGE: |
[email protected] | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1770 | if (is_lazy) { |
| 1771 | delete lazymessage_value; |
| 1772 | } else { |
| 1773 | delete message_value; |
| 1774 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1775 | break; |
| 1776 | default: |
| 1777 | break; |
| 1778 | } |
| 1779 | } |
| 1780 | } |
| 1781 | |
[email protected] | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1782 | // Defined in extension_set_heavy.cc. |
| 1783 | // int ExtensionSet::Extension::SpaceUsedExcludingSelf() const |
[email protected] | 26bd9ee | 2008-11-21 00:06:27 +0000 | [diff] [blame] | 1784 | |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1785 | bool ExtensionSet::Extension::IsInitialized() const { |
| 1786 | if (cpp_type(type) == WireFormatLite::CPPTYPE_MESSAGE) { |
| 1787 | if (is_repeated) { |
| 1788 | for (int i = 0; i < repeated_message_value->size(); i++) { |
| 1789 | if (!repeated_message_value->Get(i).IsInitialized()) { |
| 1790 | return false; |
| 1791 | } |
| 1792 | } |
| 1793 | } else { |
| 1794 | if (!is_cleared) { |
| 1795 | if (is_lazy) { |
| 1796 | if (!lazymessage_value->IsInitialized()) return false; |
| 1797 | } else { |
| 1798 | if (!message_value->IsInitialized()) return false; |
| 1799 | } |
| 1800 | } |
| 1801 | } |
| 1802 | } |
| 1803 | return true; |
| 1804 | } |
| 1805 | |
Adam Cozzette | 92a7e77 | 2017-12-01 10:05:10 -0800 | [diff] [blame] | 1806 | // Dummy key method to avoid weak vtable. |
| 1807 | void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {} |
| 1808 | |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1809 | const ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) const { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1810 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1811 | return FindOrNullInLargeMap(key); |
| 1812 | } |
| 1813 | const KeyValue* end = flat_end(); |
| 1814 | const KeyValue* it = |
| 1815 | std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); |
| 1816 | if (it != end && it->first == key) { |
| 1817 | return &it->second; |
| 1818 | } |
| 1819 | return NULL; |
| 1820 | } |
| 1821 | |
| 1822 | const ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap( |
| 1823 | int key) const { |
| 1824 | assert(is_large()); |
| 1825 | LargeMap::const_iterator it = map_.large->find(key); |
| 1826 | if (it != map_.large->end()) { |
| 1827 | return &it->second; |
| 1828 | } |
| 1829 | return NULL; |
| 1830 | } |
| 1831 | |
| 1832 | ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1833 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1834 | return FindOrNullInLargeMap(key); |
| 1835 | } |
| 1836 | KeyValue* end = flat_end(); |
| 1837 | KeyValue* it = |
| 1838 | std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); |
| 1839 | if (it != end && it->first == key) { |
| 1840 | return &it->second; |
| 1841 | } |
| 1842 | return NULL; |
| 1843 | } |
| 1844 | |
| 1845 | ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(int key) { |
| 1846 | assert(is_large()); |
| 1847 | LargeMap::iterator it = map_.large->find(key); |
| 1848 | if (it != map_.large->end()) { |
| 1849 | return &it->second; |
| 1850 | } |
| 1851 | return NULL; |
| 1852 | } |
| 1853 | |
| 1854 | std::pair<ExtensionSet::Extension*, bool> ExtensionSet::Insert(int key) { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1855 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1856 | auto maybe = map_.large->insert({key, Extension()}); |
| 1857 | return {&maybe.first->second, maybe.second}; |
| 1858 | } |
| 1859 | KeyValue* end = flat_end(); |
| 1860 | KeyValue* it = |
| 1861 | std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); |
| 1862 | if (it != end && it->first == key) { |
| 1863 | return {&it->second, false}; |
| 1864 | } |
| 1865 | if (flat_size_ < flat_capacity_) { |
| 1866 | std::copy_backward(it, end, end + 1); |
| 1867 | ++flat_size_; |
| 1868 | it->first = key; |
| 1869 | it->second = Extension(); |
| 1870 | return {&it->second, true}; |
| 1871 | } |
| 1872 | GrowCapacity(flat_size_ + 1); |
| 1873 | return Insert(key); |
| 1874 | } |
| 1875 | |
| 1876 | void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1877 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1878 | return; // LargeMap does not have a "reserve" method. |
| 1879 | } |
| 1880 | if (flat_capacity_ >= minimum_new_capacity) { |
| 1881 | return; |
| 1882 | } |
| 1883 | |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1884 | auto new_flat_capacity = flat_capacity_; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1885 | do { |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1886 | new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4; |
| 1887 | } while (new_flat_capacity < minimum_new_capacity); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1888 | |
| 1889 | const KeyValue* begin = flat_begin(); |
| 1890 | const KeyValue* end = flat_end(); |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1891 | AllocatedData new_map; |
| 1892 | if (new_flat_capacity > kMaximumFlatCapacity) { |
| 1893 | new_map.large = Arena::Create<LargeMap>(arena_); |
| 1894 | LargeMap::iterator hint = new_map.large->begin(); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1895 | for (const KeyValue* it = begin; it != end; ++it) { |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1896 | hint = new_map.large->insert(hint, {it->first, it->second}); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1897 | } |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1898 | } else { |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1899 | new_map.flat = Arena::CreateArray<KeyValue>(arena_, new_flat_capacity); |
| 1900 | std::copy(begin, end, new_map.flat); |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1901 | } |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1902 | |
Feng Xiao | 6bbe197 | 2018-08-08 17:00:41 -0700 | [diff] [blame] | 1903 | if (arena_ == nullptr) { |
Joshua Haberman | 95e6c5b | 2020-08-17 15:26:13 -0700 | [diff] [blame] | 1904 | DeleteFlatMap(begin, flat_capacity_); |
| 1905 | } |
| 1906 | flat_capacity_ = new_flat_capacity; |
| 1907 | map_ = new_map; |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1908 | } |
| 1909 | |
| 1910 | // static |
| 1911 | constexpr uint16 ExtensionSet::kMaximumFlatCapacity; |
| 1912 | |
| 1913 | void ExtensionSet::Erase(int key) { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 1914 | if (PROTOBUF_PREDICT_FALSE(is_large())) { |
Adam Cozzette | 0400cca | 2018-03-13 16:37:29 -0700 | [diff] [blame] | 1915 | map_.large->erase(key); |
| 1916 | return; |
| 1917 | } |
| 1918 | KeyValue* end = flat_end(); |
| 1919 | KeyValue* it = |
| 1920 | std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); |
| 1921 | if (it != end && it->first == key) { |
| 1922 | std::copy(it + 1, end, it); |
| 1923 | --flat_size_; |
| 1924 | } |
| 1925 | } |
| 1926 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1927 | // ================================================================== |
| 1928 | // Default repeated field instances for iterator-compatible accessors |
| 1929 | |
Adam Cozzette | a9abc78 | 2018-07-06 14:12:33 -0700 | [diff] [blame] | 1930 | const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() { |
| 1931 | static auto instance = OnShutdownDelete(new RepeatedPrimitiveDefaults); |
| 1932 | return instance; |
Peter Kasting | 4f3bead | 2015-08-27 20:16:33 -0700 | [diff] [blame] | 1933 | } |
| 1934 | |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1935 | const RepeatedStringTypeTraits::RepeatedFieldType* |
Adam Cozzette | a9abc78 | 2018-07-06 14:12:33 -0700 | [diff] [blame] | 1936 | RepeatedStringTypeTraits::GetDefaultRepeatedField() { |
| 1937 | static auto instance = OnShutdownDelete(new RepeatedFieldType); |
| 1938 | return instance; |
| 1939 | } |
[email protected] | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1940 | |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1941 | uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( |
| 1942 | int number, uint8* target, io::EpsCopyOutputStream* stream) const { |
| 1943 | if (is_repeated) { |
| 1944 | if (is_packed) { |
| 1945 | if (cached_size == 0) return target; |
| 1946 | |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 1947 | target = stream->EnsureSpace(target); |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1948 | target = WireFormatLite::WriteTagToArray( |
| 1949 | number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); |
| 1950 | target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); |
| 1951 | |
| 1952 | switch (real_type(type)) { |
| 1953 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 1954 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1955 | for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 1956 | target = stream->EnsureSpace(target); \ |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1957 | target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ |
| 1958 | repeated_##LOWERCASE##_value->Get(i), target); \ |
| 1959 | } \ |
| 1960 | break |
| 1961 | |
| 1962 | HANDLE_TYPE(INT32, Int32, int32); |
| 1963 | HANDLE_TYPE(INT64, Int64, int64); |
| 1964 | HANDLE_TYPE(UINT32, UInt32, uint32); |
| 1965 | HANDLE_TYPE(UINT64, UInt64, uint64); |
| 1966 | HANDLE_TYPE(SINT32, SInt32, int32); |
| 1967 | HANDLE_TYPE(SINT64, SInt64, int64); |
| 1968 | HANDLE_TYPE(FIXED32, Fixed32, uint32); |
| 1969 | HANDLE_TYPE(FIXED64, Fixed64, uint64); |
| 1970 | HANDLE_TYPE(SFIXED32, SFixed32, int32); |
| 1971 | HANDLE_TYPE(SFIXED64, SFixed64, int64); |
| 1972 | HANDLE_TYPE(FLOAT, Float, float); |
| 1973 | HANDLE_TYPE(DOUBLE, Double, double); |
| 1974 | HANDLE_TYPE(BOOL, Bool, bool); |
| 1975 | HANDLE_TYPE(ENUM, Enum, enum); |
| 1976 | #undef HANDLE_TYPE |
| 1977 | |
| 1978 | case WireFormatLite::TYPE_STRING: |
| 1979 | case WireFormatLite::TYPE_BYTES: |
| 1980 | case WireFormatLite::TYPE_GROUP: |
| 1981 | case WireFormatLite::TYPE_MESSAGE: |
| 1982 | GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; |
| 1983 | break; |
| 1984 | } |
| 1985 | } else { |
| 1986 | switch (real_type(type)) { |
| 1987 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 1988 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 1989 | for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 1990 | target = stream->EnsureSpace(target); \ |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 1991 | target = WireFormatLite::Write##CAMELCASE##ToArray( \ |
| 1992 | number, repeated_##LOWERCASE##_value->Get(i), target); \ |
| 1993 | } \ |
| 1994 | break |
| 1995 | |
| 1996 | HANDLE_TYPE(INT32, Int32, int32); |
| 1997 | HANDLE_TYPE(INT64, Int64, int64); |
| 1998 | HANDLE_TYPE(UINT32, UInt32, uint32); |
| 1999 | HANDLE_TYPE(UINT64, UInt64, uint64); |
| 2000 | HANDLE_TYPE(SINT32, SInt32, int32); |
| 2001 | HANDLE_TYPE(SINT64, SInt64, int64); |
| 2002 | HANDLE_TYPE(FIXED32, Fixed32, uint32); |
| 2003 | HANDLE_TYPE(FIXED64, Fixed64, uint64); |
| 2004 | HANDLE_TYPE(SFIXED32, SFixed32, int32); |
| 2005 | HANDLE_TYPE(SFIXED64, SFixed64, int64); |
| 2006 | HANDLE_TYPE(FLOAT, Float, float); |
| 2007 | HANDLE_TYPE(DOUBLE, Double, double); |
| 2008 | HANDLE_TYPE(BOOL, Bool, bool); |
| 2009 | HANDLE_TYPE(ENUM, Enum, enum); |
| 2010 | #undef HANDLE_TYPE |
| 2011 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 2012 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 2013 | for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2014 | target = stream->EnsureSpace(target); \ |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2015 | target = stream->WriteString( \ |
| 2016 | number, repeated_##LOWERCASE##_value->Get(i), target); \ |
| 2017 | } \ |
| 2018 | break |
| 2019 | HANDLE_TYPE(STRING, String, string); |
| 2020 | HANDLE_TYPE(BYTES, Bytes, string); |
| 2021 | #undef HANDLE_TYPE |
| 2022 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ |
| 2023 | case WireFormatLite::TYPE_##UPPERCASE: \ |
| 2024 | for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2025 | target = stream->EnsureSpace(target); \ |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2026 | target = WireFormatLite::InternalWrite##CAMELCASE( \ |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2027 | number, repeated_##LOWERCASE##_value->Get(i), target, stream); \ |
| 2028 | } \ |
| 2029 | break |
| 2030 | |
| 2031 | HANDLE_TYPE(GROUP, Group, message); |
| 2032 | HANDLE_TYPE(MESSAGE, Message, message); |
| 2033 | #undef HANDLE_TYPE |
| 2034 | } |
| 2035 | } |
| 2036 | } else if (!is_cleared) { |
| 2037 | switch (real_type(type)) { |
| 2038 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ |
| 2039 | case WireFormatLite::TYPE_##UPPERCASE: \ |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2040 | target = stream->EnsureSpace(target); \ |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2041 | target = WireFormatLite::Write##CAMELCASE##ToArray(number, VALUE, target); \ |
| 2042 | break |
| 2043 | |
| 2044 | HANDLE_TYPE(INT32, Int32, int32_value); |
| 2045 | HANDLE_TYPE(INT64, Int64, int64_value); |
| 2046 | HANDLE_TYPE(UINT32, UInt32, uint32_value); |
| 2047 | HANDLE_TYPE(UINT64, UInt64, uint64_value); |
| 2048 | HANDLE_TYPE(SINT32, SInt32, int32_value); |
| 2049 | HANDLE_TYPE(SINT64, SInt64, int64_value); |
| 2050 | HANDLE_TYPE(FIXED32, Fixed32, uint32_value); |
| 2051 | HANDLE_TYPE(FIXED64, Fixed64, uint64_value); |
| 2052 | HANDLE_TYPE(SFIXED32, SFixed32, int32_value); |
| 2053 | HANDLE_TYPE(SFIXED64, SFixed64, int64_value); |
| 2054 | HANDLE_TYPE(FLOAT, Float, float_value); |
| 2055 | HANDLE_TYPE(DOUBLE, Double, double_value); |
| 2056 | HANDLE_TYPE(BOOL, Bool, bool_value); |
| 2057 | HANDLE_TYPE(ENUM, Enum, enum_value); |
| 2058 | #undef HANDLE_TYPE |
| 2059 | #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ |
| 2060 | case WireFormatLite::TYPE_##UPPERCASE: \ |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2061 | target = stream->EnsureSpace(target); \ |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2062 | target = stream->WriteString(number, VALUE, target); \ |
| 2063 | break |
| 2064 | HANDLE_TYPE(STRING, String, *string_value); |
| 2065 | HANDLE_TYPE(BYTES, Bytes, *string_value); |
| 2066 | #undef HANDLE_TYPE |
| 2067 | case WireFormatLite::TYPE_GROUP: |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2068 | target = stream->EnsureSpace(target); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2069 | target = WireFormatLite::InternalWriteGroup(number, *message_value, |
| 2070 | target, stream); |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2071 | break; |
| 2072 | case WireFormatLite::TYPE_MESSAGE: |
| 2073 | if (is_lazy) { |
| 2074 | target = |
| 2075 | lazymessage_value->WriteMessageToArray(number, target, stream); |
| 2076 | } else { |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2077 | target = stream->EnsureSpace(target); |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2078 | target = WireFormatLite::InternalWriteMessage(number, *message_value, |
| 2079 | target, stream); |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2080 | } |
| 2081 | break; |
| 2082 | } |
| 2083 | } |
| 2084 | return target; |
| 2085 | } |
| 2086 | |
| 2087 | uint8* |
| 2088 | ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray( |
| 2089 | int number, uint8* target, io::EpsCopyOutputStream* stream) const { |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2090 | if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { |
| 2091 | // Not a valid MessageSet extension, but serialize it the normal way. |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2092 | GOOGLE_LOG(WARNING) << "Invalid message set extension."; |
| 2093 | return InternalSerializeFieldWithCachedSizesToArray(number, target, stream); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2094 | } |
| 2095 | |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2096 | if (is_cleared) return target; |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2097 | |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2098 | target = stream->EnsureSpace(target); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2099 | // Start group. |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2100 | target = io::CodedOutputStream::WriteTagToArray( |
| 2101 | WireFormatLite::kMessageSetItemStartTag, target); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2102 | // Write type ID. |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2103 | target = WireFormatLite::WriteUInt32ToArray( |
| 2104 | WireFormatLite::kMessageSetTypeIdNumber, number, target); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2105 | // Write message. |
| 2106 | if (is_lazy) { |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2107 | target = lazymessage_value->WriteMessageToArray( |
| 2108 | WireFormatLite::kMessageSetMessageNumber, target, stream); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2109 | } else { |
Rafi Kamal | 58d4420 | 2019-11-11 17:06:56 -0800 | [diff] [blame] | 2110 | target = WireFormatLite::InternalWriteMessage( |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2111 | WireFormatLite::kMessageSetMessageNumber, *message_value, target, |
| 2112 | stream); |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2113 | } |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2114 | // End group. |
Paul Yang | 763c358 | 2019-09-12 11:03:27 -0700 | [diff] [blame] | 2115 | target = stream->EnsureSpace(target); |
Hao Nguyen | 51026d9 | 2019-06-26 11:01:34 -0700 | [diff] [blame] | 2116 | target = io::CodedOutputStream::WriteTagToArray( |
| 2117 | WireFormatLite::kMessageSetItemEndTag, target); |
| 2118 | return target; |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2119 | } |
| 2120 | |
| 2121 | size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const { |
| 2122 | if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { |
| 2123 | // Not a valid MessageSet extension, but compute the byte size for it the |
| 2124 | // normal way. |
| 2125 | return ByteSize(number); |
| 2126 | } |
| 2127 | |
| 2128 | if (is_cleared) return 0; |
| 2129 | |
| 2130 | size_t our_size = WireFormatLite::kMessageSetItemTagsSize; |
| 2131 | |
| 2132 | // type_id |
| 2133 | our_size += io::CodedOutputStream::VarintSize32(number); |
| 2134 | |
| 2135 | // message |
| 2136 | size_t message_size = 0; |
| 2137 | if (is_lazy) { |
| 2138 | message_size = lazymessage_value->ByteSizeLong(); |
| 2139 | } else { |
| 2140 | message_size = message_value->ByteSizeLong(); |
| 2141 | } |
| 2142 | |
| 2143 | our_size += io::CodedOutputStream::VarintSize32(message_size); |
| 2144 | our_size += message_size; |
| 2145 | |
| 2146 | return our_size; |
| 2147 | } |
| 2148 | |
Josh Haberman | d61aede | 2018-09-04 10:58:54 -0700 | [diff] [blame] | 2149 | size_t ExtensionSet::MessageSetByteSize() const { |
| 2150 | size_t total_size = 0; |
| 2151 | ForEach([&total_size](int number, const Extension& ext) { |
| 2152 | total_size += ext.MessageSetItemByteSize(number); |
| 2153 | }); |
| 2154 | return total_size; |
| 2155 | } |
| 2156 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 2157 | } // namespace internal |
| 2158 | } // namespace protobuf |
| 2159 | } // namespace google |
Joshua Haberman | 5c028d6 | 2020-11-20 10:44:58 -0800 | [diff] [blame] | 2160 | |
| 2161 | #include <google/protobuf/port_undef.inc> |