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