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