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 <google/protobuf/map_type_handler.h>
36 #include <google/protobuf/wire_format_lite_inl.h>
37 
38 namespace google {
39 namespace protobuf {
40 class Arena;
41 namespace internal {
42 template <typename Key, typename Value,
43           WireFormatLite::FieldType kKeyFieldType,
44           WireFormatLite::FieldType kValueFieldType,
45           int default_enum_value>
46 class MapEntry;
47 template <typename Key, typename Value,
48           WireFormatLite::FieldType kKeyFieldType,
49           WireFormatLite::FieldType kValueFieldType,
50           int default_enum_value>
51 class MapFieldLite;
52 }  // namespace internal
53 }  // namespace protobuf
54 
55 namespace protobuf {
56 namespace internal {
57 
58 // MoveHelper::Move is used to set *dest.  It copies *src, or moves it (in
59 // the C++11 sense), or swaps it. *src is left in a sane state for
60 // subsequent destruction, but shouldn't be used for anything.
61 template <bool is_enum, bool is_message, bool is_stringlike, typename T>
62 struct MoveHelper {  // primitives
MoveMoveHelper63   static void Move(T* src, T* dest) { *dest = *src; }
64 };
65 
66 template <bool is_message, bool is_stringlike, typename T>
67 struct MoveHelper<true, is_message, is_stringlike, T> {  // enums
68   static void Move(T* src, T* dest) { *dest = *src; }
69   // T is an enum here, so allow conversions to and from int.
70   static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); }
71   static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); }
72 };
73 
74 template <bool is_stringlike, typename T>
75 struct MoveHelper<false, true, is_stringlike, T> {  // messages
76   static void Move(T* src, T* dest) { dest->Swap(src); }
77 };
78 
79 template <typename T>
80 struct MoveHelper<false, false, true, T> {  // strings and similar
81   static void Move(T* src, T* dest) {
82 #if __cplusplus >= 201103L
83     *dest = std::move(*src);
84 #else
85     dest->swap(*src);
86 #endif
87   }
88 };
89 
90 // MapEntryLite is used to implement parsing and serialization of map for lite
91 // runtime.
92 template <typename Key, typename Value,
93           WireFormatLite::FieldType kKeyFieldType,
94           WireFormatLite::FieldType kValueFieldType,
95           int default_enum_value>
96 class MapEntryLite : public MessageLite {
97   // Provide utilities to parse/serialize key/value.  Provide utilities to
98   // manipulate internal stored type.
99   typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
100   typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
101 
102   // Define internal memory layout. Strings and messages are stored as
103   // pointers, while other types are stored as values.
104   typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
105   typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
106 
107   // Enum type cannot be used for MapTypeHandler::Read. Define a type
108   // which will replace Enum with int.
109   typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
110   typedef typename ValueTypeHandler::MapEntryAccessorType
111       ValueMapEntryAccessorType;
112 
113   // Constants for field number.
114   static const int kKeyFieldNumber = 1;
115   static const int kValueFieldNumber = 2;
116 
117   // Constants for field tag.
118   static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
119       kKeyFieldNumber, KeyTypeHandler::kWireType);
120   static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
121       kValueFieldNumber, ValueTypeHandler::kWireType);
122   static const int kTagSize = 1;
123 
124  public:
125   ~MapEntryLite() {
126     if (this != default_instance_) {
127       if (GetArenaNoVirtual() != NULL) return;
128       KeyTypeHandler::DeleteNoArena(key_);
129       ValueTypeHandler::DeleteNoArena(value_);
130     }
131   }
132 
133   // accessors ======================================================
134 
135   virtual inline const KeyMapEntryAccessorType& key() const {
136     return KeyTypeHandler::GetExternalReference(key_);
137   }
138   virtual inline const ValueMapEntryAccessorType& value() const {
139     GOOGLE_CHECK(default_instance_ != NULL);
140     return ValueTypeHandler::DefaultIfNotInitialized(value_,
141                                                     default_instance_->value_);
142   }
143   inline KeyMapEntryAccessorType* mutable_key() {
144     set_has_key();
145     return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
146   }
147   inline ValueMapEntryAccessorType* mutable_value() {
148     set_has_value();
149     return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
150   }
151 
152   // implements MessageLite =========================================
153 
154   // MapEntryLite is for implementation only and this function isn't called
155   // anywhere. Just provide a fake implementation here for MessageLite.
156   string GetTypeName() const { return ""; }
157 
158   void CheckTypeAndMergeFrom(const MessageLite& other) {
159     MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
160   }
161 
162   bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
163     uint32 tag;
164 
165     for (;;) {
166       // 1) corrupted data: return false;
167       // 2) unknown field: skip without putting into unknown field set;
168       // 3) unknown enum value: keep it in parsing. In proto2, caller should
169       // check the value and put this entry into containing message's unknown
170       // field set if the value is an unknown enum. In proto3, caller doesn't
171       // need to care whether the value is unknown enum;
172       // 4) missing key/value: missed key/value will have default value. caller
173       // should take this entry as if key/value is set to default value.
174       tag = input->ReadTag();
175       switch (tag) {
176         case kKeyTag:
177           if (!KeyTypeHandler::Read(input, mutable_key())) {
178             return false;
179           }
180           set_has_key();
181           if (!input->ExpectTag(kValueTag)) break;
182           GOOGLE_FALLTHROUGH_INTENDED;
183 
184         case kValueTag:
185           if (!ValueTypeHandler::Read(input, mutable_value())) {
186             return false;
187           }
188           set_has_value();
189           if (input->ExpectAtEnd()) return true;
190           break;
191 
192         default:
193           if (tag == 0 ||
194               WireFormatLite::GetTagWireType(tag) ==
195               WireFormatLite::WIRETYPE_END_GROUP) {
196             return true;
197           }
198           if (!WireFormatLite::SkipField(input, tag)) return false;
199           break;
200       }
201     }
202   }
203 
204   int ByteSize() const {
205     int size = 0;
206     size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
207     size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
208     return size;
209   }
210 
211   void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
212     KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
213     ValueTypeHandler::Write(kValueFieldNumber, value(), output);
214   }
215 
216   ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(bool deterministic,
217                                                    ::google::protobuf::uint8* output) const {
218     output = KeyTypeHandler::InternalWriteToArray(kKeyFieldNumber, key(),
219                                                   deterministic, output);
220     output = ValueTypeHandler::InternalWriteToArray(kValueFieldNumber, value(),
221                                                     deterministic, output);
222     return output;
223   }
224   ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
225     return InternalSerializeWithCachedSizesToArray(false, output);
226   }
227 
228   int GetCachedSize() const {
229     int size = 0;
230     size += has_key()
231         ? kTagSize + KeyTypeHandler::GetCachedSize(key())
232         : 0;
233     size += has_value()
234         ? kTagSize + ValueTypeHandler::GetCachedSize(
235             value())
236         : 0;
237     return size;
238   }
239 
240   bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); }
241 
242   MessageLite* New() const {
243     MapEntryLite* entry = new MapEntryLite;
244     entry->default_instance_ = default_instance_;
245     return entry;
246   }
247 
248   MessageLite* New(Arena* arena) const {
249     MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
250     entry->default_instance_ = default_instance_;
251     return entry;
252   }
253 
254   int SpaceUsed() const {
255     int size = sizeof(MapEntryLite);
256     size += KeyTypeHandler::SpaceUsedInMapEntry(key_);
257     size += ValueTypeHandler::SpaceUsedInMapEntry(value_);
258     return size;
259   }
260 
261   void MergeFrom(const MapEntryLite& from) {
262     if (from._has_bits_[0]) {
263       if (from.has_key()) {
264         KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
265         KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual());
266         set_has_key();
267       }
268       if (from.has_value()) {
269         ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
270         ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual());
271         set_has_value();
272       }
273     }
274   }
275 
276   void Clear() {
277     KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
278     ValueTypeHandler::ClearMaybeByDefaultEnum(
279         &value_, GetArenaNoVirtual(), default_enum_value);
280     clear_has_key();
281     clear_has_value();
282   }
283 
284   void InitAsDefaultInstance() {
285     KeyTypeHandler::AssignDefaultValue(&key_);
286     ValueTypeHandler::AssignDefaultValue(&value_);
287   }
288 
289   Arena* GetArena() const {
290     return GetArenaNoVirtual();
291   }
292 
293   // Create a MapEntryLite for given key and value from google::protobuf::Map in
294   // serialization. This function is only called when value is enum. Enum is
295   // treated differently because its type in MapEntry is int and its type in
296   // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
297   static MapEntryLite* EnumWrap(const Key& key, const Value value,
298                                 Arena* arena) {
299     return Arena::CreateMessage<MapEnumEntryWrapper<
300         Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
301         arena, key, value);
302   }
303 
304   // Like above, but for all the other types. This avoids value copy to create
305   // MapEntryLite from google::protobuf::Map in serialization.
306   static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
307     return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType,
308                                                 kValueFieldType,
309                                                 default_enum_value> >(
310         arena, key, value);
311   }
312 
313   // Parsing using MergePartialFromCodedStream, above, is not as
314   // efficient as it could be.  This helper class provides a speedier way.
315   template <typename MapField, typename Map>
316   class Parser {
317    public:
318     explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
319 
320     // This does what the typical MergePartialFromCodedStream() is expected to
321     // do, with the additional side-effect that if successful (i.e., if true is
322     // going to be its return value) it inserts the key-value pair into map_.
323     bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
324       // Look for the expected thing: a key and then a value.  If it fails,
325       // invoke the enclosing class's MergePartialFromCodedStream, or return
326       // false if that would be pointless.
327       if (input->ExpectTag(kKeyTag)) {
328         if (!KeyTypeHandler::Read(input, &key_)) {
329           return false;
330         }
331         // Peek at the next byte to see if it is kValueTag.  If not, bail out.
332         const void* data;
333         int size;
334         input->GetDirectBufferPointerInline(&data, &size);
335         // We could use memcmp here, but we don't bother. The tag is one byte.
336         assert(kTagSize == 1);
337         if (size > 0 && *reinterpret_cast<const char*>(data) == kValueTag) {
338           typename Map::size_type size = map_->size();
339           value_ptr_ = &(*map_)[key_];
340           if (GOOGLE_PREDICT_TRUE(size != map_->size())) {
341             // We created a new key-value pair.  Fill in the value.
342             typedef
343                 typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type T;
344             input->Skip(kTagSize);  // Skip kValueTag.
345             if (!ValueTypeHandler::Read(input,
346                                         reinterpret_cast<T>(value_ptr_))) {
347               map_->erase(key_);  // Failure! Undo insertion.
348               return false;
349             }
350             if (input->ExpectAtEnd()) return true;
351             return ReadBeyondKeyValuePair(input);
352           }
353         }
354       } else {
355         key_ = Key();
356       }
357 
358       entry_.reset(mf_->NewEntry());
359       *entry_->mutable_key() = key_;
360       if (!entry_->MergePartialFromCodedStream(input)) return false;
361       return UseKeyAndValueFromEntry();
362     }
363 
364     const Key& key() const { return key_; }
365     const Value& value() const { return *value_ptr_; }
366 
367    private:
368     bool UseKeyAndValueFromEntry() GOOGLE_ATTRIBUTE_COLD {
369       // Update key_ in case we need it later (because key() is called).
370       // This is potentially inefficient, especially if the key is
371       // expensive to copy (e.g., a long string), but this is a cold
372       // path, so it's not a big deal.
373       key_ = entry_->key();
374       value_ptr_ = &(*map_)[key_];
375       MoveHelper<ValueTypeHandler::kIsEnum,
376                  ValueTypeHandler::kIsMessage,
377                  ValueTypeHandler::kWireType ==
378                  WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
379                  Value>::Move(entry_->mutable_value(), value_ptr_);
380       if (entry_->GetArena() != NULL) entry_.release();
381       return true;
382     }
383 
384     // After reading a key and value successfully, and inserting that data
385     // into map_, we are not at the end of the input.  This is unusual, but
386     // allowed by the spec.
387     bool ReadBeyondKeyValuePair(::google::protobuf::io::CodedInputStream* input)
388         GOOGLE_ATTRIBUTE_COLD {
389       typedef MoveHelper<KeyTypeHandler::kIsEnum,
390                          KeyTypeHandler::kIsMessage,
391                          KeyTypeHandler::kWireType ==
392                          WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
393                          Key> KeyMover;
394       typedef MoveHelper<ValueTypeHandler::kIsEnum,
395                          ValueTypeHandler::kIsMessage,
396                          ValueTypeHandler::kWireType ==
397                          WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
398                          Value> ValueMover;
399       entry_.reset(mf_->NewEntry());
400       ValueMover::Move(value_ptr_, entry_->mutable_value());
401       map_->erase(key_);
402       KeyMover::Move(&key_, entry_->mutable_key());
403       if (!entry_->MergePartialFromCodedStream(input)) return false;
404       return UseKeyAndValueFromEntry();
405     }
406 
407     MapField* const mf_;
408     Map* const map_;
409     Key key_;
410     Value* value_ptr_;
411     // On the fast path entry_ is not used.
412     google::protobuf::scoped_ptr<MapEntryLite> entry_;
413   };
414 
415  protected:
416   void set_has_key() { _has_bits_[0] |= 0x00000001u; }
417   bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
418   void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
419   void set_has_value() { _has_bits_[0] |= 0x00000002u; }
420   bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
421   void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
422 
423  private:
424   // Serializing a generated message containing map field involves serializing
425   // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
426   // after serialization should be the same as that of a MapEntry message
427   // containing the same key and value inside it.  However, google::protobuf::Map doesn't
428   // store key and value as MapEntry message, which disables us to use existing
429   // code to serialize message. In order to use existing code to serialize
430   // message, we need to construct a MapEntry from key-value pair. But it
431   // involves copy of key and value to construct a MapEntry. In order to avoid
432   // this copy in constructing a MapEntry, we need the following class which
433   // only takes references of given key and value.
434   template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
435             WireFormatLite::FieldType v_wire_type, int default_enum>
436   class MapEntryWrapper
437       : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
438     typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
439     typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
440     typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
441 
442    public:
443     MapEntryWrapper(Arena* arena, const K& key, const V& value)
444         : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
445           key_(key),
446           value_(value) {
447       Base::set_has_key();
448       Base::set_has_value();
449     }
450     inline const KeyMapEntryAccessorType& key() const { return key_; }
451     inline const ValueMapEntryAccessorType& value() const { return value_; }
452 
453    private:
454     const Key& key_;
455     const Value& value_;
456 
457     friend class ::google::protobuf::Arena;
458     typedef void InternalArenaConstructable_;
459     typedef void DestructorSkippable_;
460   };
461 
462   // Like above, but for enum value only, which stores value instead of
463   // reference of value field inside. This is needed because the type of value
464   // field in constructor is an enum, while we need to store it as an int. If we
465   // initialize a reference to int with a reference to enum, compiler will
466   // generate a temporary int from enum and initialize the reference to int with
467   // the temporary.
468   template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
469             WireFormatLite::FieldType v_wire_type, int default_enum>
470   class MapEnumEntryWrapper
471       : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
472     typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
473     typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
474     typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
475 
476    public:
477     MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
478         : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
479           key_(key),
480           value_(value) {
481       Base::set_has_key();
482       Base::set_has_value();
483     }
484     inline const KeyMapEntryAccessorType& key() const { return key_; }
485     inline const ValueMapEntryAccessorType& value() const { return value_; }
486 
487    private:
488     const KeyMapEntryAccessorType& key_;
489     const ValueMapEntryAccessorType value_;
490 
491     friend class google::protobuf::Arena;
492     typedef void DestructorSkippable_;
493   };
494 
495   MapEntryLite() : default_instance_(NULL), arena_(NULL) {
496     KeyTypeHandler::Initialize(&key_, NULL);
497     ValueTypeHandler::InitializeMaybeByDefaultEnum(
498         &value_, default_enum_value, NULL);
499     _has_bits_[0] = 0;
500   }
501 
502   explicit MapEntryLite(Arena* arena)
503       : default_instance_(NULL), arena_(arena) {
504     KeyTypeHandler::Initialize(&key_, arena);
505     ValueTypeHandler::InitializeMaybeByDefaultEnum(
506         &value_, default_enum_value, arena);
507     _has_bits_[0] = 0;
508   }
509 
510   inline Arena* GetArenaNoVirtual() const {
511     return arena_;
512   }
513 
514   void set_default_instance(MapEntryLite* default_instance) {
515     default_instance_ = default_instance;
516   }
517 
518   MapEntryLite* default_instance_;
519 
520   KeyOnMemory key_;
521   ValueOnMemory value_;
522   Arena* arena_;
523   uint32 _has_bits_[1];
524 
525   friend class ::google::protobuf::Arena;
526   typedef void InternalArenaConstructable_;
527   typedef void DestructorSkippable_;
528   template <typename K, typename V, WireFormatLite::FieldType,
529             WireFormatLite::FieldType, int>
530   friend class internal::MapEntry;
531   template <typename K, typename V, WireFormatLite::FieldType,
532             WireFormatLite::FieldType, int>
533   friend class internal::MapFieldLite;
534 
535   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
536 };
537 
538 // Helpers for deterministic serialization =============================
539 
540 // This struct can be used with any generic sorting algorithm.  If the Key
541 // type is relatively small and easy to copy then copying Keys into an
542 // array of SortItems can be beneficial.  Then all the data the sorting
543 // algorithm needs to touch is in that one array.
544 template <typename Key, typename PtrToKeyValuePair> struct SortItem {
545   SortItem() {}
546   explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {}
547 
548   Key first;
549   PtrToKeyValuePair second;
550 };
551 
552 template <typename T> struct CompareByFirstField {
553   bool operator()(const T& a, const T& b) const {
554     return a.first < b.first;
555   }
556 };
557 
558 template <typename T> struct CompareByDerefFirst {
559   bool operator()(const T& a, const T& b) const {
560     return a->first < b->first;
561   }
562 };
563 
564 }  // namespace internal
565 }  // namespace protobuf
566 
567 }  // namespace google
568 #endif  // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
569