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/common.h>
38 : #include <google/protobuf/io/coded_stream.h>
39 : #include <google/protobuf/io/zero_copy_stream.h>
40 : #include <google/protobuf/io/zero_copy_stream_impl.h>
41 : #include <google/protobuf/wire_format.h>
42 : #include <google/protobuf/stubs/stl_util.h>
43 :
44 : namespace google {
45 : namespace protobuf {
46 :
47 660 : UnknownFieldSet::UnknownFieldSet()
48 660 : : fields_(NULL) {}
49 :
50 1164 : UnknownFieldSet::~UnknownFieldSet() {
51 582 : Clear();
52 582 : delete fields_;
53 582 : }
54 :
55 0 : void UnknownFieldSet::ClearFallback() {
56 0 : GOOGLE_DCHECK(fields_ != NULL);
57 0 : for (int i = 0; i < fields_->size(); i++) {
58 0 : (*fields_)[i].Delete();
59 : }
60 0 : fields_->clear();
61 0 : }
62 :
63 0 : void UnknownFieldSet::ClearAndFreeMemory() {
64 0 : if (fields_ != NULL) {
65 0 : Clear();
66 0 : delete fields_;
67 0 : fields_ = NULL;
68 : }
69 0 : }
70 :
71 0 : void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
72 0 : for (int i = 0; i < other.field_count(); i++) {
73 0 : AddField(other.field(i));
74 : }
75 0 : }
76 :
77 0 : int UnknownFieldSet::SpaceUsedExcludingSelf() const {
78 0 : if (fields_ == NULL) return 0;
79 :
80 0 : int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
81 0 : for (int i = 0; i < fields_->size(); i++) {
82 0 : const UnknownField& field = (*fields_)[i];
83 0 : switch (field.type()) {
84 : case UnknownField::TYPE_LENGTH_DELIMITED:
85 0 : total_size += sizeof(*field.length_delimited_.string_value_) +
86 0 : internal::StringSpaceUsedExcludingSelf(
87 0 : *field.length_delimited_.string_value_);
88 0 : break;
89 : case UnknownField::TYPE_GROUP:
90 0 : total_size += field.group_->SpaceUsed();
91 0 : break;
92 : default:
93 0 : break;
94 : }
95 : }
96 0 : return total_size;
97 : }
98 :
99 0 : int UnknownFieldSet::SpaceUsed() const {
100 0 : return sizeof(*this) + SpaceUsedExcludingSelf();
101 : }
102 :
103 0 : void UnknownFieldSet::AddVarint(int number, uint64 value) {
104 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>;
105 : UnknownField field;
106 0 : field.number_ = number;
107 0 : field.SetType(UnknownField::TYPE_VARINT);
108 0 : field.varint_ = value;
109 0 : fields_->push_back(field);
110 0 : }
111 :
112 0 : void UnknownFieldSet::AddFixed32(int number, uint32 value) {
113 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>;
114 : UnknownField field;
115 0 : field.number_ = number;
116 0 : field.SetType(UnknownField::TYPE_FIXED32);
117 0 : field.fixed32_ = value;
118 0 : fields_->push_back(field);
119 0 : }
120 :
121 0 : void UnknownFieldSet::AddFixed64(int number, uint64 value) {
122 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>;
123 : UnknownField field;
124 0 : field.number_ = number;
125 0 : field.SetType(UnknownField::TYPE_FIXED64);
126 0 : field.fixed64_ = value;
127 0 : fields_->push_back(field);
128 0 : }
129 :
130 0 : string* UnknownFieldSet::AddLengthDelimited(int number) {
131 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>;
132 : UnknownField field;
133 0 : field.number_ = number;
134 0 : field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
135 0 : field.length_delimited_.string_value_ = new string;
136 0 : fields_->push_back(field);
137 0 : return field.length_delimited_.string_value_;
138 : }
139 :
140 :
141 0 : UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
142 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>;
143 : UnknownField field;
144 0 : field.number_ = number;
145 0 : field.SetType(UnknownField::TYPE_GROUP);
146 0 : field.group_ = new UnknownFieldSet;
147 0 : fields_->push_back(field);
148 0 : return field.group_;
149 : }
150 :
151 0 : void UnknownFieldSet::AddField(const UnknownField& field) {
152 0 : if (fields_ == NULL) fields_ = new vector<UnknownField>;
153 0 : fields_->push_back(field);
154 0 : fields_->back().DeepCopy();
155 0 : }
156 :
157 0 : void UnknownFieldSet::DeleteSubrange(int start, int num) {
158 0 : GOOGLE_DCHECK(fields_ != NULL);
159 : // Delete the specified fields.
160 0 : for (int i = 0; i < num; ++i) {
161 0 : (*fields_)[i + start].Delete();
162 : }
163 : // Slide down the remaining fields.
164 0 : for (int i = start + num; i < fields_->size(); ++i) {
165 0 : (*fields_)[i - num] = (*fields_)[i];
166 : }
167 : // Pop off the # of deleted fields.
168 0 : for (int i = 0; i < num; ++i) {
169 0 : fields_->pop_back();
170 : }
171 0 : }
172 :
173 0 : void UnknownFieldSet::DeleteByNumber(int number) {
174 0 : if (fields_ == NULL) return;
175 0 : int left = 0; // The number of fields left after deletion.
176 0 : for (int i = 0; i < fields_->size(); ++i) {
177 0 : UnknownField* field = &(*fields_)[i];
178 0 : if (field->number() == number) {
179 0 : field->Delete();
180 : } else {
181 0 : if (i != left) {
182 0 : (*fields_)[left] = (*fields_)[i];
183 : }
184 0 : ++left;
185 : }
186 : }
187 0 : fields_->resize(left);
188 : }
189 :
190 0 : bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
191 0 : UnknownFieldSet other;
192 0 : if (internal::WireFormat::SkipMessage(input, &other) &&
193 0 : input->ConsumedEntireMessage()) {
194 0 : MergeFrom(other);
195 0 : return true;
196 : } else {
197 0 : return false;
198 : }
199 : }
200 :
201 0 : bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
202 0 : Clear();
203 0 : return MergeFromCodedStream(input);
204 : }
205 :
206 0 : bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
207 0 : io::CodedInputStream coded_input(input);
208 0 : return (ParseFromCodedStream(&coded_input) &&
209 0 : coded_input.ConsumedEntireMessage());
210 : }
211 :
212 0 : bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
213 0 : io::ArrayInputStream input(data, size);
214 0 : return ParseFromZeroCopyStream(&input);
215 : }
216 :
217 0 : void UnknownField::Delete() {
218 0 : switch (type()) {
219 : case UnknownField::TYPE_LENGTH_DELIMITED:
220 0 : delete length_delimited_.string_value_;
221 0 : break;
222 : case UnknownField::TYPE_GROUP:
223 0 : delete group_;
224 0 : break;
225 : default:
226 0 : break;
227 : }
228 0 : }
229 :
230 0 : void UnknownField::DeepCopy() {
231 0 : switch (type()) {
232 : case UnknownField::TYPE_LENGTH_DELIMITED:
233 0 : length_delimited_.string_value_ = new string(
234 0 : *length_delimited_.string_value_);
235 0 : break;
236 : case UnknownField::TYPE_GROUP: {
237 0 : UnknownFieldSet* group = new UnknownFieldSet;
238 0 : group->MergeFrom(*group_);
239 0 : group_ = group;
240 0 : break;
241 : }
242 : default:
243 0 : break;
244 : }
245 0 : }
246 :
247 :
248 0 : void UnknownField::SerializeLengthDelimitedNoTag(
249 : io::CodedOutputStream* output) const {
250 0 : GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
251 0 : const string& data = *length_delimited_.string_value_;
252 0 : output->WriteVarint32(data.size());
253 0 : output->WriteRawMaybeAliased(data.data(), data.size());
254 0 : }
255 :
256 0 : uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
257 0 : GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
258 0 : const string& data = *length_delimited_.string_value_;
259 0 : target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
260 0 : target = io::CodedOutputStream::WriteStringToArray(data, target);
261 0 : return target;
262 : }
263 :
264 : } // namespace protobuf
265 : } // namespace google
|