blob: 0602d8479feeab9f3f064a98541c216c5e513495 [file] [log] [blame]
Jisi Liu885b6122015-02-28 14:51:22 -08001// 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 <google/protobuf/map_type_handler.h>
35#include <google/protobuf/wire_format_lite_inl.h>
36
37namespace google {
38namespace protobuf {
39class Arena;
40namespace internal {
41template <typename Key, typename Value,
42 WireFormatLite::FieldType kKeyFieldType,
43 WireFormatLite::FieldType kValueFieldType,
44 int default_enum_value>
45class MapEntry;
46template <typename Key, typename Value,
47 WireFormatLite::FieldType kKeyFieldType,
48 WireFormatLite::FieldType kValueFieldType,
49 int default_enum_value>
50class MapFieldLite;
51} // namespace internal
52} // namespace protobuf
53
54namespace protobuf {
55namespace internal {
56
57// MapEntryLite is used to implement parsing and serialization of map for lite
58// runtime.
59template <typename Key, typename Value,
60 WireFormatLite::FieldType kKeyFieldType,
61 WireFormatLite::FieldType kValueFieldType,
62 int default_enum_value>
63class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
64 // Handlers for key/value wire type. Provide utilities to parse/serialize
65 // key/value.
66 typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
67 typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
68
69 // Define key/value's internal stored type. Message is the only one whose
70 // internal stored type cannot be inferred from its proto type
71 static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
72 static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
73 typedef typename KeyWireHandler::CppType KeyInternalType;
74 typedef typename ValueWireHandler::CppType ValueInternalType;
75 typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
76 KeyCppType;
77 typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
78 ValCppType;
79
80 // Handlers for key/value's internal stored type. Provide utilities to
81 // manipulate internal stored type. We need it because some types are stored
82 // as values and others are stored as pointers (Message and string), but we
83 // need to keep the code in MapEntry unified instead of providing different
84 // codes for each type.
85 typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
86 typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
87
88 // Define internal memory layout. Strings and messages are stored as
89 // pointers, while other types are stored as values.
90 static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
91 static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
92 typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
93 KeyBase;
94 typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
95 ValueBase;
96
97 // Constants for field number.
98 static const int kKeyFieldNumber = 1;
99 static const int kValueFieldNumber = 2;
100
101 // Constants for field tag.
102 static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
103 kKeyFieldNumber, KeyWireHandler::kWireType);
104 static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
105 kValueFieldNumber, ValueWireHandler::kWireType);
106 static const int kTagSize = 1;
107
108 public:
109 ~MapEntryLite() {
110 if (this != default_instance_) {
111 KeyCppHandler::Delete(key_);
112 ValueCppHandler::Delete(value_);
113 }
114 }
115
116 // accessors ======================================================
117
118 virtual inline const KeyCppType& key() const {
119 return KeyCppHandler::Reference(key_);
120 }
121 inline KeyCppType* mutable_key() {
122 set_has_key();
123 KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
124 return KeyCppHandler::Pointer(key_);
125 }
126 virtual inline const ValCppType& value() const {
127 GOOGLE_CHECK(default_instance_ != NULL);
128 return ValueCppHandler::DefaultIfNotInitialized(value_,
129 default_instance_->value_);
130 }
131 inline ValCppType* mutable_value() {
132 set_has_value();
133 ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
134 return ValueCppHandler::Pointer(value_);
135 }
136
137 // implements MessageLite =========================================
138
139 // MapEntryLite is for implementation only and this function isn't called
140 // anywhere. Just provide a fake implementation here for MessageLite.
141 string GetTypeName() const { return ""; }
142
143 void CheckTypeAndMergeFrom(const MessageLite& other) {
144 MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
145 }
146
147 bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
148 uint32 tag;
149
150 for (;;) {
151 // 1) corrupted data: return false;
152 // 2) unknown field: skip without putting into unknown field set;
153 // 3) unknown enum value: keep it in parsing. In proto2, caller should
154 // check the value and put this entry into containing message's unknown
155 // field set if the value is an unknown enum. In proto3, caller doesn't
156 // need to care whether the value is unknown enum;
157 // 4) missing key/value: missed key/value will have default value. caller
158 // should take this entry as if key/value is set to default value.
159 tag = input->ReadTag();
160 switch (tag) {
161 case kKeyTag:
162 if (!KeyWireHandler::Read(input, mutable_key())) return false;
163 set_has_key();
164 if (!input->ExpectTag(kValueTag)) break;
165 GOOGLE_FALLTHROUGH_INTENDED;
166
167 case kValueTag:
168 if (!ValueWireHandler::Read(input, mutable_value())) return false;
169 set_has_value();
170 if (input->ExpectAtEnd()) return true;
171 break;
172
173 default:
174 if (tag == 0 ||
175 WireFormatLite::GetTagWireType(tag) ==
176 WireFormatLite::WIRETYPE_END_GROUP) {
177 return true;
178 }
179 if (!WireFormatLite::SkipField(input, tag)) return false;
180 break;
181 }
182 }
183 }
184
185 int ByteSize() const {
186 int size = 0;
187 size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0;
188 size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0;
189 return size;
190 }
191
192 void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
193 KeyWireHandler::Write(kKeyFieldNumber, key(), output);
194 ValueWireHandler::Write(kValueFieldNumber, value(), output);
195 }
196
197 ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
198 output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output);
199 output =
200 ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output);
201 return output;
202 }
203
204 int GetCachedSize() const {
205 int size = 0;
206 size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0;
207 size +=
208 has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0;
209 return size;
210 }
211
212 bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
213
214 MessageLite* New() const {
215 MapEntryLite* entry = new MapEntryLite;
216 entry->default_instance_ = default_instance_;
217 return entry;
218 }
219
220 MessageLite* New(Arena* arena) const {
221 MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
222 entry->default_instance_ = default_instance_;
223 return entry;
224 }
225
226 int SpaceUsed() const {
227 int size = sizeof(MapEntryLite);
228 size += KeyCppHandler::SpaceUsedInMapEntry(key_);
229 size += ValueCppHandler::SpaceUsedInMapEntry(value_);
230 return size;
231 }
232
233 void MergeFrom(const MapEntryLite& from) {
234 if (from._has_bits_[0]) {
235 if (from.has_key()) {
236 KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
237 KeyCppHandler::Merge(from.key(), &key_);
238 set_has_key();
239 }
240 if (from.has_value()) {
241 ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
242 ValueCppHandler::Merge(from.value(), &value_);
243 set_has_value();
244 }
245 }
246 }
247
248 void Clear() {
249 KeyCppHandler::Clear(&key_);
250 ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
251 clear_has_key();
252 clear_has_value();
253 }
254
255 void InitAsDefaultInstance() {
256 KeyCppHandler::AssignDefaultValue(&key_);
257 ValueCppHandler::AssignDefaultValue(&value_);
258 }
259
260 Arena* GetArena() const {
261 return GetArenaNoVirtual();
262 }
263
264 // Create a MapEntryLite for given key and value from google::protobuf::Map in
265 // serialization. This function is only called when value is enum. Enum is
266 // treated differently because its type in MapEntry is int and its type in
267 // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
268 static MapEntryLite* EnumWrap(const Key& key, const Value value,
269 Arena* arena) {
270 return Arena::Create<MapEnumEntryWrapper<
271 Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
272 arena, key, value, arena);
273 }
274
275 // Like above, but for all the other types. This avoids value copy to create
276 // MapEntryLite from google::protobuf::Map in serialization.
277 static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
278 return Arena::Create<MapEntryWrapper<Key, Value, kKeyFieldType,
279 kValueFieldType, default_enum_value> >(
280 arena, key, value, arena);
281 }
282
283 protected:
284 void set_has_key() { _has_bits_[0] |= 0x00000001u; }
285 bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
286 void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
287 void set_has_value() { _has_bits_[0] |= 0x00000002u; }
288 bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
289 void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
290
291 private:
292 // Serializing a generated message containing map field involves serializing
293 // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
294 // after serialization should be the same as that of a MapEntry message
295 // containing the same key and value inside it. However, google::protobuf::Map doesn't
296 // store key and value as MapEntry message, which disables us to use existing
297 // code to serialize message. In order to use existing code to serialize
298 // message, we need to construct a MapEntry from key-value pair. But it
299 // involves copy of key and value to construct a MapEntry. In order to avoid
300 // this copy in constructing a MapEntry, we need the following class which
301 // only takes references of given key and value.
302 template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
303 WireFormatLite::FieldType v_wire_type, int default_enum>
304 class LIBPROTOBUF_EXPORT MapEntryWrapper
305 : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
306 typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
307 typedef typename Base::KeyCppType KeyCppType;
308 typedef typename Base::ValCppType ValCppType;
309
310 public:
311 MapEntryWrapper(const K& key, const V& value, Arena* arena)
312 : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
313 key_(key),
314 value_(value) {
315 Base::set_has_key();
316 Base::set_has_value();
317 }
318 inline const KeyCppType& key() const { return key_; }
319 inline const ValCppType& value() const { return value_; }
320
321 private:
322 const Key& key_;
323 const Value& value_;
324
325 friend class ::google::protobuf::Arena;
326 typedef void DestructorSkippable_;
327 };
328
329 // Like above, but for enum value only, which stores value instead of
330 // reference of value field inside. This is needed because the type of value
331 // field in constructor is an enum, while we need to store it as an int. If we
332 // initialize a reference to int with a reference to enum, compiler will
333 // generate a temporary int from enum and initialize the reference to int with
334 // the temporary.
335 template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
336 WireFormatLite::FieldType v_wire_type, int default_enum>
337 class LIBPROTOBUF_EXPORT MapEnumEntryWrapper
338 : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
339 typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
340 typedef typename Base::KeyCppType KeyCppType;
341 typedef typename Base::ValCppType ValCppType;
342
343 public:
344 MapEnumEntryWrapper(const K& key, const V& value, Arena* arena)
345 : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
346 key_(key),
347 value_(value) {
348 Base::set_has_key();
349 Base::set_has_value();
350 }
351 inline const KeyCppType& key() const { return key_; }
352 inline const ValCppType& value() const { return value_; }
353
354 private:
355 const KeyCppType& key_;
356 const ValCppType value_;
357
358 friend class ::google::protobuf::Arena;
359 typedef void DestructorSkippable_;
360 };
361
362 MapEntryLite() : arena_(NULL) {
363 KeyCppHandler::Initialize(&key_, NULL);
364 ValueCppHandler::InitializeMaybeByDefaultEnum(
365 &value_, default_enum_value, NULL);
366 _has_bits_[0] = 0;
367 }
368
369 explicit MapEntryLite(Arena* arena)
370 : arena_(arena) {
371 KeyCppHandler::Initialize(&key_, arena);
372 ValueCppHandler::InitializeMaybeByDefaultEnum(
373 &value_, default_enum_value, arena);
374 _has_bits_[0] = 0;
375 }
376
377 inline Arena* GetArenaNoVirtual() const {
378 return arena_;
379 }
380
381 void set_default_instance(MapEntryLite* default_instance) {
382 default_instance_ = default_instance;
383 }
384
385 MapEntryLite* default_instance_ = NULL;
386
387 KeyBase key_;
388 ValueBase value_;
389 Arena* arena_;
390 uint32 _has_bits_[1];
391
392 friend class ::google::protobuf::Arena;
393 typedef void InternalArenaConstructable_;
394 typedef void DestructorSkippable_;
395 template <typename K, typename V, WireFormatLite::FieldType,
396 WireFormatLite::FieldType, int>
397 friend class LIBPROTOBUF_EXPORT internal::MapEntry;
398 template <typename K, typename V, WireFormatLite::FieldType,
399 WireFormatLite::FieldType, int>
400 friend class LIBPROTOBUF_EXPORT internal::MapFieldLite;
401
402 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
403};
404
405} // namespace internal
406} // namespace protobuf
407
408} // namespace google
409#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__