• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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