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