• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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