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