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 (at) 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 68 #include <google/protobuf/stubs/common.h> 69 70 #include <google/protobuf/dynamic_message.h> 71 #include <google/protobuf/descriptor.h> 72 #include <google/protobuf/descriptor.pb.h> 73 #include <google/protobuf/generated_message_util.h> 74 #include <google/protobuf/generated_message_reflection.h> 75 #include <google/protobuf/reflection_ops.h> 76 #include <google/protobuf/repeated_field.h> 77 #include <google/protobuf/extension_set.h> 78 #include <google/protobuf/wire_format.h> 79 80 namespace google { 81 namespace protobuf { 82 83 using internal::WireFormat; 84 using internal::ExtensionSet; 85 using internal::GeneratedMessageReflection; 86 87 88 // =================================================================== 89 // Some helper tables and functions... 90 91 namespace { 92 93 // Compute the byte size of the in-memory representation of the field. 94 int FieldSpaceUsed(const FieldDescriptor* field) { 95 typedef FieldDescriptor FD; // avoid line wrapping 96 if (field->label() == FD::LABEL_REPEATED) { 97 switch (field->cpp_type()) { 98 case FD::CPPTYPE_INT32 : return sizeof(RepeatedField<int32 >); 99 case FD::CPPTYPE_INT64 : return sizeof(RepeatedField<int64 >); 100 case FD::CPPTYPE_UINT32 : return sizeof(RepeatedField<uint32 >); 101 case FD::CPPTYPE_UINT64 : return sizeof(RepeatedField<uint64 >); 102 case FD::CPPTYPE_DOUBLE : return sizeof(RepeatedField<double >); 103 case FD::CPPTYPE_FLOAT : return sizeof(RepeatedField<float >); 104 case FD::CPPTYPE_BOOL : return sizeof(RepeatedField<bool >); 105 case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >); 106 case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>); 107 108 case FD::CPPTYPE_STRING: 109 switch (field->options().ctype()) { 110 default: // TODO(kenton): Support other string reps. 111 case FieldOptions::STRING: 112 return sizeof(RepeatedPtrField<string>); 113 } 114 break; 115 } 116 } else { 117 switch (field->cpp_type()) { 118 case FD::CPPTYPE_INT32 : return sizeof(int32 ); 119 case FD::CPPTYPE_INT64 : return sizeof(int64 ); 120 case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); 121 case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); 122 case FD::CPPTYPE_DOUBLE : return sizeof(double ); 123 case FD::CPPTYPE_FLOAT : return sizeof(float ); 124 case FD::CPPTYPE_BOOL : return sizeof(bool ); 125 case FD::CPPTYPE_ENUM : return sizeof(int ); 126 127 case FD::CPPTYPE_MESSAGE: 128 return sizeof(Message*); 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(string*); 135 } 136 break; 137 } 138 } 139 140 GOOGLE_LOG(DFATAL) << "Can't get here."; 141 return 0; 142 } 143 144 // Compute the byte size of in-memory representation of the oneof fields 145 // in default oneof instance. 146 int OneofFieldSpaceUsed(const FieldDescriptor* field) { 147 typedef FieldDescriptor FD; // avoid line wrapping 148 switch (field->cpp_type()) { 149 case FD::CPPTYPE_INT32 : return sizeof(int32 ); 150 case FD::CPPTYPE_INT64 : return sizeof(int64 ); 151 case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); 152 case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); 153 case FD::CPPTYPE_DOUBLE : return sizeof(double ); 154 case FD::CPPTYPE_FLOAT : return sizeof(float ); 155 case FD::CPPTYPE_BOOL : return sizeof(bool ); 156 case FD::CPPTYPE_ENUM : return sizeof(int ); 157 158 case FD::CPPTYPE_MESSAGE: 159 return sizeof(Message*); 160 161 case FD::CPPTYPE_STRING: 162 switch (field->options().ctype()) { 163 default: 164 case FieldOptions::STRING: 165 return sizeof(string*); 166 } 167 break; 168 } 169 170 GOOGLE_LOG(DFATAL) << "Can't get here."; 171 return 0; 172 } 173 174 inline int DivideRoundingUp(int i, int j) { 175 return (i + (j - 1)) / j; 176 } 177 178 static const int kSafeAlignment = sizeof(uint64); 179 static const int kMaxOneofUnionSize = sizeof(uint64); 180 181 inline int AlignTo(int offset, int alignment) { 182 return DivideRoundingUp(offset, alignment) * alignment; 183 } 184 185 // Rounds the given byte offset up to the next offset aligned such that any 186 // type may be stored at it. 187 inline int AlignOffset(int offset) { 188 return AlignTo(offset, kSafeAlignment); 189 } 190 191 #define bitsizeof(T) (sizeof(T) * 8) 192 193 } // namespace 194 195 // =================================================================== 196 197 class DynamicMessage : public Message { 198 public: 199 struct TypeInfo { 200 int size; 201 int has_bits_offset; 202 int oneof_case_offset; 203 int unknown_fields_offset; 204 int extensions_offset; 205 206 // Not owned by the TypeInfo. 207 DynamicMessageFactory* factory; // The factory that created this object. 208 const DescriptorPool* pool; // The factory's DescriptorPool. 209 const Descriptor* type; // Type of this DynamicMessage. 210 211 // Warning: The order in which the following pointers are defined is 212 // important (the prototype must be deleted *before* the offsets). 213 scoped_array<int> offsets; 214 scoped_ptr<const GeneratedMessageReflection> reflection; 215 // Don't use a scoped_ptr to hold the prototype: the destructor for 216 // DynamicMessage needs to know whether it is the prototype, and does so by 217 // looking back at this field. This would assume details about the 218 // implementation of scoped_ptr. 219 const DynamicMessage* prototype; 220 void* default_oneof_instance; 221 222 TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {} 223 224 ~TypeInfo() { 225 delete prototype; 226 operator delete(default_oneof_instance); 227 } 228 }; 229 230 DynamicMessage(const TypeInfo* type_info); 231 ~DynamicMessage(); 232 233 // Called on the prototype after construction to initialize message fields. 234 void CrossLinkPrototypes(); 235 236 // implements Message ---------------------------------------------- 237 238 Message* New() const; 239 240 int GetCachedSize() const; 241 void SetCachedSize(int size) const; 242 243 Metadata GetMetadata() const; 244 245 246 private: 247 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); 248 249 inline bool is_prototype() const { 250 return type_info_->prototype == this || 251 // If type_info_->prototype is NULL, then we must be constructing 252 // the prototype now, which means we must be the prototype. 253 type_info_->prototype == NULL; 254 } 255 256 inline void* OffsetToPointer(int offset) { 257 return reinterpret_cast<uint8*>(this) + offset; 258 } 259 inline const void* OffsetToPointer(int offset) const { 260 return reinterpret_cast<const uint8*>(this) + offset; 261 } 262 263 const TypeInfo* type_info_; 264 265 // TODO(kenton): Make this an atomic<int> when C++ supports it. 266 mutable int cached_byte_size_; 267 }; 268 269 DynamicMessage::DynamicMessage(const TypeInfo* type_info) 270 : type_info_(type_info), 271 cached_byte_size_(0) { 272 // We need to call constructors for various fields manually and set 273 // default values where appropriate. We use placement new to call 274 // constructors. If you haven't heard of placement new, I suggest Googling 275 // it now. We use placement new even for primitive types that don't have 276 // constructors for consistency. (In theory, placement new should be used 277 // any time you are trying to convert untyped memory to typed memory, though 278 // in practice that's not strictly necessary for types that don't have a 279 // constructor.) 280 281 const Descriptor* descriptor = type_info_->type; 282 283 // Initialize oneof cases. 284 for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) { 285 new(OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i)) 286 uint32(0); 287 } 288 289 new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet; 290 291 if (type_info_->extensions_offset != -1) { 292 new(OffsetToPointer(type_info_->extensions_offset)) ExtensionSet; 293 } 294 295 for (int i = 0; i < descriptor->field_count(); i++) { 296 const FieldDescriptor* field = descriptor->field(i); 297 void* field_ptr = OffsetToPointer(type_info_->offsets[i]); 298 if (field->containing_oneof()) { 299 continue; 300 } 301 switch (field->cpp_type()) { 302 #define HANDLE_TYPE(CPPTYPE, TYPE) \ 303 case FieldDescriptor::CPPTYPE_##CPPTYPE: \ 304 if (!field->is_repeated()) { \ 305 new(field_ptr) TYPE(field->default_value_##TYPE()); \ 306 } else { \ 307 new(field_ptr) RepeatedField<TYPE>(); \ 308 } \ 309 break; 310 311 HANDLE_TYPE(INT32 , int32 ); 312 HANDLE_TYPE(INT64 , int64 ); 313 HANDLE_TYPE(UINT32, uint32); 314 HANDLE_TYPE(UINT64, uint64); 315 HANDLE_TYPE(DOUBLE, double); 316 HANDLE_TYPE(FLOAT , float ); 317 HANDLE_TYPE(BOOL , bool ); 318 #undef HANDLE_TYPE 319 320 case FieldDescriptor::CPPTYPE_ENUM: 321 if (!field->is_repeated()) { 322 new(field_ptr) int(field->default_value_enum()->number()); 323 } else { 324 new(field_ptr) RepeatedField<int>(); 325 } 326 break; 327 328 case FieldDescriptor::CPPTYPE_STRING: 329 switch (field->options().ctype()) { 330 default: // TODO(kenton): Support other string reps. 331 case FieldOptions::STRING: 332 if (!field->is_repeated()) { 333 if (is_prototype()) { 334 new(field_ptr) const string*(&field->default_value_string()); 335 } else { 336 string* default_value = 337 *reinterpret_cast<string* const*>( 338 type_info_->prototype->OffsetToPointer( 339 type_info_->offsets[i])); 340 new(field_ptr) string*(default_value); 341 } 342 } else { 343 new(field_ptr) RepeatedPtrField<string>(); 344 } 345 break; 346 } 347 break; 348 349 case FieldDescriptor::CPPTYPE_MESSAGE: { 350 if (!field->is_repeated()) { 351 new(field_ptr) Message*(NULL); 352 } else { 353 new(field_ptr) RepeatedPtrField<Message>(); 354 } 355 break; 356 } 357 } 358 } 359 } 360 361 DynamicMessage::~DynamicMessage() { 362 const Descriptor* descriptor = type_info_->type; 363 364 reinterpret_cast<UnknownFieldSet*>( 365 OffsetToPointer(type_info_->unknown_fields_offset))->~UnknownFieldSet(); 366 367 if (type_info_->extensions_offset != -1) { 368 reinterpret_cast<ExtensionSet*>( 369 OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet(); 370 } 371 372 // We need to manually run the destructors for repeated fields and strings, 373 // just as we ran their constructors in the the DynamicMessage constructor. 374 // We also need to manually delete oneof fields if it is set and is string 375 // or message. 376 // Additionally, if any singular embedded messages have been allocated, we 377 // need to delete them, UNLESS we are the prototype message of this type, 378 // in which case any embedded messages are other prototypes and shouldn't 379 // be touched. 380 for (int i = 0; i < descriptor->field_count(); i++) { 381 const FieldDescriptor* field = descriptor->field(i); 382 if (field->containing_oneof()) { 383 void* field_ptr = OffsetToPointer( 384 type_info_->oneof_case_offset 385 + sizeof(uint32) * field->containing_oneof()->index()); 386 if (*(reinterpret_cast<const uint32*>(field_ptr)) == 387 field->number()) { 388 field_ptr = OffsetToPointer(type_info_->offsets[ 389 descriptor->field_count() + field->containing_oneof()->index()]); 390 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { 391 switch (field->options().ctype()) { 392 default: 393 case FieldOptions::STRING: 394 delete *reinterpret_cast<string**>(field_ptr); 395 break; 396 } 397 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { 398 delete *reinterpret_cast<Message**>(field_ptr); 399 } 400 } 401 continue; 402 } 403 void* field_ptr = OffsetToPointer(type_info_->offsets[i]); 404 405 if (field->is_repeated()) { 406 switch (field->cpp_type()) { 407 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ 408 case FieldDescriptor::CPPTYPE_##UPPERCASE : \ 409 reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \ 410 ->~RepeatedField<LOWERCASE>(); \ 411 break 412 413 HANDLE_TYPE( INT32, int32); 414 HANDLE_TYPE( INT64, int64); 415 HANDLE_TYPE(UINT32, uint32); 416 HANDLE_TYPE(UINT64, uint64); 417 HANDLE_TYPE(DOUBLE, double); 418 HANDLE_TYPE( FLOAT, float); 419 HANDLE_TYPE( BOOL, bool); 420 HANDLE_TYPE( ENUM, int); 421 #undef HANDLE_TYPE 422 423 case FieldDescriptor::CPPTYPE_STRING: 424 switch (field->options().ctype()) { 425 default: // TODO(kenton): Support other string reps. 426 case FieldOptions::STRING: 427 reinterpret_cast<RepeatedPtrField<string>*>(field_ptr) 428 ->~RepeatedPtrField<string>(); 429 break; 430 } 431 break; 432 433 case FieldDescriptor::CPPTYPE_MESSAGE: 434 reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr) 435 ->~RepeatedPtrField<Message>(); 436 break; 437 } 438 439 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { 440 switch (field->options().ctype()) { 441 default: // TODO(kenton): Support other string reps. 442 case FieldOptions::STRING: { 443 string* ptr = *reinterpret_cast<string**>(field_ptr); 444 if (ptr != &field->default_value_string()) { 445 delete ptr; 446 } 447 break; 448 } 449 } 450 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { 451 if (!is_prototype()) { 452 Message* message = *reinterpret_cast<Message**>(field_ptr); 453 if (message != NULL) { 454 delete message; 455 } 456 } 457 } 458 } 459 } 460 461 void DynamicMessage::CrossLinkPrototypes() { 462 // This should only be called on the prototype message. 463 GOOGLE_CHECK(is_prototype()); 464 465 DynamicMessageFactory* factory = type_info_->factory; 466 const Descriptor* descriptor = type_info_->type; 467 468 // Cross-link default messages. 469 for (int i = 0; i < descriptor->field_count(); i++) { 470 const FieldDescriptor* field = descriptor->field(i); 471 void* field_ptr = OffsetToPointer(type_info_->offsets[i]); 472 if (field->containing_oneof()) { 473 field_ptr = reinterpret_cast<uint8*>( 474 type_info_->default_oneof_instance) + type_info_->offsets[i]; 475 } 476 477 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && 478 !field->is_repeated()) { 479 // For fields with message types, we need to cross-link with the 480 // prototype for the field's type. 481 // For singular fields, the field is just a pointer which should 482 // point to the prototype. 483 *reinterpret_cast<const Message**>(field_ptr) = 484 factory->GetPrototypeNoLock(field->message_type()); 485 } 486 } 487 } 488 489 Message* DynamicMessage::New() const { 490 void* new_base = operator new(type_info_->size); 491 memset(new_base, 0, type_info_->size); 492 return new(new_base) DynamicMessage(type_info_); 493 } 494 495 int DynamicMessage::GetCachedSize() const { 496 return cached_byte_size_; 497 } 498 499 void DynamicMessage::SetCachedSize(int size) const { 500 // This is theoretically not thread-compatible, but in practice it works 501 // because if multiple threads write this simultaneously, they will be 502 // writing the exact same value. 503 GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); 504 cached_byte_size_ = size; 505 GOOGLE_SAFE_CONCURRENT_WRITES_END(); 506 } 507 508 Metadata DynamicMessage::GetMetadata() const { 509 Metadata metadata; 510 metadata.descriptor = type_info_->type; 511 metadata.reflection = type_info_->reflection.get(); 512 return metadata; 513 } 514 515 // =================================================================== 516 517 struct DynamicMessageFactory::PrototypeMap { 518 typedef hash_map<const Descriptor*, const DynamicMessage::TypeInfo*> Map; 519 Map map_; 520 }; 521 522 DynamicMessageFactory::DynamicMessageFactory() 523 : pool_(NULL), delegate_to_generated_factory_(false), 524 prototypes_(new PrototypeMap) { 525 } 526 527 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) 528 : pool_(pool), delegate_to_generated_factory_(false), 529 prototypes_(new PrototypeMap) { 530 } 531 532 DynamicMessageFactory::~DynamicMessageFactory() { 533 for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin(); 534 iter != prototypes_->map_.end(); ++iter) { 535 DeleteDefaultOneofInstance(iter->second->type, 536 iter->second->offsets.get(), 537 iter->second->default_oneof_instance); 538 delete iter->second; 539 } 540 } 541 542 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) { 543 MutexLock lock(&prototypes_mutex_); 544 return GetPrototypeNoLock(type); 545 } 546 547 const Message* DynamicMessageFactory::GetPrototypeNoLock( 548 const Descriptor* type) { 549 if (delegate_to_generated_factory_ && 550 type->file()->pool() == DescriptorPool::generated_pool()) { 551 return MessageFactory::generated_factory()->GetPrototype(type); 552 } 553 554 const DynamicMessage::TypeInfo** target = &prototypes_->map_[type]; 555 if (*target != NULL) { 556 // Already exists. 557 return (*target)->prototype; 558 } 559 560 DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo; 561 *target = type_info; 562 563 type_info->type = type; 564 type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_; 565 type_info->factory = this; 566 567 // We need to construct all the structures passed to 568 // GeneratedMessageReflection's constructor. This includes: 569 // - A block of memory that contains space for all the message's fields. 570 // - An array of integers indicating the byte offset of each field within 571 // this block. 572 // - A big bitfield containing a bit for each field indicating whether 573 // or not that field is set. 574 575 // Compute size and offsets. 576 int* offsets = new int[type->field_count() + type->oneof_decl_count()]; 577 type_info->offsets.reset(offsets); 578 579 // Decide all field offsets by packing in order. 580 // We place the DynamicMessage object itself at the beginning of the allocated 581 // space. 582 int size = sizeof(DynamicMessage); 583 size = AlignOffset(size); 584 585 // Next the has_bits, which is an array of uint32s. 586 type_info->has_bits_offset = size; 587 int has_bits_array_size = 588 DivideRoundingUp(type->field_count(), bitsizeof(uint32)); 589 size += has_bits_array_size * sizeof(uint32); 590 size = AlignOffset(size); 591 592 // The oneof_case, if any. It is an array of uint32s. 593 if (type->oneof_decl_count() > 0) { 594 type_info->oneof_case_offset = size; 595 size += type->oneof_decl_count() * sizeof(uint32); 596 size = AlignOffset(size); 597 } 598 599 // The ExtensionSet, if any. 600 if (type->extension_range_count() > 0) { 601 type_info->extensions_offset = size; 602 size += sizeof(ExtensionSet); 603 size = AlignOffset(size); 604 } else { 605 // No extensions. 606 type_info->extensions_offset = -1; 607 } 608 609 // All the fields. 610 for (int i = 0; i < type->field_count(); i++) { 611 // Make sure field is aligned to avoid bus errors. 612 // Oneof fields do not use any space. 613 if (!type->field(i)->containing_oneof()) { 614 int field_size = FieldSpaceUsed(type->field(i)); 615 size = AlignTo(size, min(kSafeAlignment, field_size)); 616 offsets[i] = size; 617 size += field_size; 618 } 619 } 620 621 // The oneofs. 622 for (int i = 0; i < type->oneof_decl_count(); i++) { 623 size = AlignTo(size, kSafeAlignment); 624 offsets[type->field_count() + i] = size; 625 size += kMaxOneofUnionSize; 626 } 627 628 // Add the UnknownFieldSet to the end. 629 size = AlignOffset(size); 630 type_info->unknown_fields_offset = size; 631 size += sizeof(UnknownFieldSet); 632 633 // Align the final size to make sure no clever allocators think that 634 // alignment is not necessary. 635 size = AlignOffset(size); 636 type_info->size = size; 637 638 // Allocate the prototype. 639 void* base = operator new(size); 640 memset(base, 0, size); 641 DynamicMessage* prototype = new(base) DynamicMessage(type_info); 642 type_info->prototype = prototype; 643 644 // Construct the reflection object. 645 if (type->oneof_decl_count() > 0) { 646 // Compute the size of default oneof instance and offsets of default 647 // oneof fields. 648 int oneof_size = 0; 649 for (int i = 0; i < type->oneof_decl_count(); i++) { 650 for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { 651 const FieldDescriptor* field = type->oneof_decl(i)->field(j); 652 int field_size = OneofFieldSpaceUsed(field); 653 oneof_size = AlignTo(oneof_size, min(kSafeAlignment, field_size)); 654 offsets[field->index()] = oneof_size; 655 oneof_size += field_size; 656 } 657 } 658 // Construct default oneof instance. 659 type_info->default_oneof_instance = ::operator new(oneof_size); 660 ConstructDefaultOneofInstance(type_info->type, 661 type_info->offsets.get(), 662 type_info->default_oneof_instance); 663 type_info->reflection.reset( 664 new GeneratedMessageReflection( 665 type_info->type, 666 type_info->prototype, 667 type_info->offsets.get(), 668 type_info->has_bits_offset, 669 type_info->unknown_fields_offset, 670 type_info->extensions_offset, 671 type_info->default_oneof_instance, 672 type_info->oneof_case_offset, 673 type_info->pool, 674 this, 675 type_info->size)); 676 } else { 677 type_info->reflection.reset( 678 new GeneratedMessageReflection( 679 type_info->type, 680 type_info->prototype, 681 type_info->offsets.get(), 682 type_info->has_bits_offset, 683 type_info->unknown_fields_offset, 684 type_info->extensions_offset, 685 type_info->pool, 686 this, 687 type_info->size)); 688 } 689 // Cross link prototypes. 690 prototype->CrossLinkPrototypes(); 691 692 return prototype; 693 } 694 695 void DynamicMessageFactory::ConstructDefaultOneofInstance( 696 const Descriptor* type, 697 const int offsets[], 698 void* default_oneof_instance) { 699 for (int i = 0; i < type->oneof_decl_count(); i++) { 700 for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { 701 const FieldDescriptor* field = type->oneof_decl(i)->field(j); 702 void* field_ptr = reinterpret_cast<uint8*>( 703 default_oneof_instance) + offsets[field->index()]; 704 switch (field->cpp_type()) { 705 #define HANDLE_TYPE(CPPTYPE, TYPE) \ 706 case FieldDescriptor::CPPTYPE_##CPPTYPE: \ 707 new(field_ptr) TYPE(field->default_value_##TYPE()); \ 708 break; 709 710 HANDLE_TYPE(INT32 , int32 ); 711 HANDLE_TYPE(INT64 , int64 ); 712 HANDLE_TYPE(UINT32, uint32); 713 HANDLE_TYPE(UINT64, uint64); 714 HANDLE_TYPE(DOUBLE, double); 715 HANDLE_TYPE(FLOAT , float ); 716 HANDLE_TYPE(BOOL , bool ); 717 #undef HANDLE_TYPE 718 719 case FieldDescriptor::CPPTYPE_ENUM: 720 new(field_ptr) int(field->default_value_enum()->number()); 721 break; 722 case FieldDescriptor::CPPTYPE_STRING: 723 switch (field->options().ctype()) { 724 default: 725 case FieldOptions::STRING: 726 if (field->has_default_value()) { 727 new(field_ptr) const string*(&field->default_value_string()); 728 } else { 729 new(field_ptr) string*( 730 const_cast<string*>(&internal::GetEmptyString())); 731 } 732 break; 733 } 734 break; 735 736 case FieldDescriptor::CPPTYPE_MESSAGE: { 737 new(field_ptr) Message*(NULL); 738 break; 739 } 740 } 741 } 742 } 743 } 744 745 void DynamicMessageFactory::DeleteDefaultOneofInstance( 746 const Descriptor* type, 747 const int offsets[], 748 void* default_oneof_instance) { 749 for (int i = 0; i < type->oneof_decl_count(); i++) { 750 for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { 751 const FieldDescriptor* field = type->oneof_decl(i)->field(j); 752 if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { 753 switch (field->options().ctype()) { 754 default: 755 case FieldOptions::STRING: 756 break; 757 } 758 } 759 } 760 } 761 } 762 763 } // namespace protobuf 764 } // namespace google 765