• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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