• 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_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