blob: dfc6242004d948a808605ab1968d6f61aae38b6b [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// 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_H__
32#define GOOGLE_PROTOBUF_MAP_H__
33
34#include <iterator>
35#include <google/protobuf/stubs/hash.h>
36#include <limits> // To support Visual Studio 2008
37
38#include <google/protobuf/stubs/common.h>
39#include <google/protobuf/arena.h>
40#include <google/protobuf/generated_enum_util.h>
41#include <google/protobuf/map_type_handler.h>
42#include <google/protobuf/message.h>
43#include <google/protobuf/descriptor.h>
44
45namespace google {
46namespace protobuf {
47
48template <typename Key, typename T>
49class Map;
50
51template <typename Enum> struct is_proto_enum;
52
53class MapIterator;
54
55namespace internal {
56template <typename Key, typename T,
57 WireFormatLite::FieldType key_wire_type,
58 WireFormatLite::FieldType value_wire_type,
59 int default_enum_value>
60class MapFieldLite;
61
62template <typename Key, typename T,
63 WireFormatLite::FieldType key_wire_type,
64 WireFormatLite::FieldType value_wire_type,
65 int default_enum_value>
66class MapField;
67
68template <typename Key, typename T>
69class TypeDefinedMapFieldBase;
70
71class DynamicMapField;
72
73class GeneratedMessageReflection;
74} // namespace internal
75
76#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
77 if (type() != EXPECTEDTYPE) { \
78 GOOGLE_LOG(FATAL) \
79 << "Protocol Buffer map usage error:\n" \
80 << METHOD << " type does not match\n" \
81 << " Expected : " \
82 << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
83 << " Actual : " \
84 << FieldDescriptor::CppTypeName(type()); \
85 }
86
87// MapKey is an union type for representing any possible
88// map key.
89class LIBPROTOBUF_EXPORT MapKey {
90 public:
91 MapKey() : type_(0) {
92 }
93 MapKey(const MapKey& other) : type_(0) {
94 CopyFrom(other);
95 }
96
97 ~MapKey() {
98 if (type_ == FieldDescriptor::CPPTYPE_STRING) {
99 delete val_.string_value_;
100 }
101 }
102
103 FieldDescriptor::CppType type() const {
104 if (type_ == 0) {
105 GOOGLE_LOG(FATAL)
106 << "Protocol Buffer map usage error:\n"
107 << "MapKey::type MapKey is not initialized. "
108 << "Call set methods to initialize MapKey.";
109 }
110 return (FieldDescriptor::CppType)type_;
111 }
112
113 void SetInt64Value(int64 value) {
114 SetType(FieldDescriptor::CPPTYPE_INT64);
115 val_.int64_value_ = value;
116 }
117 void SetUInt64Value(uint64 value) {
118 SetType(FieldDescriptor::CPPTYPE_UINT64);
119 val_.uint64_value_ = value;
120 }
121 void SetInt32Value(int32 value) {
122 SetType(FieldDescriptor::CPPTYPE_INT32);
123 val_.int32_value_ = value;
124 }
125 void SetUInt32Value(uint32 value) {
126 SetType(FieldDescriptor::CPPTYPE_UINT32);
127 val_.uint32_value_ = value;
128 }
129 void SetBoolValue(bool value) {
130 SetType(FieldDescriptor::CPPTYPE_BOOL);
131 val_.bool_value_ = value;
132 }
133 void SetStringValue(const string& val) {
134 SetType(FieldDescriptor::CPPTYPE_STRING);
135 *val_.string_value_ = val;
136 }
137
138 int64 GetInt64Value() const {
139 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
140 "MapKey::GetInt64Value");
141 return val_.int64_value_;
142 }
143 uint64 GetUInt64Value() const {
144 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
145 "MapKey::GetUInt64Value");
146 return val_.uint64_value_;
147 }
148 int32 GetInt32Value() const {
149 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
150 "MapKey::GetInt32Value");
151 return val_.int32_value_;
152 }
153 uint32 GetUInt32Value() const {
154 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
155 "MapKey::GetUInt32Value");
156 return val_.uint32_value_;
157 }
158 bool GetBoolValue() const {
159 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
160 "MapKey::GetBoolValue");
161 return val_.bool_value_;
162 }
163 const string& GetStringValue() const {
164 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
165 "MapKey::GetStringValue");
166 return *val_.string_value_;
167 }
168
169 bool operator==(const MapKey& other) const {
170 if (type_ != other.type_) {
171 return false;
172 }
173 switch (type()) {
174 case FieldDescriptor::CPPTYPE_STRING:
175 return *val_.string_value_ == *other.val_.string_value_;
176 case FieldDescriptor::CPPTYPE_INT64:
177 return val_.int64_value_ == other.val_.int64_value_;
178 case FieldDescriptor::CPPTYPE_INT32:
179 return val_.int32_value_ == other.val_.int32_value_;
180 case FieldDescriptor::CPPTYPE_UINT64:
181 return val_.uint64_value_ == other.val_.uint64_value_;
182 case FieldDescriptor::CPPTYPE_UINT32:
183 return val_.uint32_value_ == other.val_.uint32_value_;
184 case FieldDescriptor::CPPTYPE_BOOL:
185 return val_.bool_value_ == other.val_.bool_value_;
186 case FieldDescriptor::CPPTYPE_DOUBLE:
187 case FieldDescriptor::CPPTYPE_FLOAT:
188 case FieldDescriptor::CPPTYPE_ENUM:
189 case FieldDescriptor::CPPTYPE_MESSAGE:
190 GOOGLE_LOG(FATAL) << "Can't get here.";
191 }
192 GOOGLE_LOG(FATAL) << "Can't get here.";
193 return false;
194 }
195
196 void CopyFrom(const MapKey& other) {
197 SetType(other.type());
198 switch (type_) {
199 case FieldDescriptor::CPPTYPE_STRING:
200 *val_.string_value_ = *other.val_.string_value_;
201 break;
202 case FieldDescriptor::CPPTYPE_INT64:
203 val_.int64_value_ = other.val_.int64_value_;
204 break;
205 case FieldDescriptor::CPPTYPE_INT32:
206 val_.int32_value_ = other.val_.int32_value_;
207 break;
208 case FieldDescriptor::CPPTYPE_UINT64:
209 val_.uint64_value_ = other.val_.uint64_value_;
210 break;
211 case FieldDescriptor::CPPTYPE_UINT32:
212 val_.uint32_value_ = other.val_.uint32_value_;
213 break;
214 case FieldDescriptor::CPPTYPE_BOOL:
215 val_.bool_value_ = other.val_.bool_value_;
216 break;
217 case FieldDescriptor::CPPTYPE_DOUBLE:
218 case FieldDescriptor::CPPTYPE_FLOAT:
219 case FieldDescriptor::CPPTYPE_ENUM:
220 case FieldDescriptor::CPPTYPE_MESSAGE:
221 GOOGLE_LOG(FATAL) << "Can't get here.";
222 break;
223 }
224 }
225
226 private:
227 template <typename K, typename V>
228 friend class internal::TypeDefinedMapFieldBase;
229 friend class MapIterator;
230 friend class internal::DynamicMapField;
231
232 union KeyValue {
233 KeyValue() {}
234 string* string_value_;
235 int64 int64_value_;
236 int32 int32_value_;
237 uint64 uint64_value_;
238 uint32 uint32_value_;
239 bool bool_value_;
240 } val_;
241
242 void SetType(FieldDescriptor::CppType type) {
243 if (type_ == type) return;
244 if (type_ == FieldDescriptor::CPPTYPE_STRING) {
245 delete val_.string_value_;
246 }
247 type_ = type;
248 if (type_ == FieldDescriptor::CPPTYPE_STRING) {
249 val_.string_value_ = new string;
250 }
251 }
252
253 // type_ is 0 or a valid FieldDescriptor::CppType.
254 int type_;
255};
256
257// MapValueRef points to a map value.
258class LIBPROTOBUF_EXPORT MapValueRef {
259 public:
260 MapValueRef() : data_(NULL), type_(0) {}
261
262 void SetInt64Value(int64 value) {
263 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
264 "MapValueRef::SetInt64Value");
265 *reinterpret_cast<int64*>(data_) = value;
266 }
267 void SetUInt64Value(uint64 value) {
268 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
269 "MapValueRef::SetUInt64Value");
270 *reinterpret_cast<uint64*>(data_) = value;
271 }
272 void SetInt32Value(int32 value) {
273 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
274 "MapValueRef::SetInt32Value");
275 *reinterpret_cast<int32*>(data_) = value;
276 }
277 void SetUInt32Value(uint32 value) {
278 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
279 "MapValueRef::SetUInt32Value");
280 *reinterpret_cast<uint32*>(data_) = value;
281 }
282 void SetBoolValue(bool value) {
283 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
284 "MapValueRef::SetBoolValue");
285 *reinterpret_cast<bool*>(data_) = value;
286 }
287 // TODO(jieluo) - Checks that enum is member.
288 void SetEnumValue(int value) {
289 TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
290 "MapValueRef::SetEnumValue");
291 *reinterpret_cast<int*>(data_) = value;
292 }
293 void SetStringValue(const string& value) {
294 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
295 "MapValueRef::SetStringValue");
296 *reinterpret_cast<string*>(data_) = value;
297 }
298 void SetFloatValue(float value) {
299 TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
300 "MapValueRef::SetFloatValue");
301 *reinterpret_cast<float*>(data_) = value;
302 }
303 void SetDoubleValue(double value) {
304 TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
305 "MapValueRef::SetDoubleValue");
306 *reinterpret_cast<double*>(data_) = value;
307 }
308
309 int64 GetInt64Value() const {
310 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
311 "MapValueRef::GetInt64Value");
312 return *reinterpret_cast<int64*>(data_);
313 }
314 uint64 GetUInt64Value() const {
315 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
316 "MapValueRef::GetUInt64Value");
317 return *reinterpret_cast<uint64*>(data_);
318 }
319 int32 GetInt32Value() const {
320 TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
321 "MapValueRef::GetInt32Value");
322 return *reinterpret_cast<int32*>(data_);
323 }
324 uint32 GetUInt32Value() const {
325 TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
326 "MapValueRef::GetUInt32Value");
327 return *reinterpret_cast<uint32*>(data_);
328 }
329 bool GetBoolValue() const {
330 TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
331 "MapValueRef::GetBoolValue");
332 return *reinterpret_cast<bool*>(data_);
333 }
334 int GetEnumValue() const {
335 TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
336 "MapValueRef::GetEnumValue");
337 return *reinterpret_cast<int*>(data_);
338 }
339 const string& GetStringValue() const {
340 TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
341 "MapValueRef::GetStringValue");
342 return *reinterpret_cast<string*>(data_);
343 }
344 float GetFloatValue() const {
345 TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
346 "MapValueRef::GetFloatValue");
347 return *reinterpret_cast<float*>(data_);
348 }
349 double GetDoubleValue() const {
350 TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
351 "MapValueRef::GetDoubleValue");
352 return *reinterpret_cast<double*>(data_);
353 }
354
355 const Message& GetMessageValue() const {
356 TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
357 "MapValueRef::GetMessageValue");
358 return *reinterpret_cast<Message*>(data_);
359 }
360
361 Message* MutableMessageValue() {
362 TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
363 "MapValueRef::MutableMessageValue");
364 return reinterpret_cast<Message*>(data_);
365 }
366
367 private:
368 template <typename K, typename V,
369 internal::WireFormatLite::FieldType key_wire_type,
370 internal::WireFormatLite::FieldType value_wire_type,
371 int default_enum_value>
372 friend class internal::MapField;
373 template <typename K, typename V>
374 friend class internal::TypeDefinedMapFieldBase;
375 friend class MapIterator;
376 friend class internal::GeneratedMessageReflection;
377 friend class internal::DynamicMapField;
378
379 void SetType(FieldDescriptor::CppType type) {
380 type_ = type;
381 }
382
383 FieldDescriptor::CppType type() const {
384 if (type_ == 0 || data_ == NULL) {
385 GOOGLE_LOG(FATAL)
386 << "Protocol Buffer map usage error:\n"
387 << "MapValueRef::type MapValueRef is not initialized.";
388 }
389 return (FieldDescriptor::CppType)type_;
390 }
391 void SetValue(const void* val) {
392 data_ = const_cast<void*>(val);
393 }
394 void CopyFrom(const MapValueRef& other) {
395 type_ = other.type_;
396 data_ = other.data_;
397 }
398 // Only used in DynamicMapField
399 void DeleteData() {
400 switch (type_) {
401#define HANDLE_TYPE(CPPTYPE, TYPE) \
402 case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
403 delete reinterpret_cast<TYPE*>(data_); \
404 break; \
405 }
406 HANDLE_TYPE(INT32, int32);
407 HANDLE_TYPE(INT64, int64);
408 HANDLE_TYPE(UINT32, uint32);
409 HANDLE_TYPE(UINT64, uint64);
410 HANDLE_TYPE(DOUBLE, double);
411 HANDLE_TYPE(FLOAT, float);
412 HANDLE_TYPE(BOOL, bool);
413 HANDLE_TYPE(STRING, string);
414 HANDLE_TYPE(ENUM, int32);
415 HANDLE_TYPE(MESSAGE, Message);
416#undef HANDLE_TYPE
417 }
418 }
419 // data_ point to a map value. MapValueRef does not
420 // own this value.
421 void* data_;
422 // type_ is 0 or a valid FieldDescriptor::CppType.
423 int type_;
424};
425
426#undef TYPE_CHECK
427
428// This is the class for google::protobuf::Map's internal value_type. Instead of using
429// std::pair as value_type, we use this class which provides us more control of
430// its process of construction and destruction.
431template <typename Key, typename T>
432class MapPair {
433 public:
434 typedef const Key first_type;
435 typedef T second_type;
436
437 MapPair(const Key& other_first, const T& other_second)
438 : first(other_first), second(other_second) {}
439 explicit MapPair(const Key& other_first) : first(other_first), second() {}
440 MapPair(const MapPair& other)
441 : first(other.first), second(other.second) {}
442
443 ~MapPair() {}
444
445 // Implicitly convertible to std::pair of compatible types.
446 template <typename T1, typename T2>
447 operator std::pair<T1, T2>() const {
448 return std::pair<T1, T2>(first, second);
449 }
450
451 const Key first;
452 T second;
453
454 private:
455 friend class ::google::protobuf::Arena;
456 friend class Map<Key, T>;
457};
458
459// google::protobuf::Map is an associative container type used to store protobuf map
460// fields. Its interface is similar to std::unordered_map. Users should use this
461// interface directly to visit or change map fields.
462template <typename Key, typename T>
463class Map {
464 public:
465 typedef Key key_type;
466 typedef T mapped_type;
467 typedef MapPair<Key, T> value_type;
468
469 typedef value_type* pointer;
470 typedef const value_type* const_pointer;
471 typedef value_type& reference;
472 typedef const value_type& const_reference;
473
474 typedef size_t size_type;
475 typedef hash<Key> hasher;
476 typedef equal_to<Key> key_equal;
477
478 Map()
479 : arena_(NULL),
480 allocator_(arena_),
481 elements_(0, hasher(), key_equal(), allocator_),
482 default_enum_value_(0) {}
483 explicit Map(Arena* arena)
484 : arena_(arena),
485 allocator_(arena_),
486 elements_(0, hasher(), key_equal(), allocator_),
487 default_enum_value_(0) {
488 arena_->OwnDestructor(&elements_);
489 }
490
491 Map(const Map& other)
492 : arena_(NULL),
493 allocator_(arena_),
494 elements_(0, hasher(), key_equal(), allocator_),
495 default_enum_value_(other.default_enum_value_) {
496 insert(other.begin(), other.end());
497 }
498 template <class InputIt>
499 Map(const InputIt& first, const InputIt& last)
500 : arena_(NULL),
501 allocator_(arena_),
502 elements_(0, hasher(), key_equal(), allocator_),
503 default_enum_value_(0) {
504 insert(first, last);
505 }
506
507 ~Map() { clear(); }
508
509 private:
510 // re-implement std::allocator to use arena allocator for memory allocation.
511 // Used for google::protobuf::Map implementation. Users should not use this class
512 // directly.
513 template <typename U>
514 class MapAllocator {
515 public:
516 typedef U value_type;
517 typedef value_type* pointer;
518 typedef const value_type* const_pointer;
519 typedef value_type& reference;
520 typedef const value_type& const_reference;
521 typedef size_t size_type;
522 typedef ptrdiff_t difference_type;
523
524 MapAllocator() : arena_(NULL) {}
525 explicit MapAllocator(Arena* arena) : arena_(arena) {}
526 template <typename X>
527 MapAllocator(const MapAllocator<X>& allocator)
528 : arena_(allocator.arena_) {}
529
530 pointer allocate(size_type n, const_pointer hint = 0) {
531 // If arena is not given, malloc needs to be called which doesn't
532 // construct element object.
533 if (arena_ == NULL) {
534 return reinterpret_cast<pointer>(malloc(n * sizeof(value_type)));
535 } else {
536 return reinterpret_cast<pointer>(
537 Arena::CreateArray<uint8>(arena_, n * sizeof(value_type)));
538 }
539 }
540
541 void deallocate(pointer p, size_type n) {
542 if (arena_ == NULL) {
543 free(p);
544 }
545 }
546
547#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \
548 !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
549 template<class NodeType, class... Args>
550 void construct(NodeType* p, Args&&... args) {
551 new (static_cast<void*>(p)) NodeType(std::forward<Args>(args)...);
552 }
553
554 template<class NodeType>
555 void destroy(NodeType* p) {
556 p->~NodeType();
557 }
558#else
559 void construct(pointer p, const_reference t) { new (p) value_type(t); }
560
561 void destroy(pointer p) { p->~value_type(); }
562#endif
563
564 template <typename X>
565 struct rebind {
566 typedef MapAllocator<X> other;
567 };
568
569 template <typename X>
570 bool operator==(const MapAllocator<X>& other) const {
571 return arena_ == other.arena_;
572 }
573
574 template <typename X>
575 bool operator!=(const MapAllocator<X>& other) const {
576 return arena_ != other.arena_;
577 }
578
579 // To support Visual Studio 2008
580 size_type max_size() const {
581 return std::numeric_limits<size_type>::max();
582 }
583
584 private:
585 typedef void DestructorSkippable_;
586 Arena* const arena_;
587
588 template <typename X>
589 friend class MapAllocator;
590 };
591
592 typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
593 typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator>
594 InnerMap;
595
596 public:
597 // Iterators
598 class const_iterator
599 : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
600 const value_type*, const value_type&> {
601 typedef typename InnerMap::const_iterator InnerIt;
602
603 public:
604 const_iterator() {}
605 explicit const_iterator(const InnerIt& it) : it_(it) {}
606
607 const_reference operator*() const { return *it_->second; }
608 const_pointer operator->() const { return it_->second; }
609
610 const_iterator& operator++() {
611 ++it_;
612 return *this;
613 }
614 const_iterator operator++(int) { return const_iterator(it_++); }
615
616 friend bool operator==(const const_iterator& a, const const_iterator& b) {
617 return a.it_ == b.it_;
618 }
619 friend bool operator!=(const const_iterator& a, const const_iterator& b) {
620 return a.it_ != b.it_;
621 }
622
623 private:
624 InnerIt it_;
625 };
626
627 class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
628 typedef typename InnerMap::iterator InnerIt;
629
630 public:
631 iterator() {}
632 explicit iterator(const InnerIt& it) : it_(it) {}
633
634 reference operator*() const { return *it_->second; }
635 pointer operator->() const { return it_->second; }
636
637 iterator& operator++() {
638 ++it_;
639 return *this;
640 }
641 iterator operator++(int) { return iterator(it_++); }
642
643 // Implicitly convertible to const_iterator.
644 operator const_iterator() const { return const_iterator(it_); }
645
646 friend bool operator==(const iterator& a, const iterator& b) {
647 return a.it_ == b.it_;
648 }
649 friend bool operator!=(const iterator& a, const iterator& b) {
650 return a.it_ != b.it_;
651 }
652
653 private:
654 friend class Map;
655 InnerIt it_;
656 };
657
658 iterator begin() { return iterator(elements_.begin()); }
659 iterator end() { return iterator(elements_.end()); }
660 const_iterator begin() const { return const_iterator(elements_.begin()); }
661 const_iterator end() const { return const_iterator(elements_.end()); }
662 const_iterator cbegin() const { return begin(); }
663 const_iterator cend() const { return end(); }
664
665 // Capacity
666 size_type size() const { return elements_.size(); }
667 bool empty() const { return elements_.empty(); }
668
669 // Element access
670 T& operator[](const key_type& key) {
671 value_type** value = &elements_[key];
672 if (*value == NULL) {
673 *value = CreateValueTypeInternal(key);
674 internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
675 T>::Initialize((*value)->second,
676 default_enum_value_);
677 }
678 return (*value)->second;
679 }
680 const T& at(const key_type& key) const {
681 const_iterator it = find(key);
682 GOOGLE_CHECK(it != end());
683 return it->second;
684 }
685 T& at(const key_type& key) {
686 iterator it = find(key);
687 GOOGLE_CHECK(it != end());
688 return it->second;
689 }
690
691 // Lookup
692 size_type count(const key_type& key) const {
693 return elements_.count(key);
694 }
695 const_iterator find(const key_type& key) const {
696 return const_iterator(elements_.find(key));
697 }
698 iterator find(const key_type& key) {
699 return iterator(elements_.find(key));
700 }
701 std::pair<const_iterator, const_iterator> equal_range(
702 const key_type& key) const {
703 const_iterator it = find(key);
704 if (it == end()) {
705 return std::pair<const_iterator, const_iterator>(it, it);
706 } else {
707 const_iterator begin = it++;
708 return std::pair<const_iterator, const_iterator>(begin, it);
709 }
710 }
711 std::pair<iterator, iterator> equal_range(const key_type& key) {
712 iterator it = find(key);
713 if (it == end()) {
714 return std::pair<iterator, iterator>(it, it);
715 } else {
716 iterator begin = it++;
717 return std::pair<iterator, iterator>(begin, it);
718 }
719 }
720
721 // insert
722 std::pair<iterator, bool> insert(const value_type& value) {
723 iterator it = find(value.first);
724 if (it != end()) {
725 return std::pair<iterator, bool>(it, false);
726 } else {
727 return std::pair<iterator, bool>(
728 iterator(elements_.insert(std::pair<Key, value_type*>(
729 value.first, CreateValueTypeInternal(value))).first), true);
730 }
731 }
732 template <class InputIt>
733 void insert(InputIt first, InputIt last) {
734 for (InputIt it = first; it != last; ++it) {
735 iterator exist_it = find(it->first);
736 if (exist_it == end()) {
737 operator[](it->first) = it->second;
738 }
739 }
740 }
741
742 // Erase
743 size_type erase(const key_type& key) {
744 typename InnerMap::iterator it = elements_.find(key);
745 if (it == elements_.end()) {
746 return 0;
747 } else {
748 if (arena_ == NULL) delete it->second;
749 elements_.erase(it);
750 return 1;
751 }
752 }
753 void erase(iterator pos) {
754 if (arena_ == NULL) delete pos.it_->second;
755 elements_.erase(pos.it_);
756 }
757 void erase(iterator first, iterator last) {
758 for (iterator it = first; it != last;) {
759 if (arena_ == NULL) delete it.it_->second;
760 elements_.erase((it++).it_);
761 }
762 }
763 void clear() {
764 for (iterator it = begin(); it != end(); ++it) {
765 if (arena_ == NULL) delete it.it_->second;
766 }
767 elements_.clear();
768 }
769
770 // Assign
771 Map& operator=(const Map& other) {
772 if (this != &other) {
773 clear();
774 insert(other.begin(), other.end());
775 }
776 return *this;
777 }
778
779 private:
780 // Set default enum value only for proto2 map field whose value is enum type.
781 void SetDefaultEnumValue(int default_enum_value) {
782 default_enum_value_ = default_enum_value;
783 }
784
785 value_type* CreateValueTypeInternal(const Key& key) {
786 if (arena_ == NULL) {
787 return new value_type(key);
788 } else {
789 value_type* value = reinterpret_cast<value_type*>(
790 Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
791 Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_);
792 Arena::CreateInArenaStorage(&value->second, arena_);
793 const_cast<Key&>(value->first) = key;
794 return value;
795 }
796 }
797
798 value_type* CreateValueTypeInternal(const value_type& value) {
799 if (arena_ == NULL) {
800 return new value_type(value);
801 } else {
802 value_type* p = reinterpret_cast<value_type*>(
803 Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
804 Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_);
805 Arena::CreateInArenaStorage(&p->second, arena_);
806 const_cast<Key&>(p->first) = value.first;
807 p->second = value.second;
808 return p;
809 }
810 }
811
812 Arena* arena_;
813 Allocator allocator_;
814 InnerMap elements_;
815 int default_enum_value_;
816
817 friend class ::google::protobuf::Arena;
818 typedef void InternalArenaConstructable_;
819 typedef void DestructorSkippable_;
820 template <typename K, typename V,
821 internal::WireFormatLite::FieldType key_wire_type,
822 internal::WireFormatLite::FieldType value_wire_type,
823 int default_enum_value>
824 friend class internal::MapFieldLite;
825};
826
827} // namespace protobuf
828} // namespace google
829
830GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
831template<>
832struct hash<google::protobuf::MapKey> {
833 size_t
834 operator()(const google::protobuf::MapKey& map_key) const {
835 switch (map_key.type()) {
836 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
837 return hash<string>()(map_key.GetStringValue());
838 case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
839 return hash< ::google::protobuf::int64>()(map_key.GetInt64Value());
840 case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
841 return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
842 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
843 return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value());
844 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
845 return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
846 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
847 return hash<bool>()(map_key.GetBoolValue());
848 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
849 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
850 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
851 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
852 GOOGLE_LOG(FATAL) << "Can't get here.";
853 }
854 GOOGLE_LOG(FATAL) << "Can't get here.";
855 return 0;
856 }
857 bool
858 operator()(const google::protobuf::MapKey& map_key1,
859 const google::protobuf::MapKey& map_key2) const {
860 switch (map_key1.type()) {
861#define COMPARE_CPPTYPE(CPPTYPE, CPPTYPE_METHOD) \
862 case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
863 return map_key1.Get##CPPTYPE_METHOD##Value() < \
864 map_key2.Get##CPPTYPE_METHOD##Value();
865 COMPARE_CPPTYPE(STRING, String)
866 COMPARE_CPPTYPE(INT64, Int64)
867 COMPARE_CPPTYPE(INT32, Int32)
868 COMPARE_CPPTYPE(UINT64, UInt64)
869 COMPARE_CPPTYPE(UINT32, UInt32)
870 COMPARE_CPPTYPE(BOOL, Bool)
871#undef COMPARE_CPPTYPE
872 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
873 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
874 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
875 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
876 GOOGLE_LOG(FATAL) << "Can't get here.";
877 }
878 GOOGLE_LOG(FATAL) << "Can't get here.";
879 return true;
880 }
881};
882GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
883
884#endif // GOOGLE_PROTOBUF_MAP_H__