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