1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
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/extension_set.h>
39 #include <google/protobuf/descriptor.h>
40 #include <google/protobuf/message.h>
41 #include <google/protobuf/repeated_field.h>
42 #include <google/protobuf/wire_format.h>
43 #include <google/protobuf/wire_format_lite_inl.h>
44
45 namespace google {
46 namespace protobuf {
47 namespace internal {
48
49 // Implementation of ExtensionFinder which finds extensions in a given
50 // DescriptorPool, using the given MessageFactory to construct sub-objects.
51 // This class is implemented in extension_set_heavy.cc.
52 class DescriptorPoolExtensionFinder : public ExtensionFinder {
53 public:
DescriptorPoolExtensionFinder(const DescriptorPool * pool,MessageFactory * factory,const Descriptor * containing_type)54 DescriptorPoolExtensionFinder(const DescriptorPool* pool,
55 MessageFactory* factory,
56 const Descriptor* containing_type)
57 : pool_(pool), factory_(factory), containing_type_(containing_type) {}
~DescriptorPoolExtensionFinder()58 virtual ~DescriptorPoolExtensionFinder() {}
59
60 virtual bool Find(int number, ExtensionInfo* output);
61
62 private:
63 const DescriptorPool* pool_;
64 MessageFactory* factory_;
65 const Descriptor* containing_type_;
66 };
67
AppendToList(const Descriptor * containing_type,const DescriptorPool * pool,vector<const FieldDescriptor * > * output) const68 void ExtensionSet::AppendToList(const Descriptor* containing_type,
69 const DescriptorPool* pool,
70 vector<const FieldDescriptor*>* output) const {
71 for (map<int, Extension>::const_iterator iter = extensions_.begin();
72 iter != extensions_.end(); ++iter) {
73 bool has = false;
74 if (iter->second.is_repeated) {
75 has = iter->second.GetSize() > 0;
76 } else {
77 has = !iter->second.is_cleared;
78 }
79
80 if (has) {
81 // TODO(kenton): Looking up each field by number is somewhat unfortunate.
82 // Is there a better way? The problem is that descriptors are lazily-
83 // initialized, so they might not even be constructed until
84 // AppendToList() is called.
85
86 if (iter->second.descriptor == NULL) {
87 output->push_back(pool->FindExtensionByNumber(
88 containing_type, iter->first));
89 } else {
90 output->push_back(iter->second.descriptor);
91 }
92 }
93 }
94 }
95
real_type(FieldType type)96 inline FieldDescriptor::Type real_type(FieldType type) {
97 GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
98 return static_cast<FieldDescriptor::Type>(type);
99 }
100
cpp_type(FieldType type)101 inline FieldDescriptor::CppType cpp_type(FieldType type) {
102 return FieldDescriptor::TypeToCppType(
103 static_cast<FieldDescriptor::Type>(type));
104 }
105
106 #define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
107 GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
108 : FieldDescriptor::LABEL_OPTIONAL, \
109 FieldDescriptor::LABEL_##LABEL); \
110 GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
111
GetMessage(int number,const Descriptor * message_type,MessageFactory * factory) const112 const MessageLite& ExtensionSet::GetMessage(int number,
113 const Descriptor* message_type,
114 MessageFactory* factory) const {
115 map<int, Extension>::const_iterator iter = extensions_.find(number);
116 if (iter == extensions_.end() || iter->second.is_cleared) {
117 // Not present. Return the default value.
118 return *factory->GetPrototype(message_type);
119 } else {
120 GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
121 return *iter->second.message_value;
122 }
123 }
124
MutableMessage(const FieldDescriptor * descriptor,MessageFactory * factory)125 MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
126 MessageFactory* factory) {
127 Extension* extension;
128 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
129 extension->type = descriptor->type();
130 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
131 extension->is_repeated = false;
132 extension->is_packed = false;
133 const MessageLite* prototype =
134 factory->GetPrototype(descriptor->message_type());
135 GOOGLE_CHECK(prototype != NULL);
136 extension->message_value = prototype->New();
137 } else {
138 GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
139 }
140 extension->is_cleared = false;
141 return extension->message_value;
142 }
143
AddMessage(const FieldDescriptor * descriptor,MessageFactory * factory)144 MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
145 MessageFactory* factory) {
146 Extension* extension;
147 if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
148 extension->type = descriptor->type();
149 GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
150 extension->is_repeated = true;
151 extension->repeated_message_value =
152 new RepeatedPtrField<MessageLite>();
153 } else {
154 GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
155 }
156
157 // RepeatedPtrField<Message> does not know how to Add() since it cannot
158 // allocate an abstract object, so we have to be tricky.
159 MessageLite* result = extension->repeated_message_value
160 ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
161 if (result == NULL) {
162 const MessageLite* prototype;
163 if (extension->repeated_message_value->size() == 0) {
164 prototype = factory->GetPrototype(descriptor->message_type());
165 GOOGLE_CHECK(prototype != NULL);
166 } else {
167 prototype = &extension->repeated_message_value->Get(0);
168 }
169 result = prototype->New();
170 extension->repeated_message_value->AddAllocated(result);
171 }
172 return result;
173 }
174
ValidateEnumUsingDescriptor(const void * arg,int number)175 static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
176 return reinterpret_cast<const EnumDescriptor*>(arg)
177 ->FindValueByNumber(number) != NULL;
178 }
179
Find(int number,ExtensionInfo * output)180 bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
181 const FieldDescriptor* extension =
182 pool_->FindExtensionByNumber(containing_type_, number);
183 if (extension == NULL) {
184 return false;
185 } else {
186 output->type = extension->type();
187 output->is_repeated = extension->is_repeated();
188 output->is_packed = extension->options().packed();
189 output->descriptor = extension;
190 if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
191 output->message_prototype =
192 factory_->GetPrototype(extension->message_type());
193 GOOGLE_CHECK(output->message_prototype != NULL)
194 << "Extension factory's GetPrototype() returned NULL for extension: "
195 << extension->full_name();
196 } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
197 output->enum_validity_check.func = ValidateEnumUsingDescriptor;
198 output->enum_validity_check.arg = extension->enum_type();
199 }
200
201 return true;
202 }
203 }
204
ParseField(uint32 tag,io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)205 bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
206 const Message* containing_type,
207 UnknownFieldSet* unknown_fields) {
208 UnknownFieldSetFieldSkipper skipper(unknown_fields);
209 if (input->GetExtensionPool() == NULL) {
210 GeneratedExtensionFinder finder(containing_type);
211 return ParseField(tag, input, &finder, &skipper);
212 } else {
213 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
214 input->GetExtensionFactory(),
215 containing_type->GetDescriptor());
216 return ParseField(tag, input, &finder, &skipper);
217 }
218 }
219
ParseMessageSet(io::CodedInputStream * input,const Message * containing_type,UnknownFieldSet * unknown_fields)220 bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
221 const Message* containing_type,
222 UnknownFieldSet* unknown_fields) {
223 UnknownFieldSetFieldSkipper skipper(unknown_fields);
224 if (input->GetExtensionPool() == NULL) {
225 GeneratedExtensionFinder finder(containing_type);
226 return ParseMessageSet(input, &finder, &skipper);
227 } else {
228 DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
229 input->GetExtensionFactory(),
230 containing_type->GetDescriptor());
231 return ParseMessageSet(input, &finder, &skipper);
232 }
233 }
234
SpaceUsedExcludingSelf() const235 int ExtensionSet::SpaceUsedExcludingSelf() const {
236 int total_size =
237 extensions_.size() * sizeof(map<int, Extension>::value_type);
238 for (map<int, Extension>::const_iterator iter = extensions_.begin(),
239 end = extensions_.end();
240 iter != end;
241 ++iter) {
242 total_size += iter->second.SpaceUsedExcludingSelf();
243 }
244 return total_size;
245 }
246
RepeatedMessage_SpaceUsedExcludingSelf(RepeatedPtrFieldBase * field)247 inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
248 RepeatedPtrFieldBase* field) {
249 return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
250 }
251
SpaceUsedExcludingSelf() const252 int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
253 int total_size = 0;
254 if (is_repeated) {
255 switch (cpp_type(type)) {
256 #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
257 case FieldDescriptor::CPPTYPE_##UPPERCASE: \
258 total_size += sizeof(*repeated_##LOWERCASE##_value) + \
259 repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
260 break
261
262 HANDLE_TYPE( INT32, int32);
263 HANDLE_TYPE( INT64, int64);
264 HANDLE_TYPE( UINT32, uint32);
265 HANDLE_TYPE( UINT64, uint64);
266 HANDLE_TYPE( FLOAT, float);
267 HANDLE_TYPE( DOUBLE, double);
268 HANDLE_TYPE( BOOL, bool);
269 HANDLE_TYPE( ENUM, enum);
270 HANDLE_TYPE( STRING, string);
271 #undef HANDLE_TYPE
272
273 case FieldDescriptor::CPPTYPE_MESSAGE:
274 // repeated_message_value is actually a RepeatedPtrField<MessageLite>,
275 // but MessageLite has no SpaceUsed(), so we must directly call
276 // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
277 // handler.
278 total_size += sizeof(*repeated_message_value) +
279 RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
280 break;
281 }
282 } else {
283 switch (cpp_type(type)) {
284 case FieldDescriptor::CPPTYPE_STRING:
285 total_size += sizeof(*string_value) +
286 StringSpaceUsedExcludingSelf(*string_value);
287 break;
288 case FieldDescriptor::CPPTYPE_MESSAGE:
289 total_size += down_cast<Message*>(message_value)->SpaceUsed();
290 break;
291 default:
292 // No extra storage costs for primitive types.
293 break;
294 }
295 }
296 return total_size;
297 }
298
299 // The Serialize*ToArray methods are only needed in the heavy library, as
300 // the lite library only generates SerializeWithCachedSizes.
SerializeWithCachedSizesToArray(int start_field_number,int end_field_number,uint8 * target) const301 uint8* ExtensionSet::SerializeWithCachedSizesToArray(
302 int start_field_number, int end_field_number,
303 uint8* target) const {
304 map<int, Extension>::const_iterator iter;
305 for (iter = extensions_.lower_bound(start_field_number);
306 iter != extensions_.end() && iter->first < end_field_number;
307 ++iter) {
308 target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
309 target);
310 }
311 return target;
312 }
313
SerializeMessageSetWithCachedSizesToArray(uint8 * target) const314 uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
315 uint8* target) const {
316 map<int, Extension>::const_iterator iter;
317 for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
318 target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
319 iter->first, target);
320 }
321 return target;
322 }
323
SerializeFieldWithCachedSizesToArray(int number,uint8 * target) const324 uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
325 int number, uint8* target) const {
326 if (is_repeated) {
327 if (is_packed) {
328 if (cached_size == 0) return target;
329
330 target = WireFormatLite::WriteTagToArray(number,
331 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
332 target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
333
334 switch (real_type(type)) {
335 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
336 case FieldDescriptor::TYPE_##UPPERCASE: \
337 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
338 target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
339 repeated_##LOWERCASE##_value->Get(i), target); \
340 } \
341 break
342
343 HANDLE_TYPE( INT32, Int32, int32);
344 HANDLE_TYPE( INT64, Int64, int64);
345 HANDLE_TYPE( UINT32, UInt32, uint32);
346 HANDLE_TYPE( UINT64, UInt64, uint64);
347 HANDLE_TYPE( SINT32, SInt32, int32);
348 HANDLE_TYPE( SINT64, SInt64, int64);
349 HANDLE_TYPE( FIXED32, Fixed32, uint32);
350 HANDLE_TYPE( FIXED64, Fixed64, uint64);
351 HANDLE_TYPE(SFIXED32, SFixed32, int32);
352 HANDLE_TYPE(SFIXED64, SFixed64, int64);
353 HANDLE_TYPE( FLOAT, Float, float);
354 HANDLE_TYPE( DOUBLE, Double, double);
355 HANDLE_TYPE( BOOL, Bool, bool);
356 HANDLE_TYPE( ENUM, Enum, enum);
357 #undef HANDLE_TYPE
358
359 case WireFormatLite::TYPE_STRING:
360 case WireFormatLite::TYPE_BYTES:
361 case WireFormatLite::TYPE_GROUP:
362 case WireFormatLite::TYPE_MESSAGE:
363 GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
364 break;
365 }
366 } else {
367 switch (real_type(type)) {
368 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
369 case FieldDescriptor::TYPE_##UPPERCASE: \
370 for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
371 target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
372 repeated_##LOWERCASE##_value->Get(i), target); \
373 } \
374 break
375
376 HANDLE_TYPE( INT32, Int32, int32);
377 HANDLE_TYPE( INT64, Int64, int64);
378 HANDLE_TYPE( UINT32, UInt32, uint32);
379 HANDLE_TYPE( UINT64, UInt64, uint64);
380 HANDLE_TYPE( SINT32, SInt32, int32);
381 HANDLE_TYPE( SINT64, SInt64, int64);
382 HANDLE_TYPE( FIXED32, Fixed32, uint32);
383 HANDLE_TYPE( FIXED64, Fixed64, uint64);
384 HANDLE_TYPE(SFIXED32, SFixed32, int32);
385 HANDLE_TYPE(SFIXED64, SFixed64, int64);
386 HANDLE_TYPE( FLOAT, Float, float);
387 HANDLE_TYPE( DOUBLE, Double, double);
388 HANDLE_TYPE( BOOL, Bool, bool);
389 HANDLE_TYPE( STRING, String, string);
390 HANDLE_TYPE( BYTES, Bytes, string);
391 HANDLE_TYPE( ENUM, Enum, enum);
392 HANDLE_TYPE( GROUP, Group, message);
393 HANDLE_TYPE( MESSAGE, Message, message);
394 #undef HANDLE_TYPE
395 }
396 }
397 } else if (!is_cleared) {
398 switch (real_type(type)) {
399 #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
400 case FieldDescriptor::TYPE_##UPPERCASE: \
401 target = WireFormatLite::Write##CAMELCASE##ToArray( \
402 number, VALUE, target); \
403 break
404
405 HANDLE_TYPE( INT32, Int32, int32_value);
406 HANDLE_TYPE( INT64, Int64, int64_value);
407 HANDLE_TYPE( UINT32, UInt32, uint32_value);
408 HANDLE_TYPE( UINT64, UInt64, uint64_value);
409 HANDLE_TYPE( SINT32, SInt32, int32_value);
410 HANDLE_TYPE( SINT64, SInt64, int64_value);
411 HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
412 HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
413 HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
414 HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
415 HANDLE_TYPE( FLOAT, Float, float_value);
416 HANDLE_TYPE( DOUBLE, Double, double_value);
417 HANDLE_TYPE( BOOL, Bool, bool_value);
418 HANDLE_TYPE( STRING, String, *string_value);
419 HANDLE_TYPE( BYTES, Bytes, *string_value);
420 HANDLE_TYPE( ENUM, Enum, enum_value);
421 HANDLE_TYPE( GROUP, Group, *message_value);
422 HANDLE_TYPE( MESSAGE, Message, *message_value);
423 #undef HANDLE_TYPE
424 }
425 }
426 return target;
427 }
428
SerializeMessageSetItemWithCachedSizesToArray(int number,uint8 * target) const429 uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
430 int number,
431 uint8* target) const {
432 if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
433 // Not a valid MessageSet extension, but serialize it the normal way.
434 GOOGLE_LOG(WARNING) << "Invalid message set extension.";
435 return SerializeFieldWithCachedSizesToArray(number, target);
436 }
437
438 if (is_cleared) return target;
439
440 // Start group.
441 target = io::CodedOutputStream::WriteTagToArray(
442 WireFormatLite::kMessageSetItemStartTag, target);
443 // Write type ID.
444 target = WireFormatLite::WriteUInt32ToArray(
445 WireFormatLite::kMessageSetTypeIdNumber, number, target);
446 // Write message.
447 target = WireFormatLite::WriteMessageToArray(
448 WireFormatLite::kMessageSetMessageNumber, *message_value, target);
449 // End group.
450 target = io::CodedOutputStream::WriteTagToArray(
451 WireFormatLite::kMessageSetItemEndTag, target);
452 return target;
453 }
454
455 } // namespace internal
456 } // namespace protobuf
457 } // namespace google
458