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_FIELD_LITE_H__ |
32 | #define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ |
33 | |
34 | #include <type_traits> |
35 | |
36 | #include <google/protobuf/io/coded_stream.h> |
37 | #include <google/protobuf/port.h> |
38 | #include <google/protobuf/map.h> |
39 | #include <google/protobuf/map_entry_lite.h> |
40 | #include <google/protobuf/parse_context.h> |
41 | #include <google/protobuf/wire_format_lite.h> |
42 | |
43 | // Must be included last. |
44 | #include <google/protobuf/port_def.inc> |
45 | |
46 | #ifdef SWIG |
47 | #error "You cannot SWIG proto headers" |
48 | #endif |
49 | |
50 | namespace google { |
51 | namespace protobuf { |
52 | namespace internal { |
53 | |
54 | #ifndef NDEBUG |
55 | void MapFieldLiteNotDestructed(void* map_field_lite); |
56 | #endif |
57 | |
58 | // This class provides access to map field using generated api. It is used for |
59 | // internal generated message implementation only. Users should never use this |
60 | // directly. |
61 | template <typename Derived, typename Key, typename T, |
62 | WireFormatLite::FieldType key_wire_type, |
63 | WireFormatLite::FieldType value_wire_type> |
64 | class MapFieldLite { |
65 | // Define message type for internal repeated field. |
66 | typedef Derived EntryType; |
67 | |
68 | public: |
69 | typedef Map<Key, T> MapType; |
70 | |
71 | constexpr MapFieldLite() : map_() {} |
72 | explicit MapFieldLite(Arena* arena) : map_(arena) {} |
73 | MapFieldLite(ArenaInitialized, Arena* arena) : MapFieldLite(arena) {} |
74 | |
75 | #ifdef NDEBUG |
76 | void Destruct() { map_.~Map(); } |
77 | ~MapFieldLite() {} |
78 | #else |
79 | void Destruct() { |
80 | // We want to destruct the map in such a way that we can verify |
81 | // that we've done that, but also be sure that we've deallocated |
82 | // everything (as opposed to leaving an allocation behind with no |
83 | // data in it, as would happen if a vector was resize'd to zero. |
84 | // Map::Swap with an empty map accomplishes that. |
85 | decltype(map_) swapped_map(map_.arena()); |
86 | map_.InternalSwap(swapped_map); |
87 | } |
88 | ~MapFieldLite() { |
89 | if (map_.arena() == nullptr && !map_.empty()) { |
90 | MapFieldLiteNotDestructed(this); |
91 | } |
92 | } |
93 | #endif |
94 | // Accessors |
95 | const Map<Key, T>& GetMap() const { return map_; } |
96 | Map<Key, T>* MutableMap() { return &map_; } |
97 | |
98 | // Convenient methods for generated message implementation. |
99 | int size() const { return static_cast<int>(map_.size()); } |
100 | void Clear() { return map_.clear(); } |
101 | void MergeFrom(const MapFieldLite& other) { |
102 | for (typename Map<Key, T>::const_iterator it = other.map_.begin(); |
103 | it != other.map_.end(); ++it) { |
104 | map_[it->first] = it->second; |
105 | } |
106 | } |
107 | void Swap(MapFieldLite* other) { map_.swap(other->map_); } |
108 | void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); } |
109 | |
110 | // Used in the implementation of parsing. Caller should take the ownership iff |
111 | // arena_ is nullptr. |
112 | EntryType* NewEntry() const { |
113 | return Arena::CreateMessage<EntryType>(map_.arena()); |
114 | } |
115 | |
116 | const char* _InternalParse(const char* ptr, ParseContext* ctx) { |
117 | typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this); |
118 | return parser._InternalParse(ptr, ctx); |
119 | } |
120 | |
121 | template <typename UnknownType> |
122 | const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, |
123 | bool (*is_valid)(int), uint32_t field_num, |
124 | InternalMetadata* metadata) { |
125 | typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this); |
126 | return parser.template ParseWithEnumValidation<UnknownType>( |
127 | ptr, ctx, is_valid, field_num, metadata); |
128 | } |
129 | |
130 | private: |
131 | typedef void DestructorSkippable_; |
132 | |
133 | // map_ is inside an anonymous union so we can explicitly control its |
134 | // destruction |
135 | union { |
136 | Map<Key, T> map_; |
137 | }; |
138 | |
139 | friend class ::PROTOBUF_NAMESPACE_ID::Arena; |
140 | }; |
141 | |
142 | template <typename UnknownType, typename T> |
143 | struct EnumParseWrapper { |
144 | const char* _InternalParse(const char* ptr, ParseContext* ctx) { |
145 | return map_field->template ParseWithEnumValidation<UnknownType>( |
146 | ptr, ctx, is_valid, field_num, metadata); |
147 | } |
148 | T* map_field; |
149 | bool (*is_valid)(int); |
150 | uint32_t field_num; |
151 | InternalMetadata* metadata; |
152 | }; |
153 | |
154 | // Helper function because the typenames of maps are horrendous to print. This |
155 | // leverages compiler type deduction, to keep all type data out of the |
156 | // generated code |
157 | template <typename UnknownType, typename T> |
158 | EnumParseWrapper<UnknownType, T> InitEnumParseWrapper( |
159 | T* map_field, bool (*is_valid)(int), uint32_t field_num, |
160 | InternalMetadata* metadata) { |
161 | return EnumParseWrapper<UnknownType, T>{map_field, is_valid, field_num, |
162 | metadata}; |
163 | } |
164 | |
165 | // True if IsInitialized() is true for value field in all elements of t. T is |
166 | // expected to be message. It's useful to have this helper here to keep the |
167 | // protobuf compiler from ever having to emit loops in IsInitialized() methods. |
168 | // We want the C++ compiler to inline this or not as it sees fit. |
169 | template <typename Derived, typename Key, typename T, |
170 | WireFormatLite::FieldType key_wire_type, |
171 | WireFormatLite::FieldType value_wire_type> |
172 | bool AllAreInitialized(const MapFieldLite<Derived, Key, T, key_wire_type, |
173 | value_wire_type>& field) { |
174 | const auto& t = field.GetMap(); |
175 | for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end(); |
176 | ++it) { |
177 | if (!it->second.IsInitialized()) return false; |
178 | } |
179 | return true; |
180 | } |
181 | |
182 | template <typename MEntry> |
183 | struct MapEntryToMapField : MapEntryToMapField<typename MEntry::SuperType> {}; |
184 | |
185 | template <typename T, typename Key, typename Value, |
186 | WireFormatLite::FieldType kKeyFieldType, |
187 | WireFormatLite::FieldType kValueFieldType> |
188 | struct MapEntryToMapField< |
189 | MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>> { |
190 | typedef MapFieldLite< |
191 | MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>, Key, Value, |
192 | kKeyFieldType, kValueFieldType> |
193 | MapFieldType; |
194 | }; |
195 | |
196 | #ifndef NDEBUG |
197 | inline PROTOBUF_NOINLINE void MapFieldLiteNotDestructed(void* map_field_lite) { |
198 | bool proper_destruct = false; |
199 | GOOGLE_CHECK(proper_destruct) << map_field_lite; |
200 | } |
201 | #endif |
202 | |
203 | } // namespace internal |
204 | } // namespace protobuf |
205 | } // namespace google |
206 | |
207 | #include <google/protobuf/port_undef.inc> |
208 | |
209 | #endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ |
210 | |