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
53namespace google {
54namespace protobuf {
55namespace internal {
56template <typename Derived, typename Key, typename Value,
57 WireFormatLite::FieldType kKeyFieldType,
58 WireFormatLite::FieldType kValueFieldType, int default_enum_value>
59class MapEntry;
60template <typename Derived, typename Key, typename Value,
61 WireFormatLite::FieldType kKeyFieldType,
62 WireFormatLite::FieldType kValueFieldType, int default_enum_value>
63class MapFieldLite;
64} // namespace internal
65} // namespace protobuf
66} // namespace google
67
68namespace google {
69namespace protobuf {
70namespace 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.
75template <bool is_enum, bool is_message, bool is_stringlike, typename T>
76struct MoveHelper { // primitives
77 static void Move(T* src, T* dest) { *dest = *src; }
78};
79
80template <bool is_message, bool is_stringlike, typename T>
81struct 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
88template <bool is_stringlike, typename T>
89struct MoveHelper<false, true, is_stringlike, T> { // messages
90 static void Move(T* src, T* dest) { dest->Swap(src); }
91};
92
93template <typename T>
94struct 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).
106template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
107 WireFormatLite::FieldType kValueFieldType>
108struct 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, type: WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target: ptr);
120 ptr = io::CodedOutputStream::WriteVarint32ToArray(value: GetCachedSize(key, value),
121 target: 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 value: 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.
145template <typename Derived, typename Base, typename Key, typename Value,
146 WireFormatLite::FieldType kKeyFieldType,
147 WireFormatLite::FieldType kValueFieldType, int default_enum_value>
148class 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(from: *::google::protobuf::internal::DownCast<const Derived*>(&other));
236 }
237
238 const char* _InternalParse(const char* ptr, ParseContext* ctx) final {
239 while (!ctx->Done(ptr: &ptr)) {
240 uint32 tag;
241 ptr = ReadTag(p: ptr, out: &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, unknown: 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 += has_key() ? kTagSize +
270 static_cast<size_t>(KeyTypeHandler::ByteSize(key()))
271 : 0;
272 size += has_value()
273 ? kTagSize +
274 static_cast<size_t>(ValueTypeHandler::ByteSize(value()))
275 : 0;
276 return size;
277 }
278
279 ::google::protobuf::uint8* _InternalSerialize(::google::protobuf::uint8* ptr,
280 io::EpsCopyOutputStream* stream) const override {
281 ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream);
282 return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream);
283 }
284
285 // Don't override SerializeWithCachedSizesToArray. Use MessageLite's.
286
287 int GetCachedSize() const override {
288 int size = 0;
289 size += has_key() ? static_cast<int>(kTagSize) +
290 KeyTypeHandler::GetCachedSize(key())
291 : 0;
292 size += has_value() ? static_cast<int>(kTagSize) +
293 ValueTypeHandler::GetCachedSize(value())
294 : 0;
295 return size;
296 }
297
298 bool IsInitialized() const override {
299 return ValueTypeHandler::IsInitialized(value_);
300 }
301
302 Base* New() const override {
303 Derived* entry = new Derived;
304 return entry;
305 }
306
307 Base* New(Arena* arena) const override {
308 Derived* entry = Arena::CreateMessage<Derived>(arena);
309 return entry;
310 }
311
312 protected:
313 // We can't declare this function directly here as it would hide the other
314 // overload (const Message&).
315 void MergeFromInternal(const MapEntryImpl& from) {
316 if (from._has_bits_[0]) {
317 if (from.has_key()) {
318 KeyTypeHandler::EnsureMutable(&key_, Base::GetArena());
319 KeyTypeHandler::Merge(from.key(), &key_, Base::GetArena());
320 set_has_key();
321 }
322 if (from.has_value()) {
323 ValueTypeHandler::EnsureMutable(&value_, Base::GetArena());
324 ValueTypeHandler::Merge(from.value(), &value_, Base::GetArena());
325 set_has_value();
326 }
327 }
328 }
329
330 public:
331 void Clear() override {
332 KeyTypeHandler::Clear(&key_, Base::GetArena());
333 ValueTypeHandler::ClearMaybeByDefaultEnum(&value_, Base::GetArena(),
334 default_enum_value);
335 clear_has_key();
336 clear_has_value();
337 }
338
339 static void InitAsDefaultInstance() {
340 Derived* d = const_cast<Derived*>(Derived::internal_default_instance());
341 KeyTypeHandler::AssignDefaultValue(&d->key_);
342 ValueTypeHandler::AssignDefaultValue(&d->value_);
343 }
344
345 // Parsing using MergePartialFromCodedStream, above, is not as
346 // efficient as it could be. This helper class provides a speedier way.
347 template <typename MapField, typename Map>
348 class Parser {
349 public:
350 explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {}
351 ~Parser() {
352 if (entry_ != nullptr && entry_->GetArena() == nullptr) delete entry_;
353 }
354
355 // This does what the typical MergePartialFromCodedStream() is expected to
356 // do, with the additional side-effect that if successful (i.e., if true is
357 // going to be its return value) it inserts the key-value pair into map_.
358 bool MergePartialFromCodedStream(io::CodedInputStream* input) {
359 // Look for the expected thing: a key and then a value. If it fails,
360 // invoke the enclosing class's MergePartialFromCodedStream, or return
361 // false if that would be pointless.
362 if (input->ExpectTag(expected: kKeyTag)) {
363 if (!KeyTypeHandler::Read(input, &key_)) {
364 return false;
365 }
366 // Peek at the next byte to see if it is kValueTag. If not, bail out.
367 const void* data;
368 int size;
369 input->GetDirectBufferPointerInline(data: &data, size: &size);
370 // We could use memcmp here, but we don't bother. The tag is one byte.
371 static_assert(kTagSize == 1, "tag size must be 1");
372 if (size > 0 && *reinterpret_cast<const char*>(data) == kValueTag) {
373 typename Map::size_type map_size = map_->size();
374 value_ptr_ = &(*map_)[key_];
375 if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
376 // We created a new key-value pair. Fill in the value.
377 typedef
378 typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type T;
379 input->Skip(count: kTagSize); // Skip kValueTag.
380 if (!ValueTypeHandler::Read(input,
381 reinterpret_cast<T>(value_ptr_))) {
382 map_->erase(key_); // Failure! Undo insertion.
383 return false;
384 }
385 if (input->ExpectAtEnd()) return true;
386 return ReadBeyondKeyValuePair(input);
387 }
388 }
389 } else {
390 key_ = Key();
391 }
392
393 NewEntry();
394 *entry_->mutable_key() = key_;
395 const bool result = entry_->MergePartialFromCodedStream(input);
396 if (result) UseKeyAndValueFromEntry();
397 return result;
398 }
399
400 const char* _InternalParse(const char* ptr, ParseContext* ctx) {
401 if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) {
402 ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_);
403 if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) {
404 return nullptr;
405 }
406 if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) {
407 typename Map::size_type map_size = map_->size();
408 value_ptr_ = &(*map_)[key_];
409 if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) {
410 using T =
411 typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type;
412 ptr = ValueTypeHandler::Read(ptr + 1, ctx,
413 reinterpret_cast<T>(value_ptr_));
414 if (PROTOBUF_PREDICT_FALSE(!ptr ||
415 !Derived::ValidateValue(value_ptr_))) {
416 map_->erase(key_); // Failure! Undo insertion.
417 return nullptr;
418 }
419 if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr;
420 if (!ptr) return nullptr;
421 NewEntry();
422 ValueMover::Move(value_ptr_, entry_->mutable_value());
423 map_->erase(key_);
424 goto move_key;
425 }
426 } else {
427 if (!ptr) return nullptr;
428 }
429 NewEntry();
430 move_key:
431 KeyMover::Move(&key_, entry_->mutable_key());
432 } else {
433 if (!ptr) return nullptr;
434 NewEntry();
435 }
436 ptr = entry_->_InternalParse(ptr, ctx);
437 if (ptr) UseKeyAndValueFromEntry();
438 return ptr;
439 }
440
441 template <typename UnknownType>
442 const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx,
443 bool (*is_valid)(int), uint32 field_num,
444 InternalMetadata* metadata) {
445 auto entry = NewEntry();
446 ptr = entry->_InternalParse(ptr, ctx);
447 if (!ptr) return nullptr;
448 if (is_valid(entry->value())) {
449 UseKeyAndValueFromEntry();
450 } else {
451 WriteLengthDelimited(field_num, entry->SerializeAsString(),
452 metadata->mutable_unknown_fields<UnknownType>());
453 }
454 return ptr;
455 }
456
457 MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); }
458
459 const Key& key() const { return key_; }
460 const Value& value() const { return *value_ptr_; }
461
462 const Key& entry_key() const { return entry_->key(); }
463 const Value& entry_value() const { return entry_->value(); }
464
465 private:
466 void UseKeyAndValueFromEntry() {
467 // Update key_ in case we need it later (because key() is called).
468 // This is potentially inefficient, especially if the key is
469 // expensive to copy (e.g., a long string), but this is a cold
470 // path, so it's not a big deal.
471 key_ = entry_->key();
472 value_ptr_ = &(*map_)[key_];
473 ValueMover::Move(entry_->mutable_value(), value_ptr_);
474 }
475
476 // After reading a key and value successfully, and inserting that data
477 // into map_, we are not at the end of the input. This is unusual, but
478 // allowed by the spec.
479 bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD {
480 NewEntry();
481 ValueMover::Move(value_ptr_, entry_->mutable_value());
482 map_->erase(key_);
483 KeyMover::Move(&key_, entry_->mutable_key());
484 const bool result = entry_->MergePartialFromCodedStream(input);
485 if (result) UseKeyAndValueFromEntry();
486 return result;
487 }
488
489 typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage,
490 KeyTypeHandler::kWireType ==
491 WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
492 Key>
493 KeyMover;
494 typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage,
495 ValueTypeHandler::kWireType ==
496 WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
497 Value>
498 ValueMover;
499
500 MapField* const mf_;
501 Map* const map_;
502 Key key_;
503 Value* value_ptr_;
504 MapEntryImpl* entry_ = nullptr;
505 };
506
507 protected:
508 void set_has_key() { _has_bits_[0] |= 0x00000001u; }
509 bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
510 void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
511 void set_has_value() { _has_bits_[0] |= 0x00000002u; }
512 bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
513 void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
514
515 public:
516 inline Arena* GetArena() const { return Base::GetArena(); }
517
518 public: // Needed for constructing tables
519 KeyOnMemory key_;
520 ValueOnMemory value_;
521 uint32 _has_bits_[1];
522
523 private:
524 friend class ::PROTOBUF_NAMESPACE_ID::Arena;
525 typedef void InternalArenaConstructable_;
526 typedef void DestructorSkippable_;
527 template <typename C, typename K, typename V, WireFormatLite::FieldType,
528 WireFormatLite::FieldType, int>
529 friend class internal::MapEntry;
530 template <typename C, typename K, typename V, WireFormatLite::FieldType,
531 WireFormatLite::FieldType, int>
532 friend class internal::MapFieldLite;
533
534 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
535};
536
537template <typename T, typename Key, typename Value,
538 WireFormatLite::FieldType kKeyFieldType,
539 WireFormatLite::FieldType kValueFieldType, int default_enum_value>
540class MapEntryLite
541 : public MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
542 kValueFieldType, default_enum_value> {
543 public:
544 typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType,
545 kValueFieldType, default_enum_value>
546 SuperType;
547 MapEntryLite() {}
548 explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
549 ~MapEntryLite() { MessageLite::_internal_metadata_.Delete<std::string>(); }
550 void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
551
552 private:
553 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
554};
555// The completely unprincipled and unwieldy use of template parameters in
556// the map code necessitates wrappers to make the code a little bit more
557// manageable.
558template <typename Derived>
559struct DeconstructMapEntry;
560
561template <typename T, typename K, typename V, WireFormatLite::FieldType key,
562 WireFormatLite::FieldType value, int default_enum>
563struct DeconstructMapEntry<MapEntryLite<T, K, V, key, value, default_enum> > {
564 typedef K Key;
565 typedef V Value;
566 static const WireFormatLite::FieldType kKeyFieldType = key;
567 static const WireFormatLite::FieldType kValueFieldType = value;
568 static const int default_enum_value = default_enum;
569};
570
571// Helpers for deterministic serialization =============================
572
573// This struct can be used with any generic sorting algorithm. If the Key
574// type is relatively small and easy to copy then copying Keys into an
575// array of SortItems can be beneficial. Then all the data the sorting
576// algorithm needs to touch is in that one array.
577template <typename Key, typename PtrToKeyValuePair>
578struct SortItem {
579 SortItem() {}
580 explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {}
581
582 Key first;
583 PtrToKeyValuePair second;
584};
585
586template <typename T>
587struct CompareByFirstField {
588 bool operator()(const T& a, const T& b) const { return a.first < b.first; }
589};
590
591template <typename T>
592struct CompareByDerefFirst {
593 bool operator()(const T& a, const T& b) const { return a->first < b->first; }
594};
595
596// Helper for table driven serialization
597
598template <WireFormatLite::FieldType FieldType>
599struct FromHelper {
600 template <typename T>
601 static const T& From(const T& x) {
602 return x;
603 }
604};
605
606template <>
607struct FromHelper<WireFormatLite::TYPE_STRING> {
608 static ArenaStringPtr From(const std::string& x) {
609 ArenaStringPtr res;
610 TaggedPtr<std::string> ptr;
611 ptr.Set(const_cast<std::string*>(&x));
612 res.UnsafeSetTaggedPointer(value: ptr);
613 return res;
614 }
615};
616template <>
617struct FromHelper<WireFormatLite::TYPE_BYTES> {
618 static ArenaStringPtr From(const std::string& x) {
619 ArenaStringPtr res;
620 TaggedPtr<std::string> ptr;
621 ptr.Set(const_cast<std::string*>(&x));
622 res.UnsafeSetTaggedPointer(value: ptr);
623 return res;
624 }
625};
626template <>
627struct FromHelper<WireFormatLite::TYPE_MESSAGE> {
628 template <typename T>
629 static T* From(const T& x) {
630 return const_cast<T*>(&x);
631 }
632};
633
634template <typename MapEntryType>
635struct MapEntryHelper;
636
637template <typename T, typename Key, typename Value,
638 WireFormatLite::FieldType kKeyFieldType,
639 WireFormatLite::FieldType kValueFieldType, int default_enum_value>
640struct MapEntryHelper<MapEntryLite<T, Key, Value, kKeyFieldType,
641 kValueFieldType, default_enum_value> > {
642 // Provide utilities to parse/serialize key/value. Provide utilities to
643 // manipulate internal stored type.
644 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
645 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
646
647 // Define internal memory layout. Strings and messages are stored as
648 // pointers, while other types are stored as values.
649 typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
650 typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
651
652 explicit MapEntryHelper(const MapPair<Key, Value>& map_pair)
653 : _has_bits_(3),
654 _cached_size_(2 + KeyTypeHandler::GetCachedSize(map_pair.first) +
655 ValueTypeHandler::GetCachedSize(map_pair.second)),
656 key_(FromHelper<kKeyFieldType>::From(map_pair.first)),
657 value_(FromHelper<kValueFieldType>::From(map_pair.second)) {}
658
659 // Purposely not following the style guide naming. These are the names
660 // the proto compiler would generate given the map entry descriptor.
661 // The proto compiler generates the offsets in this struct as if this was
662 // a regular message. This way the table driven code barely notices it's
663 // dealing with a map field.
664 uint32 _has_bits_; // NOLINT
665 uint32 _cached_size_; // NOLINT
666 KeyOnMemory key_; // NOLINT
667 ValueOnMemory value_; // NOLINT
668};
669
670} // namespace internal
671} // namespace protobuf
672} // namespace google
673
674#include <google/protobuf/port_undef.inc>
675
676#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
677

source code of include/google/protobuf/map_entry_lite.h