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