• 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 // DynamicMessage is implemented by constructing a data structure which
36 // has roughly the same memory layout as a generated message would have.
37 // Then, we use GeneratedMessageReflection to implement our reflection
38 // interface.  All the other operations we need to implement (e.g.
39 // parsing, copying, etc.) are already implemented in terms of
40 // Reflection, so the rest is easy.
41 //
42 // The up side of this strategy is that it's very efficient.  We don't
43 // need to use hash_maps or generic representations of fields.  The
44 // down side is that this is a low-level memory management hack which
45 // can be tricky to get right.
46 //
47 // As mentioned in the header, we only expose a DynamicMessageFactory
48 // publicly, not the DynamicMessage class itself.  This is because
49 // GenericMessageReflection wants to have a pointer to a "default"
50 // copy of the class, with all fields initialized to their default
51 // values.  We only want to construct one of these per message type,
52 // so DynamicMessageFactory stores a cache of default messages for
53 // each type it sees (each unique Descriptor pointer).  The code
54 // refers to the "default" copy of the class as the "prototype".
55 //
56 // Note on memory allocation:  This module often calls "operator new()"
57 // to allocate untyped memory, rather than calling something like
58 // "new uint8[]".  This is because "operator new()" means "Give me some
59 // space which I can use as I please." while "new uint8[]" means "Give
60 // me an array of 8-bit integers.".  In practice, the later may return
61 // a pointer that is not aligned correctly for general use.  I believe
62 // Item 8 of "More Effective C++" discusses this in more detail, though
63 // I don't have the book on me right now so I'm not sure.
64 
65 #include <algorithm>
66 #include <google/protobuf/stubs/hash.h>
67 #include <memory>
68 #ifndef _SHARED_PTR_H
69 #include <google/protobuf/stubs/shared_ptr.h>
70 #endif
71 
72 #include <google/protobuf/stubs/common.h>
73 #include <google/protobuf/stubs/scoped_ptr.h>
74 
75 #include <google/protobuf/dynamic_message.h>
76 #include <google/protobuf/descriptor.h>
77 #include <google/protobuf/descriptor.pb.h>
78 #include <google/protobuf/generated_message_util.h>
79 #include <google/protobuf/generated_message_reflection.h>
80 #include <google/protobuf/arenastring.h>
81 #include <google/protobuf/map_field_inl.h>
82 #include <google/protobuf/reflection_ops.h>
83 #include <google/protobuf/repeated_field.h>
84 #include <google/protobuf/map_type_handler.h>
85 #include <google/protobuf/extension_set.h>
86 #include <google/protobuf/wire_format.h>
87 #include <google/protobuf/map_field.h>
88 
89 namespace google {
90 namespace protobuf {
91 
92 using internal::WireFormat;
93 using internal::ExtensionSet;
94 using internal::GeneratedMessageReflection;
95 using internal::MapField;
96 using internal::DynamicMapField;
97 
98 
99 using internal::ArenaStringPtr;
100 
101 // ===================================================================
102 // Some helper tables and functions...
103 
104 namespace {
105 
IsMapFieldInApi(const FieldDescriptor * field)106 bool IsMapFieldInApi(const FieldDescriptor* field) {
107   return field->is_map();
108 }
109 
110 // Compute the byte size of the in-memory representation of the field.
FieldSpaceUsed(const FieldDescriptor * field)111 int FieldSpaceUsed(const FieldDescriptor* field) {
112   typedef FieldDescriptor FD;  // avoid line wrapping
113   if (field->label() == FD::LABEL_REPEATED) {
114     switch (field->cpp_type()) {
115       case FD::CPPTYPE_INT32  : return sizeof(RepeatedField<int32   >);
116       case FD::CPPTYPE_INT64  : return sizeof(RepeatedField<int64   >);
117       case FD::CPPTYPE_UINT32 : return sizeof(RepeatedField<uint32  >);
118       case FD::CPPTYPE_UINT64 : return sizeof(RepeatedField<uint64  >);
119       case FD::CPPTYPE_DOUBLE : return sizeof(RepeatedField<double  >);
120       case FD::CPPTYPE_FLOAT  : return sizeof(RepeatedField<float   >);
121       case FD::CPPTYPE_BOOL   : return sizeof(RepeatedField<bool    >);
122       case FD::CPPTYPE_ENUM   : return sizeof(RepeatedField<int     >);
123       case FD::CPPTYPE_MESSAGE:
124         if (IsMapFieldInApi(field)) {
125           return sizeof(DynamicMapField);
126         } else {
127           return sizeof(RepeatedPtrField<Message>);
128         }
129 
130       case FD::CPPTYPE_STRING:
131         switch (field->options().ctype()) {
132           default:  // TODO(kenton):  Support other string reps.
133           case FieldOptions::STRING:
134             return sizeof(RepeatedPtrField<string>);
135         }
136         break;
137     }
138   } else {
139     switch (field->cpp_type()) {
140       case FD::CPPTYPE_INT32  : return sizeof(int32   );
141       case FD::CPPTYPE_INT64  : return sizeof(int64   );
142       case FD::CPPTYPE_UINT32 : return sizeof(uint32  );
143       case FD::CPPTYPE_UINT64 : return sizeof(uint64  );
144       case FD::CPPTYPE_DOUBLE : return sizeof(double  );
145       case FD::CPPTYPE_FLOAT  : return sizeof(float   );
146       case FD::CPPTYPE_BOOL   : return sizeof(bool    );
147       case FD::CPPTYPE_ENUM   : return sizeof(int     );
148 
149       case FD::CPPTYPE_MESSAGE:
150         return sizeof(Message*);
151 
152       case FD::CPPTYPE_STRING:
153         switch (field->options().ctype()) {
154           default:  // TODO(kenton):  Support other string reps.
155           case FieldOptions::STRING:
156             return sizeof(ArenaStringPtr);
157         }
158         break;
159     }
160   }
161 
162   GOOGLE_LOG(DFATAL) << "Can't get here.";
163   return 0;
164 }
165 
166 // Compute the byte size of in-memory representation of the oneof fields
167 // in default oneof instance.
OneofFieldSpaceUsed(const FieldDescriptor * field)168 int OneofFieldSpaceUsed(const FieldDescriptor* field) {
169   typedef FieldDescriptor FD;  // avoid line wrapping
170   switch (field->cpp_type()) {
171     case FD::CPPTYPE_INT32  : return sizeof(int32   );
172     case FD::CPPTYPE_INT64  : return sizeof(int64   );
173     case FD::CPPTYPE_UINT32 : return sizeof(uint32  );
174     case FD::CPPTYPE_UINT64 : return sizeof(uint64  );
175     case FD::CPPTYPE_DOUBLE : return sizeof(double  );
176     case FD::CPPTYPE_FLOAT  : return sizeof(float   );
177     case FD::CPPTYPE_BOOL   : return sizeof(bool    );
178     case FD::CPPTYPE_ENUM   : return sizeof(int     );
179 
180     case FD::CPPTYPE_MESSAGE:
181       return sizeof(Message*);
182 
183     case FD::CPPTYPE_STRING:
184       switch (field->options().ctype()) {
185         default:
186         case FieldOptions::STRING:
187           return sizeof(ArenaStringPtr);
188       }
189       break;
190   }
191 
192   GOOGLE_LOG(DFATAL) << "Can't get here.";
193   return 0;
194 }
195 
DivideRoundingUp(int i,int j)196 inline int DivideRoundingUp(int i, int j) {
197   return (i + (j - 1)) / j;
198 }
199 
200 static const int kSafeAlignment = sizeof(uint64);
201 static const int kMaxOneofUnionSize = sizeof(uint64);
202 
AlignTo(int offset,int alignment)203 inline int AlignTo(int offset, int alignment) {
204   return DivideRoundingUp(offset, alignment) * alignment;
205 }
206 
207 // Rounds the given byte offset up to the next offset aligned such that any
208 // type may be stored at it.
AlignOffset(int offset)209 inline int AlignOffset(int offset) {
210   return AlignTo(offset, kSafeAlignment);
211 }
212 
213 #define bitsizeof(T) (sizeof(T) * 8)
214 
215 }  // namespace
216 
217 // ===================================================================
218 
219 class DynamicMessage : public Message {
220  public:
221   struct TypeInfo {
222     int size;
223     int has_bits_offset;
224     int oneof_case_offset;
225     int unknown_fields_offset;
226     int extensions_offset;
227     int is_default_instance_offset;
228 
229     // Not owned by the TypeInfo.
230     DynamicMessageFactory* factory;  // The factory that created this object.
231     const DescriptorPool* pool;      // The factory's DescriptorPool.
232     const Descriptor* type;          // Type of this DynamicMessage.
233 
234     // Warning:  The order in which the following pointers are defined is
235     //   important (the prototype must be deleted *before* the offsets).
236     google::protobuf::scoped_array<int> offsets;
237     google::protobuf::scoped_ptr<const GeneratedMessageReflection> reflection;
238     // Don't use a scoped_ptr to hold the prototype: the destructor for
239     // DynamicMessage needs to know whether it is the prototype, and does so by
240     // looking back at this field. This would assume details about the
241     // implementation of scoped_ptr.
242     const DynamicMessage* prototype;
243     void* default_oneof_instance;
244 
TypeInfogoogle::protobuf::DynamicMessage::TypeInfo245     TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {}
246 
~TypeInfogoogle::protobuf::DynamicMessage::TypeInfo247     ~TypeInfo() {
248       delete prototype;
249       operator delete(default_oneof_instance);
250     }
251   };
252 
253   DynamicMessage(const TypeInfo* type_info);
254   ~DynamicMessage();
255 
256   // Called on the prototype after construction to initialize message fields.
257   void CrossLinkPrototypes();
258 
259   // implements Message ----------------------------------------------
260 
261   Message* New() const;
262   Message* New(::google::protobuf::Arena* arena) const;
GetArena() const263   ::google::protobuf::Arena* GetArena() const { return NULL; };
264 
265   int GetCachedSize() const;
266   void SetCachedSize(int size) const;
267 
268   Metadata GetMetadata() const;
269 
270   // We actually allocate more memory than sizeof(*this) when this
271   // class's memory is allocated via the global operator new. Thus, we need to
272   // manually call the global operator delete. Calling the destructor is taken
273   // care of for us. This makes DynamicMessage compatible with -fsized-delete.
274   // It doesn't work for MSVC though.
275 #ifndef _MSC_VER
operator delete(void * ptr)276   static void operator delete(void* ptr) {
277     ::operator delete(ptr);
278   }
279 #endif  // !_MSC_VER
280 
281  private:
282   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
283   DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena);
284   void SharedCtor();
285 
is_prototype() const286   inline bool is_prototype() const {
287     return type_info_->prototype == this ||
288            // If type_info_->prototype is NULL, then we must be constructing
289            // the prototype now, which means we must be the prototype.
290            type_info_->prototype == NULL;
291   }
292 
OffsetToPointer(int offset)293   inline void* OffsetToPointer(int offset) {
294     return reinterpret_cast<uint8*>(this) + offset;
295   }
OffsetToPointer(int offset) const296   inline const void* OffsetToPointer(int offset) const {
297     return reinterpret_cast<const uint8*>(this) + offset;
298   }
299 
300   const TypeInfo* type_info_;
301   // TODO(kenton):  Make this an atomic<int> when C++ supports it.
302   mutable int cached_byte_size_;
303 };
304 
DynamicMessage(const TypeInfo * type_info)305 DynamicMessage::DynamicMessage(const TypeInfo* type_info)
306   : type_info_(type_info),
307     cached_byte_size_(0) {
308   SharedCtor();
309 }
310 
DynamicMessage(const TypeInfo * type_info,::google::protobuf::Arena * arena)311 DynamicMessage::DynamicMessage(const TypeInfo* type_info,
312                                ::google::protobuf::Arena* arena)
313   : type_info_(type_info),
314     cached_byte_size_(0) {
315   SharedCtor();
316 }
317 
SharedCtor()318 void DynamicMessage::SharedCtor() {
319   // We need to call constructors for various fields manually and set
320   // default values where appropriate.  We use placement new to call
321   // constructors.  If you haven't heard of placement new, I suggest Googling
322   // it now.  We use placement new even for primitive types that don't have
323   // constructors for consistency.  (In theory, placement new should be used
324   // any time you are trying to convert untyped memory to typed memory, though
325   // in practice that's not strictly necessary for types that don't have a
326   // constructor.)
327 
328   const Descriptor* descriptor = type_info_->type;
329 
330   // Initialize oneof cases.
331   for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) {
332     new(OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i))
333         uint32(0);
334   }
335 
336   if (type_info_->is_default_instance_offset != -1) {
337     *reinterpret_cast<bool*>(
338         OffsetToPointer(type_info_->is_default_instance_offset)) = false;
339   }
340 
341   new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
342 
343   if (type_info_->extensions_offset != -1) {
344     new(OffsetToPointer(type_info_->extensions_offset)) ExtensionSet;
345   }
346 
347   for (int i = 0; i < descriptor->field_count(); i++) {
348     const FieldDescriptor* field = descriptor->field(i);
349     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
350     if (field->containing_oneof()) {
351       continue;
352     }
353     switch (field->cpp_type()) {
354 #define HANDLE_TYPE(CPPTYPE, TYPE)                                           \
355       case FieldDescriptor::CPPTYPE_##CPPTYPE:                               \
356         if (!field->is_repeated()) {                                         \
357           new(field_ptr) TYPE(field->default_value_##TYPE());                \
358         } else {                                                             \
359           new(field_ptr) RepeatedField<TYPE>();                              \
360         }                                                                    \
361         break;
362 
363       HANDLE_TYPE(INT32 , int32 );
364       HANDLE_TYPE(INT64 , int64 );
365       HANDLE_TYPE(UINT32, uint32);
366       HANDLE_TYPE(UINT64, uint64);
367       HANDLE_TYPE(DOUBLE, double);
368       HANDLE_TYPE(FLOAT , float );
369       HANDLE_TYPE(BOOL  , bool  );
370 #undef HANDLE_TYPE
371 
372       case FieldDescriptor::CPPTYPE_ENUM:
373         if (!field->is_repeated()) {
374           new(field_ptr) int(field->default_value_enum()->number());
375         } else {
376           new(field_ptr) RepeatedField<int>();
377         }
378         break;
379 
380       case FieldDescriptor::CPPTYPE_STRING:
381         switch (field->options().ctype()) {
382           default:  // TODO(kenton):  Support other string reps.
383           case FieldOptions::STRING:
384             if (!field->is_repeated()) {
385               const string* default_value;
386               if (is_prototype()) {
387                 default_value = &field->default_value_string();
388               } else {
389                 default_value =
390                   &(reinterpret_cast<const ArenaStringPtr*>(
391                     type_info_->prototype->OffsetToPointer(
392                       type_info_->offsets[i]))->Get(NULL));
393               }
394               ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr();
395               asp->UnsafeSetDefault(default_value);
396             } else {
397               new(field_ptr) RepeatedPtrField<string>();
398             }
399             break;
400         }
401         break;
402 
403       case FieldDescriptor::CPPTYPE_MESSAGE: {
404         if (!field->is_repeated()) {
405           new(field_ptr) Message*(NULL);
406         } else {
407           if (IsMapFieldInApi(field)) {
408             new (field_ptr) DynamicMapField(
409                 type_info_->factory->GetPrototypeNoLock(field->message_type()));
410           } else {
411             new (field_ptr) RepeatedPtrField<Message>();
412           }
413         }
414         break;
415       }
416     }
417   }
418 }
419 
~DynamicMessage()420 DynamicMessage::~DynamicMessage() {
421   const Descriptor* descriptor = type_info_->type;
422 
423   reinterpret_cast<UnknownFieldSet*>(
424     OffsetToPointer(type_info_->unknown_fields_offset))->~UnknownFieldSet();
425 
426   if (type_info_->extensions_offset != -1) {
427     reinterpret_cast<ExtensionSet*>(
428       OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet();
429   }
430 
431   // We need to manually run the destructors for repeated fields and strings,
432   // just as we ran their constructors in the DynamicMessage constructor.
433   // We also need to manually delete oneof fields if it is set and is string
434   // or message.
435   // Additionally, if any singular embedded messages have been allocated, we
436   // need to delete them, UNLESS we are the prototype message of this type,
437   // in which case any embedded messages are other prototypes and shouldn't
438   // be touched.
439   for (int i = 0; i < descriptor->field_count(); i++) {
440     const FieldDescriptor* field = descriptor->field(i);
441     if (field->containing_oneof()) {
442       void* field_ptr = OffsetToPointer(
443           type_info_->oneof_case_offset
444           + sizeof(uint32) * field->containing_oneof()->index());
445       if (*(reinterpret_cast<const uint32*>(field_ptr)) ==
446           field->number()) {
447         field_ptr = OffsetToPointer(type_info_->offsets[
448             descriptor->field_count() + field->containing_oneof()->index()]);
449         if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
450           switch (field->options().ctype()) {
451             default:
452             case FieldOptions::STRING: {
453               const ::std::string* default_value =
454                   &(reinterpret_cast<const ArenaStringPtr*>(
455                       reinterpret_cast<uint8*>(
456                           type_info_->default_oneof_instance)
457                       + type_info_->offsets[i])
458                     ->Get(NULL));
459               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
460                   default_value, NULL);
461               break;
462             }
463           }
464         } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
465             delete *reinterpret_cast<Message**>(field_ptr);
466         }
467       }
468       continue;
469     }
470     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
471 
472     if (field->is_repeated()) {
473       switch (field->cpp_type()) {
474 #define HANDLE_TYPE(UPPERCASE, LOWERCASE)                                     \
475         case FieldDescriptor::CPPTYPE_##UPPERCASE :                           \
476           reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr)              \
477               ->~RepeatedField<LOWERCASE>();                                  \
478           break
479 
480         HANDLE_TYPE( INT32,  int32);
481         HANDLE_TYPE( INT64,  int64);
482         HANDLE_TYPE(UINT32, uint32);
483         HANDLE_TYPE(UINT64, uint64);
484         HANDLE_TYPE(DOUBLE, double);
485         HANDLE_TYPE( FLOAT,  float);
486         HANDLE_TYPE(  BOOL,   bool);
487         HANDLE_TYPE(  ENUM,    int);
488 #undef HANDLE_TYPE
489 
490         case FieldDescriptor::CPPTYPE_STRING:
491           switch (field->options().ctype()) {
492             default:  // TODO(kenton):  Support other string reps.
493             case FieldOptions::STRING:
494               reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
495                   ->~RepeatedPtrField<string>();
496               break;
497           }
498           break;
499 
500         case FieldDescriptor::CPPTYPE_MESSAGE:
501           if (IsMapFieldInApi(field)) {
502             reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
503           } else {
504             reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
505                 ->~RepeatedPtrField<Message>();
506           }
507           break;
508       }
509 
510     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
511       switch (field->options().ctype()) {
512         default:  // TODO(kenton):  Support other string reps.
513         case FieldOptions::STRING: {
514           const ::std::string* default_value =
515               &(reinterpret_cast<const ArenaStringPtr*>(
516                   type_info_->prototype->OffsetToPointer(
517                       type_info_->offsets[i]))->Get(NULL));
518           reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
519               default_value, NULL);
520           break;
521         }
522       }
523     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
524       if (!is_prototype()) {
525         Message* message = *reinterpret_cast<Message**>(field_ptr);
526         if (message != NULL) {
527           delete message;
528         }
529       }
530     }
531   }
532 }
533 
CrossLinkPrototypes()534 void DynamicMessage::CrossLinkPrototypes() {
535   // This should only be called on the prototype message.
536   GOOGLE_CHECK(is_prototype());
537 
538   DynamicMessageFactory* factory = type_info_->factory;
539   const Descriptor* descriptor = type_info_->type;
540 
541   // Cross-link default messages.
542   for (int i = 0; i < descriptor->field_count(); i++) {
543     const FieldDescriptor* field = descriptor->field(i);
544     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
545     if (field->containing_oneof()) {
546       field_ptr = reinterpret_cast<uint8*>(
547           type_info_->default_oneof_instance) + type_info_->offsets[i];
548     }
549 
550     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
551         !field->is_repeated()) {
552       // For fields with message types, we need to cross-link with the
553       // prototype for the field's type.
554       // For singular fields, the field is just a pointer which should
555       // point to the prototype.
556       *reinterpret_cast<const Message**>(field_ptr) =
557         factory->GetPrototypeNoLock(field->message_type());
558     }
559   }
560 
561   // Set as the default instance -- this affects field-presence semantics for
562   // proto3.
563   if (type_info_->is_default_instance_offset != -1) {
564     void* is_default_instance_ptr =
565         OffsetToPointer(type_info_->is_default_instance_offset);
566     *reinterpret_cast<bool*>(is_default_instance_ptr) = true;
567   }
568 }
569 
New() const570 Message* DynamicMessage::New() const {
571   void* new_base = operator new(type_info_->size);
572   memset(new_base, 0, type_info_->size);
573   return new(new_base) DynamicMessage(type_info_);
574 }
575 
New(::google::protobuf::Arena * arena) const576 Message* DynamicMessage::New(::google::protobuf::Arena* arena) const {
577   if (arena != NULL) {
578     Message* message = New();
579     arena->Own(message);
580     return message;
581   } else {
582     return New();
583   }
584 }
585 
GetCachedSize() const586 int DynamicMessage::GetCachedSize() const {
587   return cached_byte_size_;
588 }
589 
SetCachedSize(int size) const590 void DynamicMessage::SetCachedSize(int size) const {
591   // This is theoretically not thread-compatible, but in practice it works
592   // because if multiple threads write this simultaneously, they will be
593   // writing the exact same value.
594   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
595   cached_byte_size_ = size;
596   GOOGLE_SAFE_CONCURRENT_WRITES_END();
597 }
598 
GetMetadata() const599 Metadata DynamicMessage::GetMetadata() const {
600   Metadata metadata;
601   metadata.descriptor = type_info_->type;
602   metadata.reflection = type_info_->reflection.get();
603   return metadata;
604 }
605 
606 // ===================================================================
607 
608 struct DynamicMessageFactory::PrototypeMap {
609   typedef hash_map<const Descriptor*, const DynamicMessage::TypeInfo*> Map;
610   Map map_;
611 };
612 
DynamicMessageFactory()613 DynamicMessageFactory::DynamicMessageFactory()
614   : pool_(NULL), delegate_to_generated_factory_(false),
615     prototypes_(new PrototypeMap) {
616 }
617 
DynamicMessageFactory(const DescriptorPool * pool)618 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
619   : pool_(pool), delegate_to_generated_factory_(false),
620     prototypes_(new PrototypeMap) {
621 }
622 
~DynamicMessageFactory()623 DynamicMessageFactory::~DynamicMessageFactory() {
624   for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
625        iter != prototypes_->map_.end(); ++iter) {
626     DeleteDefaultOneofInstance(iter->second->type,
627                                iter->second->offsets.get(),
628                                iter->second->default_oneof_instance);
629     delete iter->second;
630   }
631 }
632 
GetPrototype(const Descriptor * type)633 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
634   MutexLock lock(&prototypes_mutex_);
635   return GetPrototypeNoLock(type);
636 }
637 
GetPrototypeNoLock(const Descriptor * type)638 const Message* DynamicMessageFactory::GetPrototypeNoLock(
639     const Descriptor* type) {
640   if (delegate_to_generated_factory_ &&
641       type->file()->pool() == DescriptorPool::generated_pool()) {
642     return MessageFactory::generated_factory()->GetPrototype(type);
643   }
644 
645   const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
646   if (*target != NULL) {
647     // Already exists.
648     return (*target)->prototype;
649   }
650 
651   DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
652   *target = type_info;
653 
654   type_info->type = type;
655   type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
656   type_info->factory = this;
657 
658   // We need to construct all the structures passed to
659   // GeneratedMessageReflection's constructor.  This includes:
660   // - A block of memory that contains space for all the message's fields.
661   // - An array of integers indicating the byte offset of each field within
662   //   this block.
663   // - A big bitfield containing a bit for each field indicating whether
664   //   or not that field is set.
665 
666   // Compute size and offsets.
667   int* offsets = new int[type->field_count() + type->oneof_decl_count()];
668   type_info->offsets.reset(offsets);
669 
670   // Decide all field offsets by packing in order.
671   // We place the DynamicMessage object itself at the beginning of the allocated
672   // space.
673   int size = sizeof(DynamicMessage);
674   size = AlignOffset(size);
675 
676   // Next the has_bits, which is an array of uint32s.
677   if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
678     type_info->has_bits_offset = -1;
679   } else {
680     type_info->has_bits_offset = size;
681     int has_bits_array_size =
682       DivideRoundingUp(type->field_count(), bitsizeof(uint32));
683     size += has_bits_array_size * sizeof(uint32);
684     size = AlignOffset(size);
685   }
686 
687   // The is_default_instance member, if any.
688   if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
689     type_info->is_default_instance_offset = size;
690     size += sizeof(bool);
691     size = AlignOffset(size);
692   } else {
693     type_info->is_default_instance_offset = -1;
694   }
695 
696   // The oneof_case, if any. It is an array of uint32s.
697   if (type->oneof_decl_count() > 0) {
698     type_info->oneof_case_offset = size;
699     size += type->oneof_decl_count() * sizeof(uint32);
700     size = AlignOffset(size);
701   }
702 
703   // The ExtensionSet, if any.
704   if (type->extension_range_count() > 0) {
705     type_info->extensions_offset = size;
706     size += sizeof(ExtensionSet);
707     size = AlignOffset(size);
708   } else {
709     // No extensions.
710     type_info->extensions_offset = -1;
711   }
712 
713   // All the fields.
714   for (int i = 0; i < type->field_count(); i++) {
715     // Make sure field is aligned to avoid bus errors.
716     // Oneof fields do not use any space.
717     if (!type->field(i)->containing_oneof()) {
718       int field_size = FieldSpaceUsed(type->field(i));
719       size = AlignTo(size, std::min(kSafeAlignment, field_size));
720       offsets[i] = size;
721       size += field_size;
722     }
723   }
724 
725   // The oneofs.
726   for (int i = 0; i < type->oneof_decl_count(); i++) {
727     size = AlignTo(size, kSafeAlignment);
728     offsets[type->field_count() + i] = size;
729     size += kMaxOneofUnionSize;
730   }
731 
732   // Add the UnknownFieldSet to the end.
733   size = AlignOffset(size);
734   type_info->unknown_fields_offset = size;
735   size += sizeof(UnknownFieldSet);
736 
737   // Align the final size to make sure no clever allocators think that
738   // alignment is not necessary.
739   size = AlignOffset(size);
740   type_info->size = size;
741 
742   // Allocate the prototype.
743   void* base = operator new(size);
744   memset(base, 0, size);
745   // The prototype in type_info has to be set before creating the prototype
746   // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
747   // creating prototype for Foo, prototype of the map entry will also be
748   // created, which needs the address of the prototype of Foo (the value in
749   // map). To break the cyclic dependency, we have to assgin the address of
750   // prototype into type_info first.
751   type_info->prototype = static_cast<DynamicMessage*>(base);
752   DynamicMessage* prototype = new(base) DynamicMessage(type_info);
753 
754   // Construct the reflection object.
755   if (type->oneof_decl_count() > 0) {
756     // Compute the size of default oneof instance and offsets of default
757     // oneof fields.
758     int oneof_size = 0;
759     for (int i = 0; i < type->oneof_decl_count(); i++) {
760       for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
761         const FieldDescriptor* field = type->oneof_decl(i)->field(j);
762         int field_size = OneofFieldSpaceUsed(field);
763         oneof_size = AlignTo(oneof_size, std::min(kSafeAlignment, field_size));
764         offsets[field->index()] = oneof_size;
765         oneof_size += field_size;
766       }
767     }
768     // Construct default oneof instance.
769     type_info->default_oneof_instance = ::operator new(oneof_size);
770     ConstructDefaultOneofInstance(type_info->type,
771                                   type_info->offsets.get(),
772                                   type_info->default_oneof_instance);
773     type_info->reflection.reset(
774         new GeneratedMessageReflection(
775             type_info->type,
776             type_info->prototype,
777             type_info->offsets.get(),
778             type_info->has_bits_offset,
779             type_info->unknown_fields_offset,
780             type_info->extensions_offset,
781             type_info->default_oneof_instance,
782             type_info->oneof_case_offset,
783             type_info->pool,
784             this,
785             type_info->size,
786             -1 /* arena_offset */,
787             type_info->is_default_instance_offset));
788   } else {
789     type_info->reflection.reset(
790         new GeneratedMessageReflection(
791             type_info->type,
792             type_info->prototype,
793             type_info->offsets.get(),
794             type_info->has_bits_offset,
795             type_info->unknown_fields_offset,
796             type_info->extensions_offset,
797             type_info->pool,
798             this,
799             type_info->size,
800             -1 /* arena_offset */,
801             type_info->is_default_instance_offset));
802   }
803   // Cross link prototypes.
804   prototype->CrossLinkPrototypes();
805 
806   return prototype;
807 }
808 
ConstructDefaultOneofInstance(const Descriptor * type,const int offsets[],void * default_oneof_instance)809 void DynamicMessageFactory::ConstructDefaultOneofInstance(
810     const Descriptor* type,
811     const int offsets[],
812     void* default_oneof_instance) {
813   for (int i = 0; i < type->oneof_decl_count(); i++) {
814     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
815       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
816       void* field_ptr = reinterpret_cast<uint8*>(
817           default_oneof_instance) + offsets[field->index()];
818       switch (field->cpp_type()) {
819 #define HANDLE_TYPE(CPPTYPE, TYPE)                                      \
820         case FieldDescriptor::CPPTYPE_##CPPTYPE:                        \
821           new(field_ptr) TYPE(field->default_value_##TYPE());           \
822           break;
823 
824         HANDLE_TYPE(INT32 , int32 );
825         HANDLE_TYPE(INT64 , int64 );
826         HANDLE_TYPE(UINT32, uint32);
827         HANDLE_TYPE(UINT64, uint64);
828         HANDLE_TYPE(DOUBLE, double);
829         HANDLE_TYPE(FLOAT , float );
830         HANDLE_TYPE(BOOL  , bool  );
831 #undef HANDLE_TYPE
832 
833         case FieldDescriptor::CPPTYPE_ENUM:
834           new(field_ptr) int(field->default_value_enum()->number());
835           break;
836         case FieldDescriptor::CPPTYPE_STRING:
837           switch (field->options().ctype()) {
838             default:
839             case FieldOptions::STRING:
840               ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
841               asp->UnsafeSetDefault(&field->default_value_string());
842               break;
843           }
844           break;
845 
846         case FieldDescriptor::CPPTYPE_MESSAGE: {
847           new(field_ptr) Message*(NULL);
848           break;
849         }
850       }
851     }
852   }
853 }
854 
DeleteDefaultOneofInstance(const Descriptor * type,const int offsets[],void * default_oneof_instance)855 void DynamicMessageFactory::DeleteDefaultOneofInstance(
856     const Descriptor* type,
857     const int offsets[],
858     void* default_oneof_instance) {
859   for (int i = 0; i < type->oneof_decl_count(); i++) {
860     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
861       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
862       if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
863         switch (field->options().ctype()) {
864           default:
865           case FieldOptions::STRING:
866             break;
867         }
868       }
869     }
870   }
871 }
872 
873 }  // namespace protobuf
874 }  // namespace google
875