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 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ 32 #define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ 33 34 #include <assert.h> 35 #include <string> 36 37 #include <google/protobuf/stubs/casts.h> 38 #include <google/protobuf/parse_context.h> 39 #include <google/protobuf/io/coded_stream.h> 40 #include <google/protobuf/arena.h> 41 #include <google/protobuf/arenastring.h> 42 #include <google/protobuf/generated_message_util.h> 43 #include <google/protobuf/map.h> 44 #include <google/protobuf/map_type_handler.h> 45 #include <google/protobuf/port.h> 46 #include <google/protobuf/wire_format_lite.h> 47 48 #include <google/protobuf/port_def.inc> 49 #ifdef SWIG 50 #error "You cannot SWIG proto headers" 51 #endif 52 53 namespace google { 54 namespace protobuf { 55 namespace internal { 56 template <typename Derived, typename Key, typename Value, 57 WireFormatLite::FieldType kKeyFieldType, 58 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 59 class MapEntry; 60 template <typename Derived, typename Key, typename Value, 61 WireFormatLite::FieldType kKeyFieldType, 62 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 63 class MapFieldLite; 64 } // namespace internal 65 } // namespace protobuf 66 } // namespace google 67 68 namespace google { 69 namespace protobuf { 70 namespace internal { 71 72 // MoveHelper::Move is used to set *dest. It copies *src, or moves it (in 73 // the C++11 sense), or swaps it. *src is left in a sane state for 74 // subsequent destruction, but shouldn't be used for anything. 75 template <bool is_enum, bool is_message, bool is_stringlike, typename T> 76 struct MoveHelper { // primitives MoveMoveHelper77 static void Move(T* src, T* dest) { *dest = *src; } 78 }; 79 80 template <bool is_message, bool is_stringlike, typename T> 81 struct MoveHelper<true, is_message, is_stringlike, T> { // enums 82 static void Move(T* src, T* dest) { *dest = *src; } 83 // T is an enum here, so allow conversions to and from int. 84 static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); } 85 static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); } 86 }; 87 88 template <bool is_stringlike, typename T> 89 struct MoveHelper<false, true, is_stringlike, T> { // messages 90 static void Move(T* src, T* dest) { dest->Swap(src); } 91 }; 92 93 template <typename T> 94 struct MoveHelper<false, false, true, T> { // strings and similar 95 static void Move(T* src, T* dest) { 96 #if __cplusplus >= 201103L 97 *dest = std::move(*src); 98 #else 99 dest->swap(*src); 100 #endif 101 } 102 }; 103 104 // Functions for operating on a map entry. Does not contain any representation 105 // (this class is not intended to be instantiated). 106 template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, 107 WireFormatLite::FieldType kValueFieldType> 108 struct MapEntryFuncs { 109 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; 110 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler; 111 static const int kKeyFieldNumber = 1; 112 static const int kValueFieldNumber = 2; 113 114 static void SerializeToCodedStream(int field_number, const Key& key, 115 const Value& value, 116 io::CodedOutputStream* output) { 117 WireFormatLite::WriteTag(field_number, 118 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); 119 output->WriteVarint32(GetCachedSize(key, value)); 120 KeyTypeHandler::Write(kKeyFieldNumber, key, output); 121 ValueTypeHandler::Write(kValueFieldNumber, value, output); 122 } 123 124 static ::google::protobuf::uint8* SerializeToArray(int field_number, const Key& key, 125 const Value& value, ::google::protobuf::uint8* output) { 126 output = WireFormatLite::WriteTagToArray( 127 field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); 128 output = io::CodedOutputStream::WriteVarint32ToArray( 129 static_cast<uint32>(GetCachedSize(key, value)), output); 130 output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key, output); 131 output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value, output); 132 return output; 133 } 134 135 static size_t ByteSizeLong(const Key& key, const Value& value) { 136 // Tags for key and value will both be one byte (field numbers 1 and 2). 137 size_t inner_length = 138 2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value); 139 return inner_length + io::CodedOutputStream::VarintSize32(inner_length); 140 } 141 142 static int GetCachedSize(const Key& key, const Value& value) { 143 // Tags for key and value will both be one byte (field numbers 1 and 2). 144 return 2 + KeyTypeHandler::GetCachedSize(key) + 145 ValueTypeHandler::GetCachedSize(value); 146 } 147 }; 148 149 // MapEntryImpl is used to implement parsing and serialization of map entries. 150 // It uses Curious Recursive Template Pattern (CRTP) to provide the type of 151 // the eventual code to the template code. 152 template <typename Derived, typename Base, typename Key, typename Value, 153 WireFormatLite::FieldType kKeyFieldType, 154 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 155 class MapEntryImpl : public Base { 156 public: 157 typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs; 158 159 protected: 160 // Provide utilities to parse/serialize key/value. Provide utilities to 161 // manipulate internal stored type. 162 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; 163 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler; 164 165 // Define internal memory layout. Strings and messages are stored as 166 // pointers, while other types are stored as values. 167 typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory; 168 typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory; 169 170 // Enum type cannot be used for MapTypeHandler::Read. Define a type 171 // which will replace Enum with int. 172 typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType; 173 typedef 174 typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType; 175 176 // Constants for field number. 177 static const int kKeyFieldNumber = 1; 178 static const int kValueFieldNumber = 2; 179 180 // Constants for field tag. 181 static const uint8 kKeyTag = 182 GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType); 183 static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( 184 kValueFieldNumber, ValueTypeHandler::kWireType); 185 static const size_t kTagSize = 1; 186 187 public: 188 // Work-around for a compiler bug (see repeated_field.h). 189 typedef void MapEntryHasMergeTypeTrait; 190 typedef Derived EntryType; 191 typedef Key EntryKeyType; 192 typedef Value EntryValueType; 193 static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType; 194 static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType; 195 static const int kEntryDefaultEnumValue = default_enum_value; 196 197 MapEntryImpl() : arena_(NULL) { 198 KeyTypeHandler::Initialize(&key_, NULL); 199 ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value, 200 NULL); 201 _has_bits_[0] = 0; 202 } 203 204 explicit MapEntryImpl(Arena* arena) : arena_(arena) { 205 KeyTypeHandler::Initialize(&key_, arena); 206 ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value, 207 arena); 208 _has_bits_[0] = 0; 209 } 210 211 ~MapEntryImpl() { 212 if (GetArenaNoVirtual() != NULL) return; 213 KeyTypeHandler::DeleteNoArena(key_); 214 ValueTypeHandler::DeleteNoArena(value_); 215 } 216 217 // accessors ====================================================== 218 219 virtual inline const KeyMapEntryAccessorType& key() const { 220 return KeyTypeHandler::GetExternalReference(key_); 221 } 222 virtual inline const ValueMapEntryAccessorType& value() const { 223 return ValueTypeHandler::DefaultIfNotInitialized( 224 value_, Derived::internal_default_instance()->value_); 225 } 226 inline KeyMapEntryAccessorType* mutable_key() { 227 set_has_key(); 228 return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual()); 229 } 230 inline ValueMapEntryAccessorType* mutable_value() { 231 set_has_value(); 232 return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual()); 233 } 234 235 // implements MessageLite ========================================= 236 237 // MapEntryImpl is for implementation only and this function isn't called 238 // anywhere. Just provide a fake implementation here for MessageLite. 239 std::string GetTypeName() const override { return ""; } 240 241 void CheckTypeAndMergeFrom(const MessageLite& other) override { 242 MergeFromInternal(*::google::protobuf::internal::DownCast<const Derived*>(&other)); 243 } 244 245 #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 246 const char* _InternalParse(const char* ptr, ParseContext* ctx) final { 247 while (!ctx->Done(&ptr)) { 248 uint32 tag; 249 ptr = ReadTag(ptr, &tag); 250 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 251 if (tag == kKeyTag) { 252 set_has_key(); 253 KeyMapEntryAccessorType* key = mutable_key(); 254 ptr = KeyTypeHandler::Read(ptr, ctx, key); 255 if (!Derived::ValidateKey(key)) return nullptr; 256 } else if (tag == kValueTag) { 257 set_has_value(); 258 ValueMapEntryAccessorType* value = mutable_value(); 259 ptr = ValueTypeHandler::Read(ptr, ctx, value); 260 if (!Derived::ValidateValue(value)) return nullptr; 261 } else { 262 if (tag == 0 || WireFormatLite::GetTagWireType(tag) == 263 WireFormatLite::WIRETYPE_END_GROUP) { 264 ctx->SetLastTag(tag); 265 return ptr; 266 } 267 ptr = UnknownFieldParse(tag, static_cast<string*>(nullptr), ptr, ctx); 268 } 269 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 270 } 271 return ptr; 272 } 273 #else 274 bool MergePartialFromCodedStream(io::CodedInputStream* input) override { 275 uint32 tag; 276 277 for (;;) { 278 // 1) corrupted data: return false; 279 // 2) unknown field: skip without putting into unknown field set; 280 // 3) unknown enum value: keep it in parsing. In proto2, caller should 281 // check the value and put this entry into containing message's unknown 282 // field set if the value is an unknown enum. In proto3, caller doesn't 283 // need to care whether the value is unknown enum; 284 // 4) missing key/value: missed key/value will have default value. caller 285 // should take this entry as if key/value is set to default value. 286 tag = input->ReadTagNoLastTag(); 287 switch (tag) { 288 case kKeyTag: 289 if (!KeyTypeHandler::Read(input, mutable_key())) { 290 return false; 291 } 292 set_has_key(); 293 break; 294 295 case kValueTag: 296 if (!ValueTypeHandler::Read(input, mutable_value())) { 297 return false; 298 } 299 set_has_value(); 300 if (input->ExpectAtEnd()) return true; 301 break; 302 303 default: 304 if (tag == 0 || WireFormatLite::GetTagWireType(tag) == 305 WireFormatLite::WIRETYPE_END_GROUP) { 306 return true; 307 } 308 if (!WireFormatLite::SkipField(input, tag)) return false; 309 break; 310 } 311 } 312 } 313 #endif 314 315 size_t ByteSizeLong() const override { 316 size_t size = 0; 317 size += has_key() ? kTagSize + 318 static_cast<size_t>(KeyTypeHandler::ByteSize(key())) 319 : 0; 320 size += has_value() 321 ? kTagSize + 322 static_cast<size_t>(ValueTypeHandler::ByteSize(value())) 323 : 0; 324 return size; 325 } 326 327 void SerializeWithCachedSizes(io::CodedOutputStream* output) const override { 328 KeyTypeHandler::Write(kKeyFieldNumber, key(), output); 329 ValueTypeHandler::Write(kValueFieldNumber, value(), output); 330 } 331 332 ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 333 ::google::protobuf::uint8* output) const override { 334 output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output); 335 output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value(), output); 336 return output; 337 } 338 339 // Don't override SerializeWithCachedSizesToArray. Use MessageLite's. 340 341 int GetCachedSize() const override { 342 int size = 0; 343 size += has_key() ? static_cast<int>(kTagSize) + 344 KeyTypeHandler::GetCachedSize(key()) 345 : 0; 346 size += has_value() ? static_cast<int>(kTagSize) + 347 ValueTypeHandler::GetCachedSize(value()) 348 : 0; 349 return size; 350 } 351 352 bool IsInitialized() const override { 353 return ValueTypeHandler::IsInitialized(value_); 354 } 355 356 Base* New() const override { 357 Derived* entry = new Derived; 358 return entry; 359 } 360 361 Base* New(Arena* arena) const override { 362 Derived* entry = Arena::CreateMessage<Derived>(arena); 363 return entry; 364 } 365 366 protected: 367 // We can't declare this function directly here as it would hide the other 368 // overload (const Message&). 369 void MergeFromInternal(const MapEntryImpl& from) { 370 if (from._has_bits_[0]) { 371 if (from.has_key()) { 372 KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual()); 373 KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual()); 374 set_has_key(); 375 } 376 if (from.has_value()) { 377 ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual()); 378 ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual()); 379 set_has_value(); 380 } 381 } 382 } 383 384 public: 385 void Clear() override { 386 KeyTypeHandler::Clear(&key_, GetArenaNoVirtual()); 387 ValueTypeHandler::ClearMaybeByDefaultEnum(&value_, GetArenaNoVirtual(), 388 default_enum_value); 389 clear_has_key(); 390 clear_has_value(); 391 } 392 393 static void InitAsDefaultInstance() { 394 Derived* d = const_cast<Derived*>(Derived::internal_default_instance()); 395 KeyTypeHandler::AssignDefaultValue(&d->key_); 396 ValueTypeHandler::AssignDefaultValue(&d->value_); 397 } 398 399 Arena* GetArena() const override { return GetArenaNoVirtual(); } 400 401 // Parsing using MergePartialFromCodedStream, above, is not as 402 // efficient as it could be. This helper class provides a speedier way. 403 template <typename MapField, typename Map> 404 class Parser { 405 public: 406 explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {} 407 ~Parser() { 408 if (entry_ != nullptr && entry_->GetArena() == nullptr) delete entry_; 409 } 410 411 // This does what the typical MergePartialFromCodedStream() is expected to 412 // do, with the additional side-effect that if successful (i.e., if true is 413 // going to be its return value) it inserts the key-value pair into map_. 414 bool MergePartialFromCodedStream(io::CodedInputStream* input) { 415 // Look for the expected thing: a key and then a value. If it fails, 416 // invoke the enclosing class's MergePartialFromCodedStream, or return 417 // false if that would be pointless. 418 if (input->ExpectTag(kKeyTag)) { 419 if (!KeyTypeHandler::Read(input, &key_)) { 420 return false; 421 } 422 // Peek at the next byte to see if it is kValueTag. If not, bail out. 423 const void* data; 424 int size; 425 input->GetDirectBufferPointerInline(&data, &size); 426 // We could use memcmp here, but we don't bother. The tag is one byte. 427 static_assert(kTagSize == 1, "tag size must be 1"); 428 if (size > 0 && *reinterpret_cast<const char*>(data) == kValueTag) { 429 typename Map::size_type map_size = map_->size(); 430 value_ptr_ = &(*map_)[key_]; 431 if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) { 432 // We created a new key-value pair. Fill in the value. 433 typedef 434 typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type T; 435 input->Skip(kTagSize); // Skip kValueTag. 436 if (!ValueTypeHandler::Read(input, 437 reinterpret_cast<T>(value_ptr_))) { 438 map_->erase(key_); // Failure! Undo insertion. 439 return false; 440 } 441 if (input->ExpectAtEnd()) return true; 442 return ReadBeyondKeyValuePair(input); 443 } 444 } 445 } else { 446 key_ = Key(); 447 } 448 449 NewEntry(); 450 *entry_->mutable_key() = key_; 451 const bool result = entry_->MergePartialFromCodedStream(input); 452 if (result) UseKeyAndValueFromEntry(); 453 return result; 454 } 455 456 const char* _InternalParse(const char* ptr, ParseContext* ctx) { 457 if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) { 458 ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_); 459 if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) { 460 return nullptr; 461 } 462 if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) { 463 typename Map::size_type map_size = map_->size(); 464 value_ptr_ = &(*map_)[key_]; 465 if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) { 466 using T = 467 typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type; 468 ptr = ValueTypeHandler::Read(ptr + 1, ctx, 469 reinterpret_cast<T>(value_ptr_)); 470 if (PROTOBUF_PREDICT_FALSE(!ptr || 471 !Derived::ValidateValue(value_ptr_))) { 472 map_->erase(key_); // Failure! Undo insertion. 473 return nullptr; 474 } 475 if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr; 476 if (!ptr) return nullptr; 477 NewEntry(); 478 ValueMover::Move(value_ptr_, entry_->mutable_value()); 479 map_->erase(key_); 480 goto move_key; 481 } 482 } else { 483 if (!ptr) return nullptr; 484 } 485 NewEntry(); 486 move_key: 487 KeyMover::Move(&key_, entry_->mutable_key()); 488 } else { 489 if (!ptr) return nullptr; 490 NewEntry(); 491 } 492 ptr = entry_->_InternalParse(ptr, ctx); 493 if (ptr) UseKeyAndValueFromEntry(); 494 return ptr; 495 } 496 497 template <typename Metadata> 498 const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, 499 bool (*is_valid)(int), uint32 field_num, 500 Metadata* metadata) { 501 auto entry = NewEntry(); 502 ptr = entry->_InternalParse(ptr, ctx); 503 if (!ptr) return nullptr; 504 if (is_valid(entry->value())) { 505 UseKeyAndValueFromEntry(); 506 } else { 507 WriteLengthDelimited(field_num, entry->SerializeAsString(), 508 metadata->mutable_unknown_fields()); 509 } 510 return ptr; 511 } 512 513 MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); } 514 515 const Key& key() const { return key_; } 516 const Value& value() const { return *value_ptr_; } 517 518 const Key& entry_key() const { return entry_->key(); } 519 const Value& entry_value() const { return entry_->value(); } 520 521 private: 522 void UseKeyAndValueFromEntry() { 523 // Update key_ in case we need it later (because key() is called). 524 // This is potentially inefficient, especially if the key is 525 // expensive to copy (e.g., a long string), but this is a cold 526 // path, so it's not a big deal. 527 key_ = entry_->key(); 528 value_ptr_ = &(*map_)[key_]; 529 ValueMover::Move(entry_->mutable_value(), value_ptr_); 530 } 531 532 // After reading a key and value successfully, and inserting that data 533 // into map_, we are not at the end of the input. This is unusual, but 534 // allowed by the spec. 535 bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD { 536 NewEntry(); 537 ValueMover::Move(value_ptr_, entry_->mutable_value()); 538 map_->erase(key_); 539 KeyMover::Move(&key_, entry_->mutable_key()); 540 const bool result = entry_->MergePartialFromCodedStream(input); 541 if (result) UseKeyAndValueFromEntry(); 542 return result; 543 } 544 545 typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage, 546 KeyTypeHandler::kWireType == 547 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, 548 Key> 549 KeyMover; 550 typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage, 551 ValueTypeHandler::kWireType == 552 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, 553 Value> 554 ValueMover; 555 556 MapField* const mf_; 557 Map* const map_; 558 Key key_; 559 Value* value_ptr_; 560 MapEntryImpl* entry_ = nullptr; 561 }; 562 563 protected: 564 void set_has_key() { _has_bits_[0] |= 0x00000001u; } 565 bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } 566 void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } 567 void set_has_value() { _has_bits_[0] |= 0x00000002u; } 568 bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } 569 void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } 570 571 public: 572 inline Arena* GetArenaNoVirtual() const { return arena_; } 573 574 public: // Needed for constructing tables 575 KeyOnMemory key_; 576 ValueOnMemory value_; 577 Arena* arena_; 578 uint32 _has_bits_[1]; 579 580 private: 581 friend class ::PROTOBUF_NAMESPACE_ID::Arena; 582 typedef void InternalArenaConstructable_; 583 typedef void DestructorSkippable_; 584 template <typename C, typename K, typename V, WireFormatLite::FieldType, 585 WireFormatLite::FieldType, int> 586 friend class internal::MapEntry; 587 template <typename C, typename K, typename V, WireFormatLite::FieldType, 588 WireFormatLite::FieldType, int> 589 friend class internal::MapFieldLite; 590 591 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl); 592 }; 593 594 template <typename T, typename Key, typename Value, 595 WireFormatLite::FieldType kKeyFieldType, 596 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 597 class MapEntryLite 598 : public MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType, 599 kValueFieldType, default_enum_value> { 600 public: 601 typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType, 602 kValueFieldType, default_enum_value> 603 SuperType; 604 MapEntryLite() {} 605 explicit MapEntryLite(Arena* arena) : SuperType(arena) {} 606 void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); } 607 608 private: 609 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); 610 }; 611 // The completely unprincipled and unwieldy use of template parameters in 612 // the map code necessitates wrappers to make the code a little bit more 613 // manageable. 614 template <typename Derived> 615 struct DeconstructMapEntry; 616 617 template <typename T, typename K, typename V, WireFormatLite::FieldType key, 618 WireFormatLite::FieldType value, int default_enum> 619 struct DeconstructMapEntry<MapEntryLite<T, K, V, key, value, default_enum> > { 620 typedef K Key; 621 typedef V Value; 622 static const WireFormatLite::FieldType kKeyFieldType = key; 623 static const WireFormatLite::FieldType kValueFieldType = value; 624 static const int default_enum_value = default_enum; 625 }; 626 627 // Helpers for deterministic serialization ============================= 628 629 // This struct can be used with any generic sorting algorithm. If the Key 630 // type is relatively small and easy to copy then copying Keys into an 631 // array of SortItems can be beneficial. Then all the data the sorting 632 // algorithm needs to touch is in that one array. 633 template <typename Key, typename PtrToKeyValuePair> 634 struct SortItem { 635 SortItem() {} 636 explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {} 637 638 Key first; 639 PtrToKeyValuePair second; 640 }; 641 642 template <typename T> 643 struct CompareByFirstField { 644 bool operator()(const T& a, const T& b) const { return a.first < b.first; } 645 }; 646 647 template <typename T> 648 struct CompareByDerefFirst { 649 bool operator()(const T& a, const T& b) const { return a->first < b->first; } 650 }; 651 652 // Helper for table driven serialization 653 654 template <WireFormatLite::FieldType FieldType> 655 struct FromHelper { 656 template <typename T> 657 static const T& From(const T& x) { 658 return x; 659 } 660 }; 661 662 template <> 663 struct FromHelper<WireFormatLite::TYPE_STRING> { 664 static ArenaStringPtr From(const std::string& x) { 665 ArenaStringPtr res; 666 TaggedPtr<std::string> ptr; 667 ptr.Set(const_cast<std::string*>(&x)); 668 res.UnsafeSetTaggedPointer(ptr); 669 return res; 670 } 671 }; 672 template <> 673 struct FromHelper<WireFormatLite::TYPE_BYTES> { 674 static ArenaStringPtr From(const std::string& x) { 675 ArenaStringPtr res; 676 TaggedPtr<std::string> ptr; 677 ptr.Set(const_cast<std::string*>(&x)); 678 res.UnsafeSetTaggedPointer(ptr); 679 return res; 680 } 681 }; 682 template <> 683 struct FromHelper<WireFormatLite::TYPE_MESSAGE> { 684 template <typename T> 685 static T* From(const T& x) { 686 return const_cast<T*>(&x); 687 } 688 }; 689 690 template <typename MapEntryType> 691 struct MapEntryHelper; 692 693 template <typename T, typename Key, typename Value, 694 WireFormatLite::FieldType kKeyFieldType, 695 WireFormatLite::FieldType kValueFieldType, int default_enum_value> 696 struct MapEntryHelper<MapEntryLite<T, Key, Value, kKeyFieldType, 697 kValueFieldType, default_enum_value> > { 698 // Provide utilities to parse/serialize key/value. Provide utilities to 699 // manipulate internal stored type. 700 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; 701 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler; 702 703 // Define internal memory layout. Strings and messages are stored as 704 // pointers, while other types are stored as values. 705 typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory; 706 typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory; 707 708 explicit MapEntryHelper(const MapPair<Key, Value>& map_pair) 709 : _has_bits_(3), 710 _cached_size_(2 + KeyTypeHandler::GetCachedSize(map_pair.first) + 711 ValueTypeHandler::GetCachedSize(map_pair.second)), 712 key_(FromHelper<kKeyFieldType>::From(map_pair.first)), 713 value_(FromHelper<kValueFieldType>::From(map_pair.second)) {} 714 715 // Purposely not folowing the style guide naming. These are the names 716 // the proto compiler would generate given the map entry descriptor. 717 // The proto compiler generates the offsets in this struct as if this was 718 // a regular message. This way the table driven code barely notices it's 719 // dealing with a map field. 720 uint32 _has_bits_; // NOLINT 721 uint32 _cached_size_; // NOLINT 722 KeyOnMemory key_; // NOLINT 723 ValueOnMemory value_; // NOLINT 724 }; 725 726 } // namespace internal 727 } // namespace protobuf 728 } // namespace google 729 730 #include <google/protobuf/port_undef.inc> 731 732 #endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ 733