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