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