1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
9 #define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
10
11 #include <cstddef>
12 #include <type_traits>
13
14 #include "absl/log/absl_check.h"
15 #include "google/protobuf/internal_visibility.h"
16 #include "google/protobuf/io/coded_stream.h"
17 #include "google/protobuf/map.h"
18 #include "google/protobuf/parse_context.h"
19 #include "google/protobuf/port.h"
20 #include "google/protobuf/wire_format_lite.h"
21
22 // Must be included last.
23 #include "google/protobuf/port_def.inc"
24
25 #ifdef SWIG
26 #error "You cannot SWIG proto headers"
27 #endif
28
29 namespace google {
30 namespace protobuf {
31 namespace internal {
32
33 // This class provides access to map field using generated api. It is used for
34 // internal generated message implementation only. Users should never use this
35 // directly.
36 template <typename Key, typename T>
37 class MapFieldLite {
38 public:
39 typedef Map<Key, T> MapType;
40
MapFieldLite()41 constexpr MapFieldLite() : map_() {}
MapFieldLite(Arena * arena)42 explicit MapFieldLite(Arena* arena) : map_(arena) {}
MapFieldLite(ArenaInitialized,Arena * arena)43 MapFieldLite(ArenaInitialized, Arena* arena) : MapFieldLite(arena) {}
44
MapFieldLite(InternalVisibility,Arena * arena)45 MapFieldLite(InternalVisibility, Arena* arena) : map_(arena) {}
MapFieldLite(InternalVisibility,Arena * arena,const MapFieldLite & from)46 MapFieldLite(InternalVisibility, Arena* arena, const MapFieldLite& from)
47 : map_(arena) {
48 MergeFrom(from);
49 }
50
51 #ifdef NDEBUG
~MapFieldLite()52 ~MapFieldLite() { map_.~Map(); }
53 #else
~MapFieldLite()54 ~MapFieldLite() {
55 ABSL_DCHECK_EQ(map_.arena(), nullptr);
56 // We want to destruct the map in such a way that we can verify
57 // that we've done that, but also be sure that we've deallocated
58 // everything (as opposed to leaving an allocation behind with no
59 // data in it, as would happen if a vector was resize'd to zero.
60 // Map::Swap with an empty map accomplishes that.
61 decltype(map_) swapped_map(map_.arena());
62 map_.InternalSwap(&swapped_map);
63 }
64 #endif
65 // Accessors
GetMap()66 const Map<Key, T>& GetMap() const { return map_; }
MutableMap()67 Map<Key, T>* MutableMap() { return &map_; }
68
69 // Convenient methods for generated message implementation.
size()70 int size() const { return static_cast<int>(map_.size()); }
Clear()71 void Clear() { return map_.clear(); }
MergeFrom(const MapFieldLite & other)72 void MergeFrom(const MapFieldLite& other) {
73 internal::MapMergeFrom(map_, other.map_);
74 }
Swap(MapFieldLite * other)75 void Swap(MapFieldLite* other) { map_.swap(other->map_); }
InternalSwap(MapFieldLite * other)76 void InternalSwap(MapFieldLite* other) { map_.InternalSwap(&other->map_); }
77
InternalGetArenaOffset(internal::InternalVisibility access)78 static constexpr size_t InternalGetArenaOffset(
79 internal::InternalVisibility access) {
80 return PROTOBUF_FIELD_OFFSET(MapFieldLite, map_) +
81 decltype(map_)::InternalGetArenaOffset(access);
82 }
83
84 private:
85 typedef void DestructorSkippable_;
86
87 // map_ is inside an anonymous union so we can explicitly control its
88 // destruction
89 union {
90 Map<Key, T> map_;
91 };
92
93 friend class google::protobuf::Arena;
94 };
95
96 // True if IsInitialized() is true for value field in all elements of t. T is
97 // expected to be message. It's useful to have this helper here to keep the
98 // protobuf compiler from ever having to emit loops in IsInitialized() methods.
99 // We want the C++ compiler to inline this or not as it sees fit.
100 template <typename Key, typename T>
AllAreInitialized(const MapFieldLite<Key,T> & field)101 bool AllAreInitialized(const MapFieldLite<Key, T>& field) {
102 const auto& t = field.GetMap();
103 for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
104 ++it) {
105 if (!it->second.IsInitialized()) return false;
106 }
107 return true;
108 }
109
110 template <typename MEntry>
111 struct MapEntryToMapField : MapEntryToMapField<typename MEntry::SuperType> {};
112
113 } // namespace internal
114 } // namespace protobuf
115 } // namespace google
116
117 #include "google/protobuf/port_undef.inc"
118
119 #endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
120