Line data Source code
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 :
54 0 : void DeleteDefaultUnknownFieldSet() {
55 0 : delete default_unknown_field_set_instance_;
56 0 : }
57 :
58 1 : void InitDefaultUnknownFieldSet() {
59 1 : default_unknown_field_set_instance_ = new UnknownFieldSet();
60 1 : internal::OnShutdown(&DeleteDefaultUnknownFieldSet);
61 1 : }
62 :
63 : GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_);
64 : }
65 :
66 274 : const UnknownFieldSet* UnknownFieldSet::default_instance() {
67 : ::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_,
68 274 : &InitDefaultUnknownFieldSet);
69 274 : return default_unknown_field_set_instance_;
70 : }
71 :
72 1037 : UnknownFieldSet::UnknownFieldSet()
73 1037 : : fields_(NULL) {}
74 :
75 1036 : UnknownFieldSet::~UnknownFieldSet() {
76 : Clear();
77 1036 : delete fields_;
78 1036 : }
79 :
80 809 : void UnknownFieldSet::ClearFallback() {
81 4495 : if (fields_ != NULL) {
82 6563 : for (int i = 0; i < fields_->size(); i++) {
83 2068 : (*fields_)[i].Delete();
84 : }
85 1618 : delete fields_;
86 809 : fields_ = NULL;
87 : }
88 809 : }
89 :
90 0 : void UnknownFieldSet::ClearAndFreeMemory() {
91 0 : if (fields_ != NULL) {
92 : Clear();
93 : }
94 0 : }
95 :
96 2 : void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
97 2 : int other_field_count = other.field_count();
98 2 : if (other_field_count > 0) {
99 4 : fields_ = new vector<UnknownField>();
100 4 : for (int i = 0; i < other_field_count; i++) {
101 6 : fields_->push_back((*other.fields_)[i]);
102 8 : fields_->back().DeepCopy((*other.fields_)[i]);
103 : }
104 : }
105 2 : }
106 :
107 617 : void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
108 617 : int other_field_count = other.field_count();
109 617 : if (other_field_count > 0) {
110 731 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
111 478 : for (int i = 0; i < other_field_count; i++) {
112 1434 : fields_->push_back((*other.fields_)[i]);
113 1912 : fields_->back().DeepCopy((*other.fields_)[i]);
114 : }
115 : }
116 617 : }
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.
120 46 : void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
121 46 : int other_field_count = other->field_count();
122 46 : if (other_field_count > 0) {
123 92 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
124 46 : for (int i = 0; i < other_field_count; i++) {
125 138 : fields_->push_back((*other->fields_)[i]);
126 138 : (*other->fields_)[i].Reset();
127 : }
128 : }
129 92 : delete other->fields_;
130 46 : other->fields_ = NULL;
131 46 : }
132 :
133 0 : int UnknownFieldSet::SpaceUsedExcludingSelf() const {
134 0 : if (fields_ == NULL) return 0;
135 :
136 0 : int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
137 :
138 0 : for (int i = 0; i < fields_->size(); i++) {
139 0 : const UnknownField& field = (*fields_)[i];
140 0 : switch (field.type()) {
141 : case UnknownField::TYPE_LENGTH_DELIMITED:
142 0 : total_size += sizeof(*field.length_delimited_.string_value_) +
143 : internal::StringSpaceUsedExcludingSelf(
144 0 : *field.length_delimited_.string_value_);
145 0 : break;
146 : case UnknownField::TYPE_GROUP:
147 0 : total_size += field.group_->SpaceUsed();
148 0 : break;
149 : default:
150 : break;
151 : }
152 : }
153 : return total_size;
154 : }
155 :
156 0 : int UnknownFieldSet::SpaceUsed() const {
157 0 : return sizeof(*this) + SpaceUsedExcludingSelf();
158 : }
159 :
160 361 : void UnknownFieldSet::AddVarint(int number, uint64 value) {
161 : UnknownField field;
162 361 : field.number_ = number;
163 361 : field.SetType(UnknownField::TYPE_VARINT);
164 361 : field.varint_ = value;
165 709 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
166 361 : fields_->push_back(field);
167 361 : }
168 :
169 18 : void UnknownFieldSet::AddFixed32(int number, uint32 value) {
170 : UnknownField field;
171 18 : field.number_ = number;
172 18 : field.SetType(UnknownField::TYPE_FIXED32);
173 18 : field.fixed32_ = value;
174 31 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
175 18 : fields_->push_back(field);
176 18 : }
177 :
178 18 : void UnknownFieldSet::AddFixed64(int number, uint64 value) {
179 : UnknownField field;
180 18 : field.number_ = number;
181 18 : field.SetType(UnknownField::TYPE_FIXED64);
182 18 : field.fixed64_ = value;
183 29 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
184 18 : fields_->push_back(field);
185 18 : }
186 :
187 154 : string* UnknownFieldSet::AddLengthDelimited(int number) {
188 : UnknownField field;
189 154 : field.number_ = number;
190 154 : field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
191 308 : field.length_delimited_.string_value_ = new string;
192 287 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
193 154 : fields_->push_back(field);
194 154 : return field.length_delimited_.string_value_;
195 : }
196 :
197 :
198 3 : UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
199 : UnknownField field;
200 3 : field.number_ = number;
201 3 : field.SetType(UnknownField::TYPE_GROUP);
202 3 : field.group_ = new UnknownFieldSet;
203 5 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
204 3 : fields_->push_back(field);
205 3 : return field.group_;
206 : }
207 :
208 0 : void UnknownFieldSet::AddField(const UnknownField& field) {
209 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>();
210 0 : fields_->push_back(field);
211 0 : fields_->back().DeepCopy(field);
212 0 : }
213 :
214 0 : void UnknownFieldSet::DeleteSubrange(int start, int num) {
215 : // Delete the specified fields.
216 0 : for (int i = 0; i < num; ++i) {
217 0 : (*fields_)[i + start].Delete();
218 : }
219 : // Slide down the remaining fields.
220 0 : for (int i = start + num; i < fields_->size(); ++i) {
221 0 : (*fields_)[i - num] = (*fields_)[i];
222 : }
223 : // Pop off the # of deleted fields.
224 0 : for (int i = 0; i < num; ++i) {
225 0 : fields_->pop_back();
226 : }
227 0 : if (fields_ && fields_->size() == 0) {
228 : // maintain invariant: never hold fields_ if empty.
229 0 : delete fields_;
230 0 : fields_ = NULL;
231 : }
232 0 : }
233 :
234 0 : void UnknownFieldSet::DeleteByNumber(int number) {
235 0 : if (fields_ == NULL) return;
236 : int left = 0; // The number of fields left after deletion.
237 0 : for (int i = 0; i < fields_->size(); ++i) {
238 0 : UnknownField* field = &(*fields_)[i];
239 0 : if (field->number() == number) {
240 0 : field->Delete();
241 : } else {
242 0 : if (i != left) {
243 0 : (*fields_)[left] = (*fields_)[i];
244 : }
245 0 : ++left;
246 : }
247 : }
248 0 : fields_->resize(left);
249 0 : if (left == 0) {
250 : // maintain invariant: never hold fields_ if empty.
251 0 : delete fields_;
252 0 : fields_ = NULL;
253 : }
254 : }
255 :
256 92 : bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
257 46 : UnknownFieldSet other;
258 92 : if (internal::WireFormat::SkipMessage(input, &other) &&
259 46 : input->ConsumedEntireMessage()) {
260 46 : MergeFromAndDestroy(&other);
261 : return true;
262 : } else {
263 : return false;
264 46 : }
265 : }
266 :
267 46 : bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
268 : Clear();
269 46 : return MergeFromCodedStream(input);
270 : }
271 :
272 46 : bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
273 46 : io::CodedInputStream coded_input(input);
274 92 : return (ParseFromCodedStream(&coded_input) &&
275 92 : coded_input.ConsumedEntireMessage());
276 : }
277 :
278 46 : bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
279 46 : io::ArrayInputStream input(data, size);
280 46 : return ParseFromZeroCopyStream(&input);
281 : }
282 :
283 1034 : void UnknownField::Delete() {
284 1034 : switch (type()) {
285 : case UnknownField::TYPE_LENGTH_DELIMITED:
286 550 : delete length_delimited_.string_value_;
287 : break;
288 : case UnknownField::TYPE_GROUP:
289 5 : delete group_;
290 : break;
291 : default:
292 : break;
293 : }
294 1034 : }
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.
298 46 : void UnknownField::Reset() {
299 46 : switch (type()) {
300 : case UnknownField::TYPE_LENGTH_DELIMITED:
301 21 : length_delimited_.string_value_ = NULL;
302 21 : break;
303 : case UnknownField::TYPE_GROUP: {
304 0 : group_ = NULL;
305 0 : break;
306 : }
307 : default:
308 : break;
309 : }
310 46 : }
311 :
312 480 : void UnknownField::DeepCopy(const UnknownField& other) {
313 480 : switch (type()) {
314 : case UnknownField::TYPE_LENGTH_DELIMITED:
315 : length_delimited_.string_value_ = new string(
316 121 : *length_delimited_.string_value_);
317 121 : break;
318 : case UnknownField::TYPE_GROUP: {
319 2 : UnknownFieldSet* group = new UnknownFieldSet();
320 2 : group->InternalMergeFrom(*group_);
321 2 : group_ = group;
322 2 : break;
323 : }
324 : default:
325 : break;
326 : }
327 480 : }
328 :
329 :
330 0 : void UnknownField::SerializeLengthDelimitedNoTag(
331 : io::CodedOutputStream* output) const {
332 : GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
333 0 : const string& data = *length_delimited_.string_value_;
334 0 : output->WriteVarint32(data.size());
335 0 : output->WriteRawMaybeAliased(data.data(), data.size());
336 0 : }
337 :
338 0 : uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
339 : GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
340 0 : const string& data = *length_delimited_.string_value_;
341 0 : target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
342 0 : target = io::CodedOutputStream::WriteStringToArray(data, target);
343 0 : return target;
344 : }
345 :
346 : } // namespace protobuf
347 : } // namespace google
|