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 #include <google/protobuf/unknown_field_set.h>
36
37 #include <google/protobuf/stubs/logging.h>
38 #include <google/protobuf/stubs/common.h>
39 #include <google/protobuf/io/coded_stream.h>
40 #include <google/protobuf/io/zero_copy_stream.h>
41 #include <google/protobuf/io/zero_copy_stream_impl.h>
42 #include <google/protobuf/wire_format.h>
43 #include <google/protobuf/stubs/stl_util.h>
44
45 namespace google {
46 namespace protobuf {
47
48 namespace {
49 // This global instance is returned by unknown_fields() on any message class
50 // when the object has no unknown fields. This is necessary because we now
51 // instantiate the UnknownFieldSet dynamically only when required.
52 UnknownFieldSet* default_unknown_field_set_instance_ = NULL;
53
DeleteDefaultUnknownFieldSet()54 void DeleteDefaultUnknownFieldSet() {
55 delete default_unknown_field_set_instance_;
56 }
57
InitDefaultUnknownFieldSet()58 void InitDefaultUnknownFieldSet() {
59 default_unknown_field_set_instance_ = new UnknownFieldSet();
60 internal::OnShutdown(&DeleteDefaultUnknownFieldSet);
61 }
62
63 GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_);
64 }
65
default_instance()66 const UnknownFieldSet* UnknownFieldSet::default_instance() {
67 ::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_,
68 &InitDefaultUnknownFieldSet);
69 return default_unknown_field_set_instance_;
70 }
71
UnknownFieldSet()72 UnknownFieldSet::UnknownFieldSet()
73 : fields_(NULL) {}
74
~UnknownFieldSet()75 UnknownFieldSet::~UnknownFieldSet() {
76 Clear();
77 delete fields_;
78 }
79
ClearFallback()80 void UnknownFieldSet::ClearFallback() {
81 if (fields_ != NULL) {
82 for (int i = 0; i < fields_->size(); i++) {
83 (*fields_)[i].Delete();
84 }
85 delete fields_;
86 fields_ = NULL;
87 }
88 }
89
ClearAndFreeMemory()90 void UnknownFieldSet::ClearAndFreeMemory() {
91 if (fields_ != NULL) {
92 Clear();
93 }
94 }
95
InternalMergeFrom(const UnknownFieldSet & other)96 void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
97 int other_field_count = other.field_count();
98 if (other_field_count > 0) {
99 fields_ = new vector<UnknownField>();
100 for (int i = 0; i < other_field_count; i++) {
101 fields_->push_back((*other.fields_)[i]);
102 fields_->back().DeepCopy((*other.fields_)[i]);
103 }
104 }
105 }
106
MergeFrom(const UnknownFieldSet & other)107 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
108 int other_field_count = other.field_count();
109 if (other_field_count > 0) {
110 if (fields_ == NULL) fields_ = new vector<UnknownField>();
111 for (int i = 0; i < other_field_count; i++) {
112 fields_->push_back((*other.fields_)[i]);
113 fields_->back().DeepCopy((*other.fields_)[i]);
114 }
115 }
116 }
117
118 // A specialized MergeFrom for performance when we are merging from an UFS that
119 // is temporary and can be destroyed in the process.
MergeFromAndDestroy(UnknownFieldSet * other)120 void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
121 int other_field_count = other->field_count();
122 if (other_field_count > 0) {
123 if (fields_ == NULL) fields_ = new vector<UnknownField>();
124 for (int i = 0; i < other_field_count; i++) {
125 fields_->push_back((*other->fields_)[i]);
126 (*other->fields_)[i].Reset();
127 }
128 }
129 delete other->fields_;
130 other->fields_ = NULL;
131 }
132
SpaceUsedExcludingSelf() const133 int UnknownFieldSet::SpaceUsedExcludingSelf() const {
134 if (fields_ == NULL) return 0;
135
136 int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
137
138 for (int i = 0; i < fields_->size(); i++) {
139 const UnknownField& field = (*fields_)[i];
140 switch (field.type()) {
141 case UnknownField::TYPE_LENGTH_DELIMITED:
142 total_size += sizeof(*field.length_delimited_.string_value_) +
143 internal::StringSpaceUsedExcludingSelf(
144 *field.length_delimited_.string_value_);
145 break;
146 case UnknownField::TYPE_GROUP:
147 total_size += field.group_->SpaceUsed();
148 break;
149 default:
150 break;
151 }
152 }
153 return total_size;
154 }
155
SpaceUsed() const156 int UnknownFieldSet::SpaceUsed() const {
157 return sizeof(*this) + SpaceUsedExcludingSelf();
158 }
159
AddVarint(int number,uint64 value)160 void UnknownFieldSet::AddVarint(int number, uint64 value) {
161 UnknownField field;
162 field.number_ = number;
163 field.SetType(UnknownField::TYPE_VARINT);
164 field.varint_ = value;
165 if (fields_ == NULL) fields_ = new vector<UnknownField>();
166 fields_->push_back(field);
167 }
168
AddFixed32(int number,uint32 value)169 void UnknownFieldSet::AddFixed32(int number, uint32 value) {
170 UnknownField field;
171 field.number_ = number;
172 field.SetType(UnknownField::TYPE_FIXED32);
173 field.fixed32_ = value;
174 if (fields_ == NULL) fields_ = new vector<UnknownField>();
175 fields_->push_back(field);
176 }
177
AddFixed64(int number,uint64 value)178 void UnknownFieldSet::AddFixed64(int number, uint64 value) {
179 UnknownField field;
180 field.number_ = number;
181 field.SetType(UnknownField::TYPE_FIXED64);
182 field.fixed64_ = value;
183 if (fields_ == NULL) fields_ = new vector<UnknownField>();
184 fields_->push_back(field);
185 }
186
AddLengthDelimited(int number)187 string* UnknownFieldSet::AddLengthDelimited(int number) {
188 UnknownField field;
189 field.number_ = number;
190 field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
191 field.length_delimited_.string_value_ = new string;
192 if (fields_ == NULL) fields_ = new vector<UnknownField>();
193 fields_->push_back(field);
194 return field.length_delimited_.string_value_;
195 }
196
197
AddGroup(int number)198 UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
199 UnknownField field;
200 field.number_ = number;
201 field.SetType(UnknownField::TYPE_GROUP);
202 field.group_ = new UnknownFieldSet;
203 if (fields_ == NULL) fields_ = new vector<UnknownField>();
204 fields_->push_back(field);
205 return field.group_;
206 }
207
AddField(const UnknownField & field)208 void UnknownFieldSet::AddField(const UnknownField& field) {
209 if (fields_ == NULL) fields_ = new vector<UnknownField>();
210 fields_->push_back(field);
211 fields_->back().DeepCopy(field);
212 }
213
DeleteSubrange(int start,int num)214 void UnknownFieldSet::DeleteSubrange(int start, int num) {
215 // Delete the specified fields.
216 for (int i = 0; i < num; ++i) {
217 (*fields_)[i + start].Delete();
218 }
219 // Slide down the remaining fields.
220 for (int i = start + num; i < fields_->size(); ++i) {
221 (*fields_)[i - num] = (*fields_)[i];
222 }
223 // Pop off the # of deleted fields.
224 for (int i = 0; i < num; ++i) {
225 fields_->pop_back();
226 }
227 if (fields_ && fields_->size() == 0) {
228 // maintain invariant: never hold fields_ if empty.
229 delete fields_;
230 fields_ = NULL;
231 }
232 }
233
DeleteByNumber(int number)234 void UnknownFieldSet::DeleteByNumber(int number) {
235 if (fields_ == NULL) return;
236 int left = 0; // The number of fields left after deletion.
237 for (int i = 0; i < fields_->size(); ++i) {
238 UnknownField* field = &(*fields_)[i];
239 if (field->number() == number) {
240 field->Delete();
241 } else {
242 if (i != left) {
243 (*fields_)[left] = (*fields_)[i];
244 }
245 ++left;
246 }
247 }
248 fields_->resize(left);
249 if (left == 0) {
250 // maintain invariant: never hold fields_ if empty.
251 delete fields_;
252 fields_ = NULL;
253 }
254 }
255
MergeFromCodedStream(io::CodedInputStream * input)256 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
257 UnknownFieldSet other;
258 if (internal::WireFormat::SkipMessage(input, &other) &&
259 input->ConsumedEntireMessage()) {
260 MergeFromAndDestroy(&other);
261 return true;
262 } else {
263 return false;
264 }
265 }
266
ParseFromCodedStream(io::CodedInputStream * input)267 bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
268 Clear();
269 return MergeFromCodedStream(input);
270 }
271
ParseFromZeroCopyStream(io::ZeroCopyInputStream * input)272 bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
273 io::CodedInputStream coded_input(input);
274 return (ParseFromCodedStream(&coded_input) &&
275 coded_input.ConsumedEntireMessage());
276 }
277
ParseFromArray(const void * data,int size)278 bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
279 io::ArrayInputStream input(data, size);
280 return ParseFromZeroCopyStream(&input);
281 }
282
Delete()283 void UnknownField::Delete() {
284 switch (type()) {
285 case UnknownField::TYPE_LENGTH_DELIMITED:
286 delete length_delimited_.string_value_;
287 break;
288 case UnknownField::TYPE_GROUP:
289 delete group_;
290 break;
291 default:
292 break;
293 }
294 }
295
296 // Reset all owned ptrs, a special function for performance, to avoid double
297 // owning the ptrs, when we merge from a temporary UnknownFieldSet objects.
Reset()298 void UnknownField::Reset() {
299 switch (type()) {
300 case UnknownField::TYPE_LENGTH_DELIMITED:
301 length_delimited_.string_value_ = NULL;
302 break;
303 case UnknownField::TYPE_GROUP: {
304 group_ = NULL;
305 break;
306 }
307 default:
308 break;
309 }
310 }
311
DeepCopy(const UnknownField & other)312 void UnknownField::DeepCopy(const UnknownField& other) {
313 switch (type()) {
314 case UnknownField::TYPE_LENGTH_DELIMITED:
315 length_delimited_.string_value_ = new string(
316 *length_delimited_.string_value_);
317 break;
318 case UnknownField::TYPE_GROUP: {
319 UnknownFieldSet* group = new UnknownFieldSet();
320 group->InternalMergeFrom(*group_);
321 group_ = group;
322 break;
323 }
324 default:
325 break;
326 }
327 }
328
329
SerializeLengthDelimitedNoTag(io::CodedOutputStream * output) const330 void UnknownField::SerializeLengthDelimitedNoTag(
331 io::CodedOutputStream* output) const {
332 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
333 const string& data = *length_delimited_.string_value_;
334 output->WriteVarint32(data.size());
335 output->WriteRawMaybeAliased(data.data(), data.size());
336 }
337
SerializeLengthDelimitedNoTagToArray(uint8 * target) const338 uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
339 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
340 const string& data = *length_delimited_.string_value_;
341 target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
342 target = io::CodedOutputStream::WriteStringToArray(data, target);
343 return target;
344 }
345
346 } // namespace protobuf
347 } // namespace google
348