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 #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 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. 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. 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 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 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. 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 245 TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {} 246 247 ~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; 263 ::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 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 286 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 293 inline void* OffsetToPointer(int offset) { 294 return reinterpret_cast<uint8*>(this) + offset; 295 } 296 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 305 DynamicMessage::DynamicMessage(const TypeInfo* type_info) 306 : type_info_(type_info), 307 cached_byte_size_(0) { 308 SharedCtor(); 309 } 310 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 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 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 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 570 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 576 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 586 int DynamicMessage::GetCachedSize() const { 587 return cached_byte_size_; 588 } 589 590 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 599 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 613 DynamicMessageFactory::DynamicMessageFactory() 614 : pool_(NULL), delegate_to_generated_factory_(false), 615 prototypes_(new PrototypeMap) { 616 } 617 618 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) 619 : pool_(pool), delegate_to_generated_factory_(false), 620 prototypes_(new PrototypeMap) { 621 } 622 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 633 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) { 634 MutexLock lock(&prototypes_mutex_); 635 return GetPrototypeNoLock(type); 636 } 637 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 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 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