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 // Contains methods defined in extension_set.h which cannot be part of the
36 // lite library because they use descriptors or reflection.
37
38 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
39 #include <google/protobuf/descriptor.h>
40 #include <google/protobuf/extension_set.h>
41 #include <google/protobuf/message.h>
42 #include <google/protobuf/repeated_field.h>
43 #include <google/protobuf/wire_format.h>
44 #include <google/protobuf/wire_format_lite_inl.h>
45
46 namespace google {
47
48 namespace protobuf {
49 namespace internal {
50
51 // A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet.
52 class MessageSetFieldSkipper
53 : public UnknownFieldSetFieldSkipper {
54 public:
MessageSetFieldSkipper(UnknownFieldSet * unknown_fields)55 explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields)
56 : UnknownFieldSetFieldSkipper(unknown_fields) {}
~MessageSetFieldSkipper()57 virtual ~MessageSetFieldSkipper() {}
58
59 virtual bool SkipMessageSetField(io::CodedInputStream* input,
60 int field_number);
61 };
SkipMessageSetField(io::CodedInputStream * input,int field_number)62 bool MessageSetFieldSkipper::SkipMessageSetField(
63 io::CodedInputStream* input, int field_number) {
64 uint32 length;
65 if (!input->ReadVarint32(&length)) return false;
66 if (unknown_fields_ == NULL) {
67 return input->Skip(length);
68 } else {
69 return input->ReadString(
70 unknown_fields_->AddLengthDelimited(field_number), length);
71 }
72 }
73
74
75 // Implementation of ExtensionFinder which finds extensions in a given
76 // DescriptorPool, using the given MessageFactory to construct sub-objects.
77 // This class is implemented in extension_set_heavy.cc.
78 class DescriptorPoolExtensionFinder : public ExtensionFinder {
79 public:
DescriptorPoolExtensionFinder(const DescriptorPool * pool,MessageFactory * factory,const Descriptor * containing_type)80 DescriptorPoolExtensionFinder(const DescriptorPool* pool,
81 MessageFactory* factory,
82 const Descriptor* containing_type)
83 : pool_(pool), factory_(factory), containing_type_(containing_type) {}
~DescriptorPoolExtensionFinder()84 virtual ~DescriptorPoolExtensionFinder() {}
85
86 virtual bool Find(int number, ExtensionInfo* output);
87
88 private:
89 const DescriptorPool* pool_;
90 MessageFactory* factory_;
91 const Descriptor* containing_type_;
92 };
93
AppendToList(const Descriptor * containing_type,const DescriptorPool * pool,std::vector<const FieldDescriptor * > * output) const94 void ExtensionSet::AppendToList(
95 const Descriptor* containing_type,
96 const DescriptorPool* pool,
97 std::vector<const FieldDescriptor*>* output) const {
98 for (ExtensionMap::const_iterator iter = extensions_.begin();
99 iter != extensions_.end(); ++iter) {
100 bool has = false;
101 if (iter->second.is_repeated) {
102 has = iter->second.GetSize() > 0;
103 } else {
104 has = !iter->second.is_cleared;
105 }
106
107 if (has) {
108 // TODO(kenton): Looking up each field by number is somewhat unfortunate.
109 // Is there a better way? The problem is that descriptors are lazily-
110 // initialized, so they might not even be constructed until
111 // AppendToList() is called.
112
113 if (iter->second.descriptor == NULL) {
114 output->push_back(pool->FindExtensionByNumber(
115 containing_type, iter->first));
116 } else {
117 output->push_back(iter->second.descriptor);
118 }
119 }
120 }
121 }
122
real_type(FieldType type)123 inline FieldDescriptor::Type real_type(FieldType type) {
124 GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
125 return static_cast<FieldDescriptor::Type>(type);
126 }
127
cpp_type(FieldType type)128 inline FieldDescriptor::CppType cpp_type(FieldType type) {
129 return FieldDescriptor::TypeToCppType(
130 static_cast<FieldDescriptor::Type>(type));
131 }
132
field_type(FieldType type)133 inline WireFormatLite::FieldType field_type(FieldType type) {
134 GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
135 return static_cast<WireFormatLite::FieldType>(type);
136 }
137
138 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
139 GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
140 : FieldDescriptor::LABEL_OPTIONAL, \
141 FieldDescriptor::LABEL_##LABEL); \
142 GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
143
GetMessage(int number,const Descriptor * message_type,MessageFactory * factory) const144 const MessageLite& ExtensionSet::GetMessage(int number,
145 const Descriptor* message_type,
146 MessageFactory* factory) const {
147 ExtensionMap::const_iterator iter = extensions_.find(number);
148 if (iter == extensions_.end() || iter->second.is_cleared) {
149 // Not present. Return the default value.
150 return *factory->GetPrototype(message_type);
151 } else {
152 GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
153 if (iter->second.is_lazy) {
154 return iter->second.lazymessage_value->GetMessage(
155 *factory->GetPrototype(message_type));
156 } else {
157 return *iter->second.message_value;
158 }
159 }
160 }
161
MutableMessage(const FieldDescriptor * descriptor,MessageFactory * factory)162 MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
163 MessageFactory* factory) {
164 Extension* extension;
165 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
166 extension->type = descriptor->type();
167 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
168 extension->is_repeated = false;
169 extension->is_packed = false;
170 const MessageLite* prototype =
171 factory->GetPrototype(descriptor->message_type());
172 extension->is_lazy = false;
173 extension->message_value = prototype->New(arena_);
174 extension->is_cleared = false;
175 return extension->message_value;
176 } else {
177 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
178 extension->is_cleared = false;
179 if (extension->is_lazy) {
180 return extension->lazymessage_value->MutableMessage(
181 *factory->GetPrototype(descriptor->message_type()));
182 } else {
183 return extension->message_value;
184 }
185 }
186 }
187
ReleaseMessage(const FieldDescriptor * descriptor,MessageFactory * factory)188 MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
189 MessageFactory* factory) {
190 ExtensionMap::iterator iter = extensions_.find(descriptor->number());
191 if (iter == extensions_.end()) {
192 // Not present. Return NULL.
193 return NULL;
194 } else {
195 GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
196 MessageLite* ret = NULL;
197 if (iter->second.is_lazy) {
198 ret = iter->second.lazymessage_value->ReleaseMessage(
199 *factory->GetPrototype(descriptor->message_type()));
200 if (arena_ == NULL) {
201 delete iter->second.lazymessage_value;
202 }
203 } else {
204 if (arena_ != NULL) {
205 ret = (iter->second.message_value)->New();
206 ret->CheckTypeAndMergeFrom(*(iter->second.message_value));
207 } else {
208 ret = iter->second.message_value;
209 }
210 }
211 extensions_.erase(descriptor->number());
212 return ret;
213 }
214 }
215
UnsafeArenaReleaseMessage(const FieldDescriptor * descriptor,MessageFactory * factory)216 MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
217 const FieldDescriptor* descriptor, MessageFactory* factory) {
218 ExtensionMap::iterator iter = extensions_.find(descriptor->number());
219 if (iter == extensions_.end()) {
220 // Not present. Return NULL.
221 return NULL;
222 } else {
223 GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
224 MessageLite* ret = NULL;
225 if (iter->second.is_lazy) {
226 ret = iter->second.lazymessage_value->UnsafeArenaReleaseMessage(
227 *factory->GetPrototype(descriptor->message_type()));
228 if (arena_ == NULL) {
229 delete iter->second.lazymessage_value;
230 }
231 } else {
232 ret = iter->second.message_value;
233 }
234 extensions_.erase(descriptor->number());
235 return ret;
236 }
237 }
238
MaybeNewRepeatedExtension(const FieldDescriptor * descriptor)239 ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) {
240 Extension* extension;
241 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
242 extension->type = descriptor->type();
243 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
244 extension->is_repeated = true;
245 extension->repeated_message_value =
246 ::google::protobuf::Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
247 } else {
248 GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
249 }
250 return extension;
251 }
252
AddMessage(const FieldDescriptor * descriptor,MessageFactory * factory)253 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
254 MessageFactory* factory) {
255 Extension* extension = MaybeNewRepeatedExtension(descriptor);
256
257 // RepeatedPtrField<Message> does not know how to Add() since it cannot
258 // allocate an abstract object, so we have to be tricky.
259 MessageLite* result = extension->repeated_message_value
260 ->AddFromCleared<GenericTypeHandler<MessageLite> >();
261 if (result == NULL) {
262 const MessageLite* prototype;
263 if (extension->repeated_message_value->size() == 0) {
264 prototype = factory->GetPrototype(descriptor->message_type());
265 GOOGLE_CHECK(prototype != NULL);
266 } else {
267 prototype = &extension->repeated_message_value->Get(0);
268 }
269 result = prototype->New(arena_);
270 extension->repeated_message_value->AddAllocated(result);
271 }
272 return result;
273 }
274
AddAllocatedMessage(const FieldDescriptor * descriptor,MessageLite * new_entry)275 void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
276 MessageLite* new_entry) {
277 Extension* extension = MaybeNewRepeatedExtension(descriptor);
278
279 extension->repeated_message_value->AddAllocated(new_entry);
280 }
281
ValidateEnumUsingDescriptor(const void * arg,int number)282 static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
283 return reinterpret_cast<const EnumDescriptor*>(arg)
284 ->FindValueByNumber(number) != NULL;
285 }
286
Find(int number,ExtensionInfo * output)287 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
288 const FieldDescriptor* extension =
289 pool_->FindExtensionByNumber(containing_type_, number);
290 if (extension == NULL) {
291 return false;
292 } else {
293 output->type = extension->type();
294 output->is_repeated = extension->is_repeated();
295 output->is_packed = extension->options().packed();
296 output->descriptor = extension;
297 if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
298 output->message_prototype =
299 factory_->GetPrototype(extension->message_type());
300 GOOGLE_CHECK(output->message_prototype != NULL)
301 << "Extension factory's GetPrototype() returned NULL for extension: "
302 << extension->full_name();
303 } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
304 output->enum_validity_check.func = ValidateEnumUsingDescriptor;
305 output->enum_validity_check.arg = extension->enum_type();
306 }
307
308 return true;
309 }
310 }
311
ParseField(uint32 tag,io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)312 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
313 const Message* containing_type,
314 UnknownFieldSet* unknown_fields) {
315 UnknownFieldSetFieldSkipper skipper(unknown_fields);
316 if (input->GetExtensionPool() == NULL) {
317 GeneratedExtensionFinder finder(containing_type);
318 return ParseField(tag, input, &finder, &skipper);
319 } else {
320 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
321 input->GetExtensionFactory(),
322 containing_type->GetDescriptor());
323 return ParseField(tag, input, &finder, &skipper);
324 }
325 }
326
ParseMessageSet(io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)327 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
328 const Message* containing_type,
329 UnknownFieldSet* unknown_fields) {
330 MessageSetFieldSkipper skipper(unknown_fields);
331 if (input->GetExtensionPool() == NULL) {
332 GeneratedExtensionFinder finder(containing_type);
333 return ParseMessageSet(input, &finder, &skipper);
334 } else {
335 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
336 input->GetExtensionFactory(),
337 containing_type->GetDescriptor());
338 return ParseMessageSet(input, &finder, &skipper);
339 }
340 }
341
SpaceUsedExcludingSelf() const342 int ExtensionSet::SpaceUsedExcludingSelf() const {
343 int total_size =
344 extensions_.size() * sizeof(ExtensionMap::value_type);
345 for (ExtensionMap::const_iterator iter = extensions_.begin(),
346 end = extensions_.end();
347 iter != end;
348 ++iter) {
349 total_size += iter->second.SpaceUsedExcludingSelf();
350 }
351 return total_size;
352 }
353
RepeatedMessage_SpaceUsedExcludingSelf(RepeatedPtrFieldBase * field)354 inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
355 RepeatedPtrFieldBase* field) {
356 return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
357 }
358
SpaceUsedExcludingSelf() const359 int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
360 int total_size = 0;
361 if (is_repeated) {
362 switch (cpp_type(type)) {
363 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
364 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
365 total_size += sizeof(*repeated_##LOWERCASE##_value) + \
366 repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
367 break
368
369 HANDLE_TYPE( INT32, int32);
370 HANDLE_TYPE( INT64, int64);
371 HANDLE_TYPE( UINT32, uint32);
372 HANDLE_TYPE( UINT64, uint64);
373 HANDLE_TYPE( FLOAT, float);
374 HANDLE_TYPE( DOUBLE, double);
375 HANDLE_TYPE( BOOL, bool);
376 HANDLE_TYPE( ENUM, enum);
377 HANDLE_TYPE( STRING, string);
378 #undef HANDLE_TYPE
379
380 case FieldDescriptor::CPPTYPE_MESSAGE:
381 // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
382 // but MessageLite has no SpaceUsed(), so we must directly call
383 // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
384 // handler.
385 total_size += sizeof(*repeated_message_value) +
386 RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
387 break;
388 }
389 } else {
390 switch (cpp_type(type)) {
391 case FieldDescriptor::CPPTYPE_STRING:
392 total_size += sizeof(*string_value) +
393 StringSpaceUsedExcludingSelf(*string_value);
394 break;
395 case FieldDescriptor::CPPTYPE_MESSAGE:
396 if (is_lazy) {
397 total_size += lazymessage_value->SpaceUsed();
398 } else {
399 total_size += down_cast<Message*>(message_value)->SpaceUsed();
400 }
401 break;
402 default:
403 // No extra storage costs for primitive types.
404 break;
405 }
406 }
407 return total_size;
408 }
409
410 // The Serialize*ToArray methods are only needed in the heavy library, as
411 // the lite library only generates SerializeWithCachedSizes.
SerializeWithCachedSizesToArray(int start_field_number,int end_field_number,uint8 * target) const412 uint8* ExtensionSet::SerializeWithCachedSizesToArray(int start_field_number,
413 int end_field_number,
414 uint8* target) const {
415 return InternalSerializeWithCachedSizesToArray(
416 start_field_number, end_field_number, false, target);
417 }
418
SerializeMessageSetWithCachedSizesToArray(uint8 * target) const419 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
420 uint8* target) const {
421 return InternalSerializeMessageSetWithCachedSizesToArray(false, target);
422 }
423
InternalSerializeWithCachedSizesToArray(int start_field_number,int end_field_number,bool deterministic,uint8 * target) const424 uint8* ExtensionSet::InternalSerializeWithCachedSizesToArray(
425 int start_field_number, int end_field_number,
426 bool deterministic, uint8* target) const {
427 ExtensionMap::const_iterator iter;
428 for (iter = extensions_.lower_bound(start_field_number);
429 iter != extensions_.end() && iter->first < end_field_number;
430 ++iter) {
431 target = iter->second.InternalSerializeFieldWithCachedSizesToArray(
432 iter->first, deterministic, target);
433 }
434 return target;
435 }
436
InternalSerializeMessageSetWithCachedSizesToArray(bool deterministic,uint8 * target) const437 uint8* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray(
438 bool deterministic, uint8* target) const {
439 ExtensionMap::const_iterator iter;
440 for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
441 target = iter->second.InternalSerializeMessageSetItemWithCachedSizesToArray(
442 iter->first, deterministic, target);
443 }
444 return target;
445 }
446
InternalSerializeFieldWithCachedSizesToArray(int number,bool deterministic,uint8 * target) const447 uint8* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray(
448 int number, bool deterministic, uint8* target) const {
449 if (is_repeated) {
450 if (is_packed) {
451 if (cached_size == 0) return target;
452
453 target = WireFormatLite::WriteTagToArray(number,
454 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
455 target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
456
457 switch (real_type(type)) {
458 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
459 case FieldDescriptor::TYPE_##UPPERCASE: \
460 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
461 target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
462 repeated_##LOWERCASE##_value->Get(i), target); \
463 } \
464 break
465
466 HANDLE_TYPE( INT32, Int32, int32);
467 HANDLE_TYPE( INT64, Int64, int64);
468 HANDLE_TYPE( UINT32, UInt32, uint32);
469 HANDLE_TYPE( UINT64, UInt64, uint64);
470 HANDLE_TYPE( SINT32, SInt32, int32);
471 HANDLE_TYPE( SINT64, SInt64, int64);
472 HANDLE_TYPE( FIXED32, Fixed32, uint32);
473 HANDLE_TYPE( FIXED64, Fixed64, uint64);
474 HANDLE_TYPE(SFIXED32, SFixed32, int32);
475 HANDLE_TYPE(SFIXED64, SFixed64, int64);
476 HANDLE_TYPE( FLOAT, Float, float);
477 HANDLE_TYPE( DOUBLE, Double, double);
478 HANDLE_TYPE( BOOL, Bool, bool);
479 HANDLE_TYPE( ENUM, Enum, enum);
480 #undef HANDLE_TYPE
481
482 case WireFormatLite::TYPE_STRING:
483 case WireFormatLite::TYPE_BYTES:
484 case WireFormatLite::TYPE_GROUP:
485 case WireFormatLite::TYPE_MESSAGE:
486 GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
487 break;
488 }
489 } else {
490 switch (real_type(type)) {
491 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
492 case FieldDescriptor::TYPE_##UPPERCASE: \
493 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
494 target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
495 repeated_##LOWERCASE##_value->Get(i), target); \
496 } \
497 break
498
499 HANDLE_TYPE( INT32, Int32, int32);
500 HANDLE_TYPE( INT64, Int64, int64);
501 HANDLE_TYPE( UINT32, UInt32, uint32);
502 HANDLE_TYPE( UINT64, UInt64, uint64);
503 HANDLE_TYPE( SINT32, SInt32, int32);
504 HANDLE_TYPE( SINT64, SInt64, int64);
505 HANDLE_TYPE( FIXED32, Fixed32, uint32);
506 HANDLE_TYPE( FIXED64, Fixed64, uint64);
507 HANDLE_TYPE(SFIXED32, SFixed32, int32);
508 HANDLE_TYPE(SFIXED64, SFixed64, int64);
509 HANDLE_TYPE( FLOAT, Float, float);
510 HANDLE_TYPE( DOUBLE, Double, double);
511 HANDLE_TYPE( BOOL, Bool, bool);
512 HANDLE_TYPE( STRING, String, string);
513 HANDLE_TYPE( BYTES, Bytes, string);
514 HANDLE_TYPE( ENUM, Enum, enum);
515 #undef HANDLE_TYPE
516 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
517 case FieldDescriptor::TYPE_##UPPERCASE: \
518 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
519 target = WireFormatLite::InternalWrite##CAMELCASE##ToArray( \
520 number, repeated_##LOWERCASE##_value->Get(i), \
521 deterministic, target); \
522 } \
523 break
524
525 HANDLE_TYPE( GROUP, Group, message);
526 HANDLE_TYPE( MESSAGE, Message, message);
527 #undef HANDLE_TYPE
528 }
529 }
530 } else if (!is_cleared) {
531 switch (real_type(type)) {
532 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
533 case FieldDescriptor::TYPE_##UPPERCASE: \
534 target = WireFormatLite::Write##CAMELCASE##ToArray( \
535 number, VALUE, target); \
536 break
537
538 HANDLE_TYPE( INT32, Int32, int32_value);
539 HANDLE_TYPE( INT64, Int64, int64_value);
540 HANDLE_TYPE( UINT32, UInt32, uint32_value);
541 HANDLE_TYPE( UINT64, UInt64, uint64_value);
542 HANDLE_TYPE( SINT32, SInt32, int32_value);
543 HANDLE_TYPE( SINT64, SInt64, int64_value);
544 HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
545 HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
546 HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
547 HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
548 HANDLE_TYPE( FLOAT, Float, float_value);
549 HANDLE_TYPE( DOUBLE, Double, double_value);
550 HANDLE_TYPE( BOOL, Bool, bool_value);
551 HANDLE_TYPE( STRING, String, *string_value);
552 HANDLE_TYPE( BYTES, Bytes, *string_value);
553 HANDLE_TYPE( ENUM, Enum, enum_value);
554 HANDLE_TYPE( GROUP, Group, *message_value);
555 #undef HANDLE_TYPE
556 case FieldDescriptor::TYPE_MESSAGE:
557 if (is_lazy) {
558 target = lazymessage_value->InternalWriteMessageToArray(
559 number, deterministic, target);
560 } else {
561 target = WireFormatLite::InternalWriteMessageToArray(
562 number, *message_value, deterministic, target);
563 }
564 break;
565 }
566 }
567 return target;
568 }
569
570 uint8*
InternalSerializeMessageSetItemWithCachedSizesToArray(int number,bool deterministic,uint8 * target) const571 ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray(
572 int number, bool deterministic, uint8* target) const {
573 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
574 // Not a valid MessageSet extension, but serialize it the normal way.
575 GOOGLE_LOG(WARNING) << "Invalid message set extension.";
576 return InternalSerializeFieldWithCachedSizesToArray(number, deterministic,
577 target);
578 }
579
580 if (is_cleared) return target;
581
582 // Start group.
583 target = io::CodedOutputStream::WriteTagToArray(
584 WireFormatLite::kMessageSetItemStartTag, target);
585 // Write type ID.
586 target = WireFormatLite::WriteUInt32ToArray(
587 WireFormatLite::kMessageSetTypeIdNumber, number, target);
588 // Write message.
589 if (is_lazy) {
590 target = lazymessage_value->WriteMessageToArray(
591 WireFormatLite::kMessageSetMessageNumber, target);
592 } else {
593 target = WireFormatLite::WriteMessageToArray(
594 WireFormatLite::kMessageSetMessageNumber, *message_value, target);
595 }
596 // End group.
597 target = io::CodedOutputStream::WriteTagToArray(
598 WireFormatLite::kMessageSetItemEndTag, target);
599 return target;
600 }
601
602
ParseFieldMaybeLazily(int wire_type,int field_number,io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)603 bool ExtensionSet::ParseFieldMaybeLazily(
604 int wire_type, int field_number, io::CodedInputStream* input,
605 ExtensionFinder* extension_finder,
606 MessageSetFieldSkipper* field_skipper) {
607 return ParseField(WireFormatLite::MakeTag(
608 field_number, static_cast<WireFormatLite::WireType>(wire_type)),
609 input, extension_finder, field_skipper);
610 }
611
ParseMessageSet(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)612 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
613 ExtensionFinder* extension_finder,
614 MessageSetFieldSkipper* field_skipper) {
615 while (true) {
616 const uint32 tag = input->ReadTag();
617 switch (tag) {
618 case 0:
619 return true;
620 case WireFormatLite::kMessageSetItemStartTag:
621 if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
622 return false;
623 }
624 break;
625 default:
626 if (!ParseField(tag, input, extension_finder, field_skipper)) {
627 return false;
628 }
629 break;
630 }
631 }
632 }
633
ParseMessageSet(io::CodedInputStream * input,const MessageLite * containing_type)634 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
635 const MessageLite* containing_type) {
636 MessageSetFieldSkipper skipper(NULL);
637 GeneratedExtensionFinder finder(containing_type);
638 return ParseMessageSet(input, &finder, &skipper);
639 }
640
ParseMessageSetItem(io::CodedInputStream * input,ExtensionFinder * extension_finder,MessageSetFieldSkipper * field_skipper)641 bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
642 ExtensionFinder* extension_finder,
643 MessageSetFieldSkipper* field_skipper) {
644 // TODO(kenton): It would be nice to share code between this and
645 // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
646 // differences would be hard to factor out.
647
648 // This method parses a group which should contain two fields:
649 // required int32 type_id = 2;
650 // required data message = 3;
651
652 uint32 last_type_id = 0;
653
654 // If we see message data before the type_id, we'll append it to this so
655 // we can parse it later.
656 string message_data;
657
658 while (true) {
659 const uint32 tag = input->ReadTag();
660 if (tag == 0) return false;
661
662 switch (tag) {
663 case WireFormatLite::kMessageSetTypeIdTag: {
664 uint32 type_id;
665 if (!input->ReadVarint32(&type_id)) return false;
666 last_type_id = type_id;
667
668 if (!message_data.empty()) {
669 // We saw some message data before the type_id. Have to parse it
670 // now.
671 io::CodedInputStream sub_input(
672 reinterpret_cast<const uint8*>(message_data.data()),
673 message_data.size());
674 if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
675 last_type_id, &sub_input,
676 extension_finder, field_skipper)) {
677 return false;
678 }
679 message_data.clear();
680 }
681
682 break;
683 }
684
685 case WireFormatLite::kMessageSetMessageTag: {
686 if (last_type_id == 0) {
687 // We haven't seen a type_id yet. Append this data to message_data.
688 string temp;
689 uint32 length;
690 if (!input->ReadVarint32(&length)) return false;
691 if (!input->ReadString(&temp, length)) return false;
692 io::StringOutputStream output_stream(&message_data);
693 io::CodedOutputStream coded_output(&output_stream);
694 coded_output.WriteVarint32(length);
695 coded_output.WriteString(temp);
696 } else {
697 // Already saw type_id, so we can parse this directly.
698 if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
699 last_type_id, input,
700 extension_finder, field_skipper)) {
701 return false;
702 }
703 }
704
705 break;
706 }
707
708 case WireFormatLite::kMessageSetItemEndTag: {
709 return true;
710 }
711
712 default: {
713 if (!field_skipper->SkipField(input, tag)) return false;
714 }
715 }
716 }
717 }
718
SerializeMessageSetItemWithCachedSizes(int number,io::CodedOutputStream * output) const719 void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
720 int number,
721 io::CodedOutputStream* output) const {
722 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
723 // Not a valid MessageSet extension, but serialize it the normal way.
724 SerializeFieldWithCachedSizes(number, output);
725 return;
726 }
727
728 if (is_cleared) return;
729
730 // Start group.
731 output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
732
733 // Write type ID.
734 WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
735 number,
736 output);
737 // Write message.
738 if (is_lazy) {
739 lazymessage_value->WriteMessage(
740 WireFormatLite::kMessageSetMessageNumber, output);
741 } else {
742 WireFormatLite::WriteMessageMaybeToArray(
743 WireFormatLite::kMessageSetMessageNumber,
744 *message_value,
745 output);
746 }
747
748 // End group.
749 output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
750 }
751
MessageSetItemByteSize(int number) const752 int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
753 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
754 // Not a valid MessageSet extension, but compute the byte size for it the
755 // normal way.
756 return ByteSize(number);
757 }
758
759 if (is_cleared) return 0;
760
761 int our_size = WireFormatLite::kMessageSetItemTagsSize;
762
763 // type_id
764 our_size += io::CodedOutputStream::VarintSize32(number);
765
766 // message
767 int message_size = 0;
768 if (is_lazy) {
769 message_size = lazymessage_value->ByteSize();
770 } else {
771 message_size = message_value->ByteSize();
772 }
773
774 our_size += io::CodedOutputStream::VarintSize32(message_size);
775 our_size += message_size;
776
777 return our_size;
778 }
779
SerializeMessageSetWithCachedSizes(io::CodedOutputStream * output) const780 void ExtensionSet::SerializeMessageSetWithCachedSizes(
781 io::CodedOutputStream* output) const {
782 for (ExtensionMap::const_iterator iter = extensions_.begin();
783 iter != extensions_.end(); ++iter) {
784 iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
785 }
786 }
787
MessageSetByteSize() const788 int ExtensionSet::MessageSetByteSize() const {
789 int total_size = 0;
790
791 for (ExtensionMap::const_iterator iter = extensions_.begin();
792 iter != extensions_.end(); ++iter) {
793 total_size += iter->second.MessageSetItemByteSize(iter->first);
794 }
795
796 return total_size;
797 }
798
799 } // namespace internal
800 } // namespace protobuf
801 } // namespace google
802