blob: 987c4e297c8aa467c2dd125327734951a77cfaa8 [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_ENTRY_H__
32#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
33
34#include <google/protobuf/generated_message_reflection.h>
35#include <google/protobuf/map_entry_lite.h>
36#include <google/protobuf/map_type_handler.h>
37#include <google/protobuf/metadata.h>
38#include <google/protobuf/reflection_ops.h>
39#include <google/protobuf/unknown_field_set.h>
40#include <google/protobuf/wire_format_lite_inl.h>
41
42namespace google {
43namespace protobuf {
44class Arena;
45namespace internal {
46template <typename Key, typename Value,
47 WireFormatLite::FieldType kKeyFieldType,
48 WireFormatLite::FieldType kValueFieldType,
49 int default_enum_value>
50class MapField;
51}
52}
53
54namespace protobuf {
55namespace internal {
56
57// Register all MapEntry default instances so we can delete them in
58// ShutdownProtobufLibrary().
59void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
60 MessageLite* default_instance);
61
62// This is the common base class for MapEntry. It is used by MapFieldBase in
63// reflection api, in which the static type of key and value is unknown.
64class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
65 public:
66 ::google::protobuf::Metadata GetMetadata() const {
67 ::google::protobuf::Metadata metadata;
68 metadata.descriptor = descriptor_;
69 metadata.reflection = reflection_;
70 return metadata;
71 }
72
73 protected:
74 MapEntryBase() : descriptor_(NULL), reflection_(NULL) { }
75 virtual ~MapEntryBase() {}
76
77 const Descriptor* descriptor_;
78 const Reflection* reflection_;
79};
80
81// MapEntry is the returned google::protobuf::Message when calling AddMessage of
82// google::protobuf::Reflection. In order to let it work with generated message
83// reflection, its in-memory type is the same as generated message with the same
84// fields. However, in order to decide the in-memory type of key/value, we need
85// to know both their cpp type in generated api and proto type. In
86// implmentation, all in-memory types have related wire format functions to
87// support except ArenaStringPtr. Therefore, we need to define another type with
88// supporting wire format functions. Since this type is only used as return type
89// of MapEntry accessors, it's named MapEntry accessor type.
90//
91// cpp type: the type visible to users in public API.
92// proto type: WireFormatLite::FieldType of the field.
93// in-memory type: type of the data member used to stored this field.
94// MapEntry accessor type: type used in MapEntry getters/mutators to access the
95// field.
96//
97// cpp type | proto type | in-memory type | MapEntry accessor type
98// int32 TYPE_INT32 int32 int32
99// int32 TYPE_FIXED32 int32 int32
100// string TYPE_STRING ArenaStringPtr string
101// FooEnum TYPE_ENUM int int
102// FooMessage TYPE_MESSAGE FooMessage* FooMessage
103//
104// The in-memory types of primitive types can be inferred from its proto type,
105// while we need to explicitly specify the cpp type if proto type is
106// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is
107// used to initialize enum field in proto2.
108template <typename Key, typename Value,
109 WireFormatLite::FieldType kKeyFieldType,
110 WireFormatLite::FieldType kValueFieldType,
111 int default_enum_value>
112class MapEntry : public MapEntryBase {
113 // Provide utilities to parse/serialize key/value. Provide utilities to
114 // manipulate internal stored type.
115 typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
116 typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
117
118 // Enum type cannot be used for MapTypeHandler::Read. Define a type
119 // which will replace Enum with int.
120 typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
121 typedef typename ValueTypeHandler::MapEntryAccessorType
122 ValueMapEntryAccessorType;
123
124 // Abbreviation for MapEntry
125 typedef typename google::protobuf::internal::MapEntry<
126 Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
127
128 // Abbreviation for MapEntryLite
129 typedef typename google::protobuf::internal::MapEntryLite<
130 Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
131 EntryLiteType;
132
133 public:
134 ~MapEntry() {
135 if (this == default_instance_) {
136 delete reflection_;
137 }
138 }
139
140 // accessors ======================================================
141
142 virtual inline const KeyMapEntryAccessorType& key() const {
143 return entry_lite_.key();
144 }
145 inline KeyMapEntryAccessorType* mutable_key() {
146 return entry_lite_.mutable_key();
147 }
148 virtual inline const ValueMapEntryAccessorType& value() const {
149 return entry_lite_.value();
150 }
151 inline ValueMapEntryAccessorType* mutable_value() {
152 return entry_lite_.mutable_value();
153 }
154
155 // implements Message =============================================
156
157 bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
158 return entry_lite_.MergePartialFromCodedStream(input);
159 }
160
161 int ByteSize() const {
162 return entry_lite_.ByteSize();
163 }
164
165 void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
166 entry_lite_.SerializeWithCachedSizes(output);
167 }
168
169 ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
170 return entry_lite_.SerializeWithCachedSizesToArray(output);
171 }
172
173 int GetCachedSize() const {
174 return entry_lite_.GetCachedSize();
175 }
176
177 bool IsInitialized() const {
178 return entry_lite_.IsInitialized();
179 }
180
181 Message* New() const {
182 MapEntry* entry = new MapEntry;
183 entry->descriptor_ = descriptor_;
184 entry->reflection_ = reflection_;
185 entry->set_default_instance(default_instance_);
186 return entry;
187 }
188
189 Message* New(Arena* arena) const {
190 MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
191 entry->descriptor_ = descriptor_;
192 entry->reflection_ = reflection_;
193 entry->set_default_instance(default_instance_);
194 return entry;
195 }
196
197 int SpaceUsed() const {
198 int size = sizeof(MapEntry);
199 size += entry_lite_.SpaceUsed();
200 return size;
201 }
202
203 void CopyFrom(const ::google::protobuf::Message& from) {
204 Clear();
205 MergeFrom(from);
206 }
207
208 void MergeFrom(const ::google::protobuf::Message& from) {
209 GOOGLE_CHECK_NE(&from, this);
210 const MapEntry* source = dynamic_cast_if_available<const MapEntry*>(&from);
211 if (source == NULL) {
212 ReflectionOps::Merge(from, this);
213 } else {
214 MergeFrom(*source);
215 }
216 }
217
218 void CopyFrom(const MapEntry& from) {
219 Clear();
220 MergeFrom(from);
221 }
222
223 void MergeFrom(const MapEntry& from) {
224 entry_lite_.MergeFrom(from.entry_lite_);
225 }
226
227 void Clear() {
228 entry_lite_.Clear();
229 }
230
231 void InitAsDefaultInstance() {
232 entry_lite_.InitAsDefaultInstance();
233 }
234
235 Arena* GetArena() const {
236 return entry_lite_.GetArena();
237 }
238
239 // Create default MapEntry instance for given descriptor. Descriptor has to be
240 // given when creating default MapEntry instance because different map field
241 // may have the same type and MapEntry class. The given descriptor is needed
242 // to distinguish instances of the same MapEntry class.
243 static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
244 MapEntry* entry = new MapEntry;
245 const Reflection* reflection = new GeneratedMessageReflection(
246 descriptor, entry, offsets_,
247 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
248 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
249 DescriptorPool::generated_pool(),
250 ::google::protobuf::MessageFactory::generated_factory(),
251 sizeof(MapEntry),
252 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_));
253 entry->descriptor_ = descriptor;
254 entry->reflection_ = reflection;
255 entry->set_default_instance(entry);
256 entry->InitAsDefaultInstance();
257 RegisterMapEntryDefaultInstance(entry);
258 return entry;
259 }
260
261 private:
262 MapEntry()
263 : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {}
264
265 explicit MapEntry(Arena* arena)
266 : _internal_metadata_(arena),
267 default_instance_(NULL),
268 entry_lite_(arena) {}
269
270 inline Arena* GetArenaNoVirtual() const {
271 return entry_lite_.GetArenaNoVirtual();
272 }
273
274 void set_default_instance(MapEntry* default_instance) {
275 default_instance_ = default_instance;
276 entry_lite_.set_default_instance(&default_instance->entry_lite_);
277 }
278
279 static int offsets_[2];
280 UnknownFieldSet _unknown_fields_;
281 InternalMetadataWithArena _internal_metadata_;
282 MapEntry* default_instance_;
283 EntryLiteType entry_lite_;
284
285 friend class ::google::protobuf::Arena;
286 typedef void InternalArenaConstructable_;
287 typedef void DestructorSkippable_;
288 template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
289 WireFormatLite::FieldType, int default_enum>
290 friend class internal::MapField;
291 friend class internal::GeneratedMessageReflection;
292
293 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
294};
295
296template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
297 WireFormatLite::FieldType kValueFieldType, int default_enum_value>
298int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
299 default_enum_value>::offsets_[2] = {
300 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
301 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
302};
303
304} // namespace internal
305} // namespace protobuf
306
307} // namespace google
308#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__