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