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