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