1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
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
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.
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.
31
// Author: kenton@google.com (Kenton Varda)
32
// Based on original Protocol Buffers design by
33
// Sanjay Ghemawat, Jeff Dean, and others.
35
// Contains methods defined in extension_set.h which cannot be part of the
36
// lite library because they use descriptors or reflection.
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>
48
void ExtensionSet::AppendToList(const Descriptor* containing_type,
49
const DescriptorPool* pool,
50
vector<const FieldDescriptor*>* output) const {
51
for (map<int, Extension>::const_iterator iter = extensions_.begin();
52
iter != extensions_.end(); ++iter) {
54
if (iter->second.is_repeated) {
55
has = iter->second.GetSize() > 0;
57
has = !iter->second.is_cleared;
62
pool->FindExtensionByNumber(containing_type, iter->first));
67
inline FieldDescriptor::CppType cpp_type(FieldType type) {
68
return FieldDescriptor::TypeToCppType(
69
static_cast<FieldDescriptor::Type>(type));
72
#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
73
GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
74
: FieldDescriptor::LABEL_OPTIONAL, \
75
FieldDescriptor::LABEL_##LABEL); \
76
GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
78
const MessageLite& ExtensionSet::GetMessage(int number,
79
const Descriptor* message_type,
80
MessageFactory* factory) const {
81
map<int, Extension>::const_iterator iter = extensions_.find(number);
82
if (iter == extensions_.end() || iter->second.is_cleared) {
83
// Not present. Return the default value.
84
return *factory->GetPrototype(message_type);
86
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
87
return *iter->second.message_value;
91
MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
92
const Descriptor* message_type,
93
MessageFactory* factory) {
95
if (MaybeNewExtension(number, &extension)) {
96
extension->type = type;
97
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
98
extension->is_repeated = false;
99
extension->is_packed = false;
100
const MessageLite* prototype = factory->GetPrototype(message_type);
101
GOOGLE_CHECK(prototype != NULL);
102
extension->message_value = prototype->New();
104
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
106
extension->is_cleared = false;
107
return extension->message_value;
110
MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
111
const Descriptor* message_type,
112
MessageFactory* factory) {
113
Extension* extension;
114
if (MaybeNewExtension(number, &extension)) {
115
extension->type = type;
116
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
117
extension->is_repeated = true;
118
extension->repeated_message_value =
119
new RepeatedPtrField<MessageLite>();
121
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
124
// RepeatedPtrField<Message> does not know how to Add() since it cannot
125
// allocate an abstract object, so we have to be tricky.
126
MessageLite* result = extension->repeated_message_value
127
->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
128
if (result == NULL) {
129
const MessageLite* prototype;
130
if (extension->repeated_message_value->size() == 0) {
131
prototype = factory->GetPrototype(message_type);
132
GOOGLE_CHECK(prototype != NULL);
134
prototype = &extension->repeated_message_value->Get(0);
136
result = prototype->New();
137
extension->repeated_message_value->AddAllocated(result);
142
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
143
const MessageLite* containing_type,
144
UnknownFieldSet* unknown_fields) {
145
UnknownFieldSetFieldSkipper skipper(unknown_fields);
146
return ParseField(tag, input, containing_type, &skipper);
149
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
150
const MessageLite* containing_type,
151
UnknownFieldSet* unknown_fields) {
152
UnknownFieldSetFieldSkipper skipper(unknown_fields);
153
return ParseMessageSet(input, containing_type, &skipper);
156
int ExtensionSet::SpaceUsedExcludingSelf() const {
158
extensions_.size() * sizeof(map<int, Extension>::value_type);
159
for (map<int, Extension>::const_iterator iter = extensions_.begin(),
160
end = extensions_.end();
163
total_size += iter->second.SpaceUsedExcludingSelf();
168
inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf(
169
RepeatedPtrFieldBase* field) {
170
return field->SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
173
int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
176
switch (cpp_type(type)) {
177
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
178
case WireFormatLite::CPPTYPE_##UPPERCASE: \
179
total_size += sizeof(*repeated_##LOWERCASE##_value) + \
180
repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
183
HANDLE_TYPE( INT32, int32);
184
HANDLE_TYPE( INT64, int64);
185
HANDLE_TYPE( UINT32, uint32);
186
HANDLE_TYPE( UINT64, uint64);
187
HANDLE_TYPE( FLOAT, float);
188
HANDLE_TYPE( DOUBLE, double);
189
HANDLE_TYPE( BOOL, bool);
190
HANDLE_TYPE( ENUM, enum);
191
HANDLE_TYPE( STRING, string);
193
case WireFormatLite::CPPTYPE_MESSAGE:
194
// repeated_message_value is actually a RepeatedPtrField<MessageLite>,
195
// but MessageLite has no SpaceUsed(), so we must directly call
196
// RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
198
total_size += sizeof(*repeated_message_value) +
199
RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value);
203
switch (cpp_type(type)) {
204
case WireFormatLite::CPPTYPE_STRING:
205
total_size += sizeof(*string_value) +
206
StringSpaceUsedExcludingSelf(*string_value);
208
case WireFormatLite::CPPTYPE_MESSAGE:
209
total_size += down_cast<Message*>(message_value)->SpaceUsed();
212
// No extra storage costs for primitive types.
219
} // namespace internal
220
} // namespace protobuf
221
} // namespace google