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
39 #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
40 // We're only using this as a standard way for getting the thread id.
41 // We're not using any thread functionality.
42 #include <thread> // NOLINT
43 #endif // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
44
45 #include <vector>
46
47 #include <google/protobuf/io/coded_stream.h>
48 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
49 #include <google/protobuf/arenastring.h>
50 #include <google/protobuf/extension_set.h>
51 #include <google/protobuf/generated_message_table_driven.h>
52 #include <google/protobuf/message_lite.h>
53 #include <google/protobuf/metadata_lite.h>
54 #include <google/protobuf/stubs/mutex.h>
55 #include <google/protobuf/port_def.inc>
56 #include <google/protobuf/repeated_field.h>
57 #include <google/protobuf/wire_format_lite.h>
58
59
60 namespace google {
61 namespace protobuf {
62 namespace internal {
63
DestroyMessage(const void * message)64 void DestroyMessage(const void* message) {
65 static_cast<const MessageLite*>(message)->~MessageLite();
66 }
DestroyString(const void * s)67 void DestroyString(const void* s) {
68 static_cast<const std::string*>(s)->~string();
69 }
70
71 ExplicitlyConstructed<std::string> fixed_address_empty_string;
72
73
InitProtobufDefaultsImpl()74 static bool InitProtobufDefaultsImpl() {
75 fixed_address_empty_string.DefaultConstruct();
76 OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
77 return true;
78 }
79
InitProtobufDefaults()80 void InitProtobufDefaults() {
81 static bool is_inited = InitProtobufDefaultsImpl();
82 (void)is_inited;
83 }
84
StringSpaceUsedExcludingSelfLong(const std::string & str)85 size_t StringSpaceUsedExcludingSelfLong(const std::string& str) {
86 const void* start = &str;
87 const void* end = &str + 1;
88 if (start <= str.data() && str.data() < end) {
89 // The string's data is stored inside the string object itself.
90 return 0;
91 } else {
92 return str.capacity();
93 }
94 }
95
96 template <typename T>
Get(const void * ptr)97 const T& Get(const void* ptr) {
98 return *static_cast<const T*>(ptr);
99 }
100
101 // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
102 // WireFormatLite has a very inconvenient interface with respect to template
103 // meta-programming. This class wraps the different named functions into
104 // a single Serialize / SerializeToArray interface.
105 template <int type>
106 struct PrimitiveTypeHelper;
107
108 template <>
109 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
110 typedef bool Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper111 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
112 WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
113 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper114 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
115 return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
116 }
117 };
118
119 template <>
120 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
121 typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper122 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
123 WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
124 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper125 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
126 return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
127 }
128 };
129
130 template <>
131 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
132 typedef int32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper133 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
134 WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
135 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper136 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
137 return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
138 }
139 };
140
141 template <>
142 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
143 typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper144 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
145 WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
146 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper147 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
148 return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
149 }
150 };
151 template <>
152 struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
153 typedef int64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper154 static void Serialize(const void* ptr, 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, io::CodedOutputStream* output) {
166 WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
167 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper168 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
169 return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
170 }
171 };
172 template <>
173 struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
174 typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper175 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
176 WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
177 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper178 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
179 return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
180 }
181 };
182
183 template <>
184 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
185 typedef uint32 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper186 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
187 WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
188 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper189 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
190 return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
191 }
192 };
193
194 template <>
195 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
196 typedef uint64 Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper197 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
198 WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
199 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper200 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
201 return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
202 }
203 };
204
205 template <>
206 struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
207 : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
208
209 template <>
210 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
211 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
212 typedef int32 Type;
213 };
214 template <>
215 struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
216 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
217 typedef int64 Type;
218 };
219 template <>
220 struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
221 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
222 typedef float Type;
223 };
224 template <>
225 struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
226 : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
227 typedef double Type;
228 };
229
230 template <>
231 struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
232 typedef std::string Type;
Serializegoogle::protobuf::internal::PrimitiveTypeHelper233 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
234 const Type& value = *static_cast<const Type*>(ptr);
235 output->WriteVarint32(value.size());
236 output->WriteRawMaybeAliased(value.data(), value.size());
237 }
SerializeToArraygoogle::protobuf::internal::PrimitiveTypeHelper238 static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
239 const Type& value = *static_cast<const Type*>(ptr);
240 return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
241 }
242 };
243
244 template <>
245 struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
246 : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
247
248
249 template <>
250 struct PrimitiveTypeHelper<FieldMetadata::kInlinedType>
251 : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
252
253 // We want to serialize to both CodedOutputStream and directly into byte arrays
254 // without duplicating the code. In fact we might want extra output channels in
255 // the future.
256 template <typename O, int type>
257 struct OutputHelper;
258
259 template <int type, typename O>
SerializeTo(const void * ptr,O * output)260 void SerializeTo(const void* ptr, O* output) {
261 OutputHelper<O, type>::Serialize(ptr, output);
262 }
263
264 template <typename O>
WriteTagTo(uint32 tag,O * output)265 void WriteTagTo(uint32 tag, O* output) {
266 SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
267 }
268
269 template <typename O>
WriteLengthTo(uint32 length,O * output)270 void WriteLengthTo(uint32 length, O* output) {
271 SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
272 }
273
274 // Specialization for coded output stream
275 template <int type>
276 struct OutputHelper<io::CodedOutputStream, type> {
Serializegoogle::protobuf::internal::OutputHelper277 static void Serialize(const void* ptr, io::CodedOutputStream* output) {
278 PrimitiveTypeHelper<type>::Serialize(ptr, output);
279 }
280 };
281
282 // Specialization for writing into a plain array
283 struct ArrayOutput {
284 uint8* ptr;
285 bool is_deterministic;
286 };
287
288 template <int type>
289 struct OutputHelper<ArrayOutput, type> {
Serializegoogle::protobuf::internal::OutputHelper290 static void Serialize(const void* ptr, ArrayOutput* output) {
291 output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
292 }
293 };
294
SerializeMessageNoTable(const MessageLite * msg,io::CodedOutputStream * output)295 void SerializeMessageNoTable(const MessageLite* msg,
296 io::CodedOutputStream* output) {
297 msg->SerializeWithCachedSizes(output);
298 }
299
SerializeMessageNoTable(const MessageLite * msg,ArrayOutput * output)300 void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
301 io::ArrayOutputStream array_stream(output->ptr, INT_MAX);
302 io::CodedOutputStream o(&array_stream);
303 o.SetSerializationDeterministic(output->is_deterministic);
304 msg->SerializeWithCachedSizes(&o);
305 output->ptr += o.ByteCount();
306 }
307
308 // Helper to branch to fast path if possible
SerializeMessageDispatch(const MessageLite & msg,const FieldMetadata * field_table,int num_fields,int32 cached_size,io::CodedOutputStream * output)309 void SerializeMessageDispatch(const MessageLite& msg,
310 const FieldMetadata* field_table, int num_fields,
311 int32 cached_size,
312 io::CodedOutputStream* output) {
313 const uint8* base = reinterpret_cast<const uint8*>(&msg);
314 SerializeInternal(base, field_table, num_fields, output);
315 }
316
317 // Helper to branch to fast path if possible
SerializeMessageDispatch(const MessageLite & msg,const FieldMetadata * field_table,int num_fields,int32 cached_size,ArrayOutput * output)318 void SerializeMessageDispatch(const MessageLite& msg,
319 const FieldMetadata* field_table, int num_fields,
320 int32 cached_size, ArrayOutput* output) {
321 const uint8* base = reinterpret_cast<const uint8*>(&msg);
322 output->ptr = SerializeInternalToArray(base, field_table, num_fields,
323 output->is_deterministic, output->ptr);
324 }
325
326 // Serializing messages is special as it's not a primitive type and needs an
327 // explicit overload for each output type.
328 template <typename O>
SerializeMessageTo(const MessageLite * msg,const void * table_ptr,O * output)329 void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
330 O* output) {
331 const SerializationTable* table =
332 static_cast<const SerializationTable*>(table_ptr);
333 if (!table) {
334 // Proto1
335 WriteLengthTo(msg->GetCachedSize(), output);
336 SerializeMessageNoTable(msg, output);
337 return;
338 }
339 const FieldMetadata* field_table = table->field_table;
340 const uint8* base = reinterpret_cast<const uint8*>(msg);
341 int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
342 WriteLengthTo(cached_size, output);
343 int num_fields = table->num_fields - 1;
344 SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
345 output);
346 }
347
348 // Almost the same as above only it doesn't output the length field.
349 template <typename O>
SerializeGroupTo(const MessageLite * msg,const void * table_ptr,O * output)350 void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
351 O* output) {
352 const SerializationTable* table =
353 static_cast<const SerializationTable*>(table_ptr);
354 if (!table) {
355 // Proto1
356 SerializeMessageNoTable(msg, output);
357 return;
358 }
359 const FieldMetadata* field_table = table->field_table;
360 const uint8* base = reinterpret_cast<const uint8*>(msg);
361 int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
362 int num_fields = table->num_fields - 1;
363 SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
364 output);
365 }
366
367 template <int type>
368 struct SingularFieldHelper {
369 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper370 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
371 WriteTagTo(md.tag, output);
372 SerializeTo<type>(field, output);
373 }
374 };
375
376 template <>
377 struct SingularFieldHelper<WireFormatLite::TYPE_STRING> {
378 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper379 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
380 WriteTagTo(md.tag, output);
381 SerializeTo<WireFormatLite::TYPE_STRING>(&Get<ArenaStringPtr>(field).Get(),
382 output);
383 }
384 };
385
386 template <>
387 struct SingularFieldHelper<WireFormatLite::TYPE_BYTES>
388 : SingularFieldHelper<WireFormatLite::TYPE_STRING> {};
389
390 template <>
391 struct SingularFieldHelper<WireFormatLite::TYPE_GROUP> {
392 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper393 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
394 WriteTagTo(md.tag, output);
395 SerializeGroupTo(Get<const MessageLite*>(field),
396 static_cast<const SerializationTable*>(md.ptr), output);
397 WriteTagTo(md.tag + 1, output);
398 }
399 };
400
401 template <>
402 struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
403 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper404 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
405 WriteTagTo(md.tag, output);
406 SerializeMessageTo(Get<const MessageLite*>(field),
407 static_cast<const SerializationTable*>(md.ptr), output);
408 }
409 };
410
411 template <>
412 struct SingularFieldHelper<FieldMetadata::kInlinedType> {
413 template <typename O>
Serializegoogle::protobuf::internal::SingularFieldHelper414 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
415 WriteTagTo(md.tag, output);
416 SerializeTo<FieldMetadata::kInlinedType>(&Get<std::string>(field), output);
417 }
418 };
419
420 template <int type>
421 struct RepeatedFieldHelper {
422 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper423 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
424 typedef typename PrimitiveTypeHelper<type>::Type T;
425 const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
426 for (int i = 0; i < array.size(); i++) {
427 WriteTagTo(md.tag, output);
428 SerializeTo<type>(&array[i], output);
429 }
430 }
431 };
432
433 // We need to use a helper class to get access to the private members
434 class AccessorHelper {
435 public:
Size(const RepeatedPtrFieldBase & x)436 static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
Get(const RepeatedPtrFieldBase & x,int idx)437 static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
438 return x.raw_data()[idx];
439 }
440 };
441
442 template <>
443 struct RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {
444 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper445 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
446 const internal::RepeatedPtrFieldBase& array =
447 Get<internal::RepeatedPtrFieldBase>(field);
448 for (int i = 0; i < AccessorHelper::Size(array); i++) {
449 WriteTagTo(md.tag, output);
450 SerializeTo<WireFormatLite::TYPE_STRING>(AccessorHelper::Get(array, i),
451 output);
452 }
453 }
454 };
455
456 template <>
457 struct RepeatedFieldHelper<WireFormatLite::TYPE_BYTES>
458 : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
459
460 template <>
461 struct RepeatedFieldHelper<WireFormatLite::TYPE_GROUP> {
462 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper463 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
464 const internal::RepeatedPtrFieldBase& array =
465 Get<internal::RepeatedPtrFieldBase>(field);
466 for (int i = 0; i < AccessorHelper::Size(array); i++) {
467 WriteTagTo(md.tag, output);
468 SerializeGroupTo(
469 static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
470 static_cast<const SerializationTable*>(md.ptr), output);
471 WriteTagTo(md.tag + 1, output);
472 }
473 }
474 };
475
476 template <>
477 struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
478 template <typename O>
Serializegoogle::protobuf::internal::RepeatedFieldHelper479 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
480 const internal::RepeatedPtrFieldBase& array =
481 Get<internal::RepeatedPtrFieldBase>(field);
482 for (int i = 0; i < AccessorHelper::Size(array); i++) {
483 WriteTagTo(md.tag, output);
484 SerializeMessageTo(
485 static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
486 md.ptr, output);
487 }
488 }
489 };
490
491
492 template <>
493 struct RepeatedFieldHelper<FieldMetadata::kInlinedType>
494 : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
495
496 template <int type>
497 struct PackedFieldHelper {
498 template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper499 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
500 typedef typename PrimitiveTypeHelper<type>::Type T;
501 const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
502 if (array.empty()) return;
503 WriteTagTo(md.tag, output);
504 int cached_size =
505 Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
506 WriteLengthTo(cached_size, output);
507 for (int i = 0; i < array.size(); i++) {
508 SerializeTo<type>(&array[i], output);
509 }
510 }
511 };
512
513 template <>
514 struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
515 template <typename O>
Serializegoogle::protobuf::internal::PackedFieldHelper516 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
517 GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
518 << md.type;
519 }
520 };
521
522 template <>
523 struct PackedFieldHelper<WireFormatLite::TYPE_BYTES>
524 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
525 template <>
526 struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
527 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
528 template <>
529 struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
530 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
531 template <>
532 struct PackedFieldHelper<FieldMetadata::kInlinedType>
533 : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
534
535 template <int type>
536 struct OneOfFieldHelper {
537 template <typename O>
Serializegoogle::protobuf::internal::OneOfFieldHelper538 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
539 SingularFieldHelper<type>::Serialize(field, md, output);
540 }
541 };
542
543
544 template <>
545 struct OneOfFieldHelper<FieldMetadata::kInlinedType> {
546 template <typename O>
Serializegoogle::protobuf::internal::OneOfFieldHelper547 static void Serialize(const void* field, const FieldMetadata& md, O* output) {
548 SingularFieldHelper<FieldMetadata::kInlinedType>::Serialize(
549 Get<const std::string*>(field), md, output);
550 }
551 };
552
SerializeNotImplemented(int field)553 void SerializeNotImplemented(int field) {
554 GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
555 }
556
557 // When switching to c++11 we should make these constexpr functions
558 #define SERIALIZE_TABLE_OP(type, type_class) \
559 ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
560
CalculateType(int type,FieldMetadata::FieldTypeClass type_class)561 int FieldMetadata::CalculateType(int type,
562 FieldMetadata::FieldTypeClass type_class) {
563 return SERIALIZE_TABLE_OP(type, type_class);
564 }
565
566 template <int type>
IsNull(const void * ptr)567 bool IsNull(const void* ptr) {
568 return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
569 0;
570 }
571
572 template <>
IsNull(const void * ptr)573 bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
574 return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
575 }
576
577 template <>
IsNull(const void * ptr)578 bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
579 return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
580 }
581
582 template <>
IsNull(const void * ptr)583 bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
584 return Get<const MessageLite*>(ptr) == NULL;
585 }
586
587 template <>
IsNull(const void * ptr)588 bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
589 return Get<const MessageLite*>(ptr) == NULL;
590 }
591
592
593 template <>
IsNull(const void * ptr)594 bool IsNull<FieldMetadata::kInlinedType>(const void* ptr) {
595 return static_cast<const std::string*>(ptr)->empty();
596 }
597
598 #define SERIALIZERS_FOR_TYPE(type) \
599 case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \
600 if (!IsPresent(base, field_metadata.has_offset)) continue; \
601 SingularFieldHelper<type>::Serialize(ptr, field_metadata, output); \
602 break; \
603 case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence): \
604 if (IsNull<type>(ptr)) continue; \
605 SingularFieldHelper<type>::Serialize(ptr, field_metadata, output); \
606 break; \
607 case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated): \
608 RepeatedFieldHelper<type>::Serialize(ptr, field_metadata, output); \
609 break; \
610 case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked): \
611 PackedFieldHelper<type>::Serialize(ptr, field_metadata, output); \
612 break; \
613 case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf): \
614 if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \
615 continue; \
616 OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output); \
617 break
618
SerializeInternal(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,io::CodedOutputStream * output)619 void SerializeInternal(const uint8* base,
620 const FieldMetadata* field_metadata_table,
621 int32 num_fields, io::CodedOutputStream* output) {
622 SpecialSerializer func = nullptr;
623 for (int i = 0; i < num_fields; i++) {
624 const FieldMetadata& field_metadata = field_metadata_table[i];
625 const uint8* ptr = base + field_metadata.offset;
626 switch (field_metadata.type) {
627 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
628 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
629 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
630 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
631 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
632 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
633 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
634 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
635 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
636 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
637 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
638 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
639 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
640 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
641 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
642 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
643 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
644 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
645 SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
646
647 // Special cases
648 case FieldMetadata::kSpecial:
649 func = reinterpret_cast<SpecialSerializer>(
650 const_cast<void*>(field_metadata.ptr));
651 func(base, field_metadata.offset, field_metadata.tag,
652 field_metadata.has_offset, output);
653 break;
654 default:
655 // __builtin_unreachable()
656 SerializeNotImplemented(field_metadata.type);
657 }
658 }
659 }
660
SerializeInternalToArray(const uint8 * base,const FieldMetadata * field_metadata_table,int32 num_fields,bool is_deterministic,uint8 * buffer)661 uint8* SerializeInternalToArray(const uint8* base,
662 const FieldMetadata* field_metadata_table,
663 int32 num_fields, bool is_deterministic,
664 uint8* buffer) {
665 ArrayOutput array_output = {buffer, is_deterministic};
666 ArrayOutput* output = &array_output;
667 SpecialSerializer func = nullptr;
668 for (int i = 0; i < num_fields; i++) {
669 const FieldMetadata& field_metadata = field_metadata_table[i];
670 const uint8* ptr = base + field_metadata.offset;
671 switch (field_metadata.type) {
672 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
673 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
674 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
675 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
676 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
677 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
678 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
679 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
680 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
681 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
682 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
683 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
684 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
685 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
686 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
687 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
688 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
689 SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
690 SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType);
691 // Special cases
692 case FieldMetadata::kSpecial: {
693 io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
694 io::CodedOutputStream output(&array_stream);
695 output.SetSerializationDeterministic(is_deterministic);
696 func = reinterpret_cast<SpecialSerializer>(
697 const_cast<void*>(field_metadata.ptr));
698 func(base, field_metadata.offset, field_metadata.tag,
699 field_metadata.has_offset, &output);
700 array_output.ptr += output.ByteCount();
701 } break;
702 default:
703 // __builtin_unreachable()
704 SerializeNotImplemented(field_metadata.type);
705 }
706 }
707 return array_output.ptr;
708 }
709 #undef SERIALIZERS_FOR_TYPE
710
ExtensionSerializer(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,io::CodedOutputStream * output)711 void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
712 uint32 has_offset, io::CodedOutputStream* output) {
713 reinterpret_cast<const ExtensionSet*>(ptr + offset)
714 ->SerializeWithCachedSizes(tag, has_offset, output);
715 }
716
UnknownFieldSerializerLite(const uint8 * ptr,uint32 offset,uint32 tag,uint32 has_offset,io::CodedOutputStream * output)717 void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
718 uint32 has_offset,
719 io::CodedOutputStream* output) {
720 output->WriteString(
721 reinterpret_cast<const InternalMetadata*>(ptr + offset)
722 ->unknown_fields<std::string>(&internal::GetEmptyString));
723 }
724
DuplicateIfNonNullInternal(MessageLite * message)725 MessageLite* DuplicateIfNonNullInternal(MessageLite* message) {
726 if (message) {
727 MessageLite* ret = message->New();
728 ret->CheckTypeAndMergeFrom(*message);
729 return ret;
730 } else {
731 return NULL;
732 }
733 }
734
GenericSwap(MessageLite * m1,MessageLite * m2)735 void GenericSwap(MessageLite* m1, MessageLite* m2) {
736 std::unique_ptr<MessageLite> tmp(m1->New());
737 tmp->CheckTypeAndMergeFrom(*m1);
738 m1->Clear();
739 m1->CheckTypeAndMergeFrom(*m2);
740 m2->Clear();
741 m2->CheckTypeAndMergeFrom(*tmp);
742 }
743
744 // Returns a message owned by this Arena. This may require Own()ing or
745 // duplicating the message.
GetOwnedMessageInternal(Arena * message_arena,MessageLite * submessage,Arena * submessage_arena)746 MessageLite* GetOwnedMessageInternal(Arena* message_arena,
747 MessageLite* submessage,
748 Arena* submessage_arena) {
749 GOOGLE_DCHECK(submessage->GetArena() == submessage_arena);
750 GOOGLE_DCHECK(message_arena != submessage_arena);
751 if (message_arena != NULL && submessage_arena == NULL) {
752 message_arena->Own(submessage);
753 return submessage;
754 } else {
755 MessageLite* ret = submessage->New(message_arena);
756 ret->CheckTypeAndMergeFrom(*submessage);
757 return ret;
758 }
759 }
760
761 namespace {
762
InitSCC_DFS(SCCInfoBase * scc)763 void InitSCC_DFS(SCCInfoBase* scc) {
764 if (scc->visit_status.load(std::memory_order_relaxed) !=
765 SCCInfoBase::kUninitialized)
766 return;
767 scc->visit_status.store(SCCInfoBase::kRunning, std::memory_order_relaxed);
768 // Each base is followed by an array of void*, containing first pointers to
769 // SCCInfoBase and then pointers-to-pointers to SCCInfoBase.
770 auto deps = reinterpret_cast<void**>(scc + 1);
771 auto strong_deps = reinterpret_cast<SCCInfoBase* const*>(deps);
772 for (int i = 0; i < scc->num_deps; ++i) {
773 if (strong_deps[i]) InitSCC_DFS(strong_deps[i]);
774 }
775 auto implicit_weak_deps =
776 reinterpret_cast<SCCInfoBase** const*>(deps + scc->num_deps);
777 for (int i = 0; i < scc->num_implicit_weak_deps; ++i) {
778 if (*implicit_weak_deps[i]) {
779 InitSCC_DFS(*implicit_weak_deps[i]);
780 }
781 }
782 scc->init_func();
783 // Mark done (note we use memory order release here), other threads could
784 // now see this as initialized and thus the initialization must have happened
785 // before.
786 scc->visit_status.store(SCCInfoBase::kInitialized, std::memory_order_release);
787 }
788
789 } // namespace
790
InitSCCImpl(SCCInfoBase * scc)791 void InitSCCImpl(SCCInfoBase* scc) {
792 static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
793 // Either the default in case no initialization is running or the id of the
794 // thread that is currently initializing.
795 #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
796 static std::atomic<std::thread::id> runner;
797 auto me = std::this_thread::get_id();
798 #else
799 // This is a lightweight replacement for std::thread::id. std::thread does not
800 // work on Windows XP SP2 with the latest VC++ libraries, because it utilizes
801 // the Concurrency Runtime that is only supported on Windows XP SP3 and above.
802 static std::atomic_llong runner(-1);
803 auto me = ::GetCurrentThreadId();
804 #endif // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
805
806 // This will only happen because the constructor will call InitSCC while
807 // constructing the default instance.
808 if (runner.load(std::memory_order_relaxed) == me) {
809 // Because we're in the process of constructing the default instance.
810 // We can be assured that we're already exploring this SCC.
811 GOOGLE_CHECK_EQ(scc->visit_status.load(std::memory_order_relaxed),
812 SCCInfoBase::kRunning);
813 return;
814 }
815 InitProtobufDefaults();
816 mu.Lock();
817 runner.store(me, std::memory_order_relaxed);
818 InitSCC_DFS(scc);
819
820 #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
821 runner.store(std::thread::id{}, std::memory_order_relaxed);
822 #else
823 runner.store(-1, std::memory_order_relaxed);
824 #endif // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
825
826 mu.Unlock();
827 }
828
829 } // namespace internal
830 } // namespace protobuf
831 } // namespace google
832