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 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <google/protobuf/generated_message_util.h>
36
37 #include <limits>
38 #include <vector>
39
40 #include <google/protobuf/io/coded_stream_inl.h>
41 #include <google/protobuf/io/coded_stream.h>
42 #include <google/protobuf/arenastring.h>
43 #include <google/protobuf/extension_set.h>
44 #include <google/protobuf/message_lite.h>
45 #include <google/protobuf/metadata_lite.h>
46 #include <google/protobuf/stubs/port.h>
47 #include <google/protobuf/repeated_field.h>
48 #include <google/protobuf/wire_format_lite.h>
49 #include <google/protobuf/wire_format_lite_inl.h>
50
51 namespace google {
52
53 namespace protobuf {
54 namespace internal {
55
56
Infinity()57 double Infinity() {
58 return std::numeric_limits<double>::infinity();
59 }
NaN()60 double NaN() {
61 return std::numeric_limits<double>::quiet_NaN();
62 }
63
64 ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
65 GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
66
DeleteEmptyString()67 void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
68
InitEmptyString()69 void InitEmptyString() {
70 fixed_address_empty_string.DefaultConstruct();
71 OnShutdown(&DeleteEmptyString);
72 }
73
StringSpaceUsedExcludingSelfLong(const string & str)74 size_t StringSpaceUsedExcludingSelfLong(const string& str) {
75 const void* start = &str;
76 const void* end = &str + 1;
77 if (start <= str.data() && str.data() < end) {
78 // The string's data is stored inside the string object itself.
79 return 0;
80 } else {
81 return str.capacity();
82 }
83 }
84
85
86
InitProtobufDefaults()87 void InitProtobufDefaults() {
88 GetEmptyString();
89 }
90
91 template <typename T>
Get(const void * ptr)92 const T& Get(const void* ptr) {
93 return *static_cast<const T*>(ptr);
94 }
95
96 // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
97 // WireFormatLite has a very inconvenient interface with respect to template
98 // meta-programming. This class wraps the different named functions into
99 // a single Serialize / SerializeToArray interface.
100 template <int type>
101 struct PrimitiveTypeHelper;
102
103 template <>
104 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
105 typedef bool Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper106 static void Serialize(const void* ptr,
107 ::google::protobuf::io::CodedOutputStream* output) {
108 WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
109 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper110 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
111 return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
112 }
113 };
114
115 template <>
116 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
117 typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper118 static void Serialize(const void* ptr,
119 ::google::protobuf::io::CodedOutputStream* output) {
120 WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
121 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper122 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
123 return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
124 }
125 };
126
127 template <>
128 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
129 typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper130 static void Serialize(const void* ptr,
131 ::google::protobuf::io::CodedOutputStream* output) {
132 WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
133 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper134 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
135 return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
136 }
137 };
138
139 template <>
140 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
141 typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper142 static void Serialize(const void* ptr,
143 ::google::protobuf::io::CodedOutputStream* output) {
144 WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
145 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper146 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
147 return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
148 }
149 };
150 template <>
151 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
152 typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper153 static void Serialize(const void* ptr,
154 ::google::protobuf::io::CodedOutputStream* output) {
155 WireFormatLite::WriteInt64NoTag(Get<int64>(ptr), output);
156 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper157 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
158 return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
159 }
160 };
161
162 template <>
163 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
164 typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper165 static void Serialize(const void* ptr,
166 ::google::protobuf::io::CodedOutputStream* output) {
167 WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
168 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper169 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
170 return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
171 }
172 };
173 template <>
174 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
175 typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper176 static void Serialize(const void* ptr,
177 ::google::protobuf::io::CodedOutputStream* output) {
178 WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
179 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper180 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
181 return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
182 }
183 };
184
185 template <>
186 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
187 typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper188 static void Serialize(const void* ptr,
189 ::google::protobuf::io::CodedOutputStream* output) {
190 WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
191 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper192 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
193 return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
194 }
195 };
196
197 template <>
198 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
199 typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper200 static void Serialize(const void* ptr,
201 ::google::protobuf::io::CodedOutputStream* output) {
202 WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
203 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper204 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
205 return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
206 }
207 };
208
209 template <>
210 struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
211 : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
212
213 template <>
214 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
215 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
216 typedef int32 Type;
217 };
218 template <>
219 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
220 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
221 typedef int64 Type;
222 };
223 template <>
224 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
225 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
226 typedef float Type;
227 };
228 template <>
229 struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
230 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
231 typedef double Type;
232 };
233
234 template <>
235 struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
236 typedef string Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper237 static void Serialize(const void* ptr,
238 ::google::protobuf::io::CodedOutputStream* output) {
239 const Type& value = *static_cast<const Type*>(ptr);
240 output->WriteVarint32(value.size());
241 output->WriteRawMaybeAliased(value.data(), value.size());
242 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper243 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
244 const Type& value = *static_cast<const Type*>(ptr);
245 return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
246 }
247 };
248
249 template <>
250 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
251 : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
252
253
254 // We want to serialize to both CodedOutputStream and directly into byte arrays
255 // without duplicating the code. In fact we might want extra output channels in
256 // the future.
257 template <typename O, int type>
258 struct OutputHelper;
259
260 template <int type, typename O>
SerializeTo(const void * ptr,O * output)261 void SerializeTo(const void* ptr, O* output) {
262 OutputHelper<O, type>::Serialize(ptr, output);
263 }
264
265 template <typename O>
WriteTagTo(uint32 tag,O * output)266 void WriteTagTo(uint32 tag, O* output) {
267 SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
268 }
269
270 template <typename O>
WriteLengthTo(uint32 length,O * output)271 void WriteLengthTo(uint32 length, O* output) {
272 SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
273 }
274
275 // Specialization for coded output stream
276 template <int type>
277 struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> {
Serializegoogle::protobuf::internal::OutputHelper278 static void Serialize(const void* ptr,
279 ::google::protobuf::io::CodedOutputStream* output) {
280 PrimitiveTypeHelper<type>::Serialize(ptr, output);
281 }
282 };
283
284 // Specialization for writing into a plain array
285 struct ArrayOutput {
286 uint8* ptr;
287 bool is_deterministic;
288 };
289
290 template <int type>
291 struct OutputHelper<ArrayOutput, type> {
Serializegoogle::protobuf::internal::OutputHelper292 static void Serialize(const void* ptr, ArrayOutput* output) {
293 output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
294 }
295 };
296
SerializeMessageNoTable(const MessageLite * msg,::google::protobuf::io::CodedOutputStream * output)297 void SerializeMessageNoTable(const MessageLite* msg,
298 ::google::protobuf::io::CodedOutputStream* output) {
299 msg->SerializeWithCachedSizes(output);
300 }
301
SerializeMessageNoTable(const MessageLite * msg,ArrayOutput * output)302 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
303 output->ptr = msg->InternalSerializeWithCachedSizesToArray(
304 output->is_deterministic, output->ptr);
305 }
306
307 // Helper to branch to fast path if possible
SerializeMessageDispatch(const::google::protobuf::MessageLite & msg,const FieldMetadata * field_table,int num_fields,int32 cached_size,::google::protobuf::io::CodedOutputStream * output)308 void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
309 const FieldMetadata* field_table, int num_fields,
310 int32 cached_size,
311 ::google::protobuf::io::CodedOutputStream* output) {
312 const uint8* base = reinterpret_cast<const uint8*>(&msg);
313 // Try the fast path
314 uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
315 if (ptr) {
316 // We use virtual dispatch to enable dedicated generated code for the
317 // fast path.
318 msg.InternalSerializeWithCachedSizesToArray(
319 output->IsSerializationDeterministic(), ptr);
320 return;
321 }
322 SerializeInternal(base, field_table, num_fields, output);
323 }
324
325 // Helper to branch to fast path if possible
SerializeMessageDispatch(const::google::protobuf::MessageLite & msg,const FieldMetadata * field_table,int num_fields,int32 cached_size,ArrayOutput * output)326 void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
327 const FieldMetadata* field_table, int num_fields,
328 int32 cached_size, ArrayOutput* output) {
329 const uint8* base = reinterpret_cast<const uint8*>(&msg);
330 output->ptr = SerializeInternalToArray(base, field_table, num_fields,
331 output->is_deterministic, output->ptr);
332 }
333
334 // Serializing messages is special as it's not a primitive type and needs an
335 // explicit overload for each output type.
336 template <typename O>
SerializeMessageTo(const MessageLite * msg,const void * table_ptr,O * output)337 void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
338 O* output) {
339 const SerializationTable* table =
340 static_cast<const SerializationTable*>(table_ptr);
341 if (!table) {
342 // Proto1
343 WriteLengthTo(msg->GetCachedSize(), output);
344 SerializeMessageNoTable(msg, output);
345 return;
346 }
347 const FieldMetadata* field_table = table->field_table;
348 const uint8* base = reinterpret_cast<const uint8*>(msg);
349 int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
350 WriteLengthTo(cached_size, output);
351 int num_fields = table->num_fields - 1;
352 SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
353 output);
354 }
355
356 // Almost the same as above only it doesn't output the length field.
357 template <typename O>
SerializeGroupTo(const MessageLite * msg,const void * table_ptr,O * output)358 void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
359 O* output) {
360 const SerializationTable* table =
361 static_cast<const SerializationTable*>(table_ptr);
362 if (!table) {
363 // Proto1
364 SerializeMessageNoTable(msg, output);
365 return;
366 }
367 const FieldMetadata* field_table = table->field_table;
368 const uint8* base = reinterpret_cast<const uint8*>(msg);
369 int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
370 int num_fields = table->num_fields - 1;
371 SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
372 output);
373 }
374
375 template <int type>
376 struct SingularFieldHelper {
377 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper378 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
379 WriteTagTo(md.tag, output);
380 SerializeTo<type>(field, output);
381 }
382 };
383
384 template <>
385 struct SingularFieldHelper<WireFormatLite::TYPE_STRING> {
386 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper387 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
388 WriteTagTo(md.tag, output);
389 SerializeTo<WireFormatLite::TYPE_STRING>(&Get<ArenaStringPtr>(field).Get(),
390 output);
391 }
392 };
393
394 template <>
395 struct SingularFieldHelper<WireFormatLite::TYPE_BYTES>
396 : SingularFieldHelper<WireFormatLite::TYPE_STRING> {};
397
398 template <>
399 struct SingularFieldHelper<WireFormatLite::TYPE_GROUP> {
400 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper401 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
402 WriteTagTo(md.tag, output);
403 SerializeGroupTo(Get<const MessageLite*>(field),
404 static_cast<const SerializationTable*>(md.ptr), output);
405 WriteTagTo(md.tag + 1, output);
406 }
407 };
408
409 template <>
410 struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
411 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper412 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
413 WriteTagTo(md.tag, output);
414 SerializeMessageTo(Get<const MessageLite*>(field),
415 static_cast<const SerializationTable*>(md.ptr), output);
416 }
417 };
418
419 template <int type>
420 struct RepeatedFieldHelper {
421 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper422 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
423 typedef typename PrimitiveTypeHelper<type>::Type T;
424 const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
425 for (int i = 0; i < array.size(); i++) {
426 WriteTagTo(md.tag, output);
427 SerializeTo<type>(&array[i], output);
428 }
429 }
430 };
431
432 // We need to use a helper class to get access to the private members
433 class AccessorHelper {
434 public:
Size(const RepeatedPtrFieldBase & x)435 static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
Get(const RepeatedPtrFieldBase & x,int idx)436 static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
437 return x.raw_data()[idx];
438 }
439 };
440
441 template <>
442 struct RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {
443 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper444 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
445 const internal::RepeatedPtrFieldBase& array =
446 Get<internal::RepeatedPtrFieldBase>(field);
447 for (int i = 0; i < AccessorHelper::Size(array); i++) {
448 WriteTagTo(md.tag, output);
449 SerializeTo<WireFormatLite::TYPE_STRING>(AccessorHelper::Get(array, i),
450 output);
451 }
452 }
453 };
454
455 template <>
456 struct RepeatedFieldHelper<WireFormatLite::TYPE_BYTES>
457 : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
458
459 template <>
460 struct RepeatedFieldHelper<WireFormatLite::TYPE_GROUP> {
461 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper462 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
463 const internal::RepeatedPtrFieldBase& array =
464 Get<internal::RepeatedPtrFieldBase>(field);
465 for (int i = 0; i < AccessorHelper::Size(array); i++) {
466 WriteTagTo(md.tag, output);
467 SerializeGroupTo(
468 static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
469 static_cast<const SerializationTable*>(md.ptr), output);
470 WriteTagTo(md.tag + 1, output);
471 }
472 }
473 };
474
475 template <>
476 struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
477 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper478 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
479 const internal::RepeatedPtrFieldBase& array =
480 Get<internal::RepeatedPtrFieldBase>(field);
481 for (int i = 0; i < AccessorHelper::Size(array); i++) {
482 WriteTagTo(md.tag, output);
483 SerializeMessageTo(
484 static_cast<const MessageLite*>(AccessorHelper::Get(array, i)), md.ptr,
485 output);
486 }
487 }
488 };
489
490
491 template <int type>
492 struct PackedFieldHelper {
493 template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper494 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
495 typedef typename PrimitiveTypeHelper<type>::Type T;
496 const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
497 if (array.empty()) return;
498 WriteTagTo(md.tag, output);
499 int cached_size =
500 Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
501 WriteLengthTo(cached_size, output);
502 for (int i = 0; i < array.size(); i++) {
503 SerializeTo<type>(&array[i], output);
504 }
505 }
506 };
507
508 template <>
509 struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
510 template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper511 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
512 GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
513 << md.type;
514 }
515 };
516
517 template <>
518 struct PackedFieldHelper<WireFormatLite::TYPE_BYTES>
519 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
520 template <>
521 struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
522 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
523 template <>
524 struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
525 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
526
527 template <int type>
528 struct OneOfFieldHelper {
529 template <typename O>
Serializegoogle::protobuf::internal::OneOfFieldHelper530 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
531 SingularFieldHelper<type>::Serialize(field, md, output);
532 }
533 };
534
535
SerializeNotImplemented(int field)536 void SerializeNotImplemented(int field) {
537 GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
538 }
539
540 // When switching to c++11 we should make these constexpr functions
541 #define SERIALIZE_TABLE_OP(type, type_class) \
542 ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
543
CalculateType(int type,FieldMetadata::FieldTypeClass type_class)544 int FieldMetadata::CalculateType(int type,
545 FieldMetadata::FieldTypeClass type_class) {
546 return SERIALIZE_TABLE_OP(type, type_class);
547 }
548
549 template <int type>
IsNull(const void * ptr)550 bool IsNull(const void* ptr) {
551 return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
552 0;
553 }
554
555 template <>
IsNull(const void * ptr)556 bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
557 return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
558 }
559
560 template <>
IsNull(const void * ptr)561 bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
562 return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
563 }
564
565 template <>
IsNull(const void * ptr)566 bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
567 return Get<const MessageLite*>(ptr) == NULL;
568 }
569
570 template <>
IsNull(const void * ptr)571 bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
572 return Get<const MessageLite*>(ptr) == NULL;
573 }
574
575
576 #define SERIALIZERS_FOR_TYPE(type) \
577 case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \
578 if (!IsPresent(base, field_metadata.has_offset)) continue; \
579 SingularFieldHelper<type>::Serialize(ptr, field_metadata, output); \
580 break; \
581 case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence): \
582 if (IsNull<type>(ptr)) continue; \
583 SingularFieldHelper<type>::Serialize(ptr, field_metadata, output); \
584 break; \
585 case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated): \
586 RepeatedFieldHelper<type>::Serialize(ptr, field_metadata, output); \
587 break; \
588 case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked): \
589 PackedFieldHelper<type>::Serialize(ptr, field_metadata, output); \
590 break; \
591 case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf): \
592 if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \
593 continue; \
594 OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output); \
595 break
596
SerializeInternal(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,::google::protobuf::io::CodedOutputStream * output)597 void SerializeInternal(const uint8* base,
598 const FieldMetadata* field_metadata_table,
599 int32 num_fields,
600 ::google::protobuf::io::CodedOutputStream* output) {
601 for (int i = 0; i < num_fields; i++) {
602 const FieldMetadata& field_metadata = field_metadata_table[i];
603 const uint8* ptr = base + field_metadata.offset;
604 switch (field_metadata.type) {
605 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
606 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
607 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
608 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
609 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
610 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
611 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
612 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
613 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
614 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
615 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
616 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
617 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
618 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
619 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
620 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
621 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
622 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
623
624 // Special cases
625 case FieldMetadata::kSpecial:
626 reinterpret_cast<SpecialSerializer>(
627 const_cast<void*>(field_metadata.ptr))(
628 base, field_metadata.offset, field_metadata.tag,
629 field_metadata.has_offset, output);
630 break;
631 default:
632 // __builtin_unreachable()
633 SerializeNotImplemented(field_metadata.type);
634 }
635 }
636 }
637
SerializeInternalToArray(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,bool is_deterministic,uint8 * buffer)638 uint8* SerializeInternalToArray(const uint8* base,
639 const FieldMetadata* field_metadata_table,
640 int32 num_fields, bool is_deterministic,
641 uint8* buffer) {
642 ArrayOutput array_output = {buffer, is_deterministic};
643 ArrayOutput* output = &array_output;
644 for (int i = 0; i < num_fields; i++) {
645 const FieldMetadata& field_metadata = field_metadata_table[i];
646 const uint8* ptr = base + field_metadata.offset;
647 switch (field_metadata.type) {
648 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
649 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
650 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
651 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
652 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
653 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
654 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
655 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
656 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
657 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
658 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
659 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
660 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
661 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
662 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
663 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
664 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
665 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
666 // Special cases
667 case FieldMetadata::kSpecial: {
668 io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
669 io::CodedOutputStream output(&array_stream);
670 output.SetSerializationDeterministic(is_deterministic);
671 reinterpret_cast<SpecialSerializer>(
672 const_cast<void*>(field_metadata.ptr))(
673 base, field_metadata.offset, field_metadata.tag,
674 field_metadata.has_offset, &output);
675 array_output.ptr += output.ByteCount();
676 } break;
677 default:
678 // __builtin_unreachable()
679 SerializeNotImplemented(field_metadata.type);
680 }
681 }
682 return array_output.ptr;
683 }
684 #undef SERIALIZERS_FOR_TYPE
685
ExtensionSerializer(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,::google::protobuf::io::CodedOutputStream * output)686 void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
687 uint32 has_offset,
688 ::google::protobuf::io::CodedOutputStream* output) {
689 reinterpret_cast<const ExtensionSet*>(ptr + offset)
690 ->SerializeWithCachedSizes(tag, has_offset, output);
691 }
692
UnknownFieldSerializerLite(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,::google::protobuf::io::CodedOutputStream * output)693 void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
694 uint32 has_offset,
695 ::google::protobuf::io::CodedOutputStream* output) {
696 output->WriteString(
697 reinterpret_cast<const InternalMetadataWithArenaLite*>(ptr + offset)
698 ->unknown_fields());
699 }
700
DuplicateIfNonNullInternal(MessageLite * message,Arena * arena)701 MessageLite* DuplicateIfNonNullInternal(MessageLite* message, Arena* arena) {
702 if (message) {
703 MessageLite* ret = message->New(arena);
704 ret->CheckTypeAndMergeFrom(*message);
705 return ret;
706 } else {
707 return NULL;
708 }
709 }
710
711 // Returns a message owned by this Arena. This may require Own()ing or
712 // duplicating the message.
GetOwnedMessageInternal(Arena * message_arena,MessageLite * submessage,Arena * submessage_arena)713 MessageLite* GetOwnedMessageInternal(Arena* message_arena,
714 MessageLite* submessage,
715 Arena* submessage_arena) {
716 GOOGLE_DCHECK(submessage->GetArena() == submessage_arena);
717 GOOGLE_DCHECK(message_arena != submessage_arena);
718 if (message_arena != NULL && submessage_arena == NULL) {
719 message_arena->Own(submessage);
720 return submessage;
721 } else {
722 MessageLite* ret = submessage->New(message_arena);
723 ret->CheckTypeAndMergeFrom(*submessage);
724 return ret;
725 }
726 }
727
728 } // namespace internal
729 } // namespace protobuf
730 } // namespace google
731