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