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/io/zero_copy_stream_impl_lite.h>
43#include <google/protobuf/extension_set.h>
44#include <google/protobuf/generated_message_tctable_decl.h>
45#include <google/protobuf/generated_message_tctable_impl.h>
46#include <google/protobuf/parse_context.h>
47#include <google/protobuf/wire_format.h>
48#include <google/protobuf/wire_format_lite.h>
49#include <google/protobuf/stubs/stl_util.h>
50
51// Must be included last.
52#include <google/protobuf/port_def.inc>
53
54namespace google {
55namespace protobuf {
56
57const UnknownFieldSet& UnknownFieldSet::default_instance() {
58 static auto instance = internal::OnShutdownDelete(p: new UnknownFieldSet());
59 return *instance;
60}
61
62void UnknownFieldSet::ClearFallback() {
63 GOOGLE_DCHECK(!fields_.empty());
64 int n = fields_.size();
65 do {
66 (fields_)[--n].Delete();
67 } while (n > 0);
68 fields_.clear();
69}
70
71void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
72 int other_field_count = other.field_count();
73 if (other_field_count > 0) {
74 fields_.reserve(n: fields_.size() + other_field_count);
75 for (int i = 0; i < other_field_count; i++) {
76 fields_.push_back(x: (other.fields_)[i]);
77 fields_.back().DeepCopy(other: (other.fields_)[i]);
78 }
79 }
80}
81
82void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
83 int other_field_count = other.field_count();
84 if (other_field_count > 0) {
85 fields_.reserve(n: fields_.size() + other_field_count);
86 for (int i = 0; i < other_field_count; i++) {
87 fields_.push_back(x: (other.fields_)[i]);
88 fields_.back().DeepCopy(other: (other.fields_)[i]);
89 }
90 }
91}
92
93// A specialized MergeFrom for performance when we are merging from an UFS that
94// is temporary and can be destroyed in the process.
95void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
96 if (fields_.empty()) {
97 fields_ = std::move(other->fields_);
98 } else {
99 fields_.insert(position: fields_.end(),
100 first: std::make_move_iterator(i: other->fields_.begin()),
101 last: std::make_move_iterator(i: other->fields_.end()));
102 }
103 other->fields_.clear();
104}
105
106void UnknownFieldSet::MergeToInternalMetadata(
107 const UnknownFieldSet& other, internal::InternalMetadata* metadata) {
108 metadata->mutable_unknown_fields<UnknownFieldSet>()->MergeFrom(other);
109}
110
111size_t UnknownFieldSet::SpaceUsedExcludingSelfLong() const {
112 if (fields_.empty()) return 0;
113
114 size_t total_size = sizeof(UnknownField) * fields_.capacity();
115
116 for (const UnknownField& field : fields_) {
117 switch (field.type()) {
118 case UnknownField::TYPE_LENGTH_DELIMITED:
119 total_size += sizeof(*field.data_.length_delimited_.string_value) +
120 internal::StringSpaceUsedExcludingSelfLong(
121 str: *field.data_.length_delimited_.string_value);
122 break;
123 case UnknownField::TYPE_GROUP:
124 total_size += field.data_.group_->SpaceUsedLong();
125 break;
126 default:
127 break;
128 }
129 }
130 return total_size;
131}
132
133size_t UnknownFieldSet::SpaceUsedLong() const {
134 return sizeof(*this) + SpaceUsedExcludingSelf();
135}
136
137void UnknownFieldSet::AddVarint(int number, uint64_t value) {
138 UnknownField field;
139 field.number_ = number;
140 field.SetType(UnknownField::TYPE_VARINT);
141 field.data_.varint_ = value;
142 fields_.push_back(x: field);
143}
144
145void UnknownFieldSet::AddFixed32(int number, uint32_t value) {
146 UnknownField field;
147 field.number_ = number;
148 field.SetType(UnknownField::TYPE_FIXED32);
149 field.data_.fixed32_ = value;
150 fields_.push_back(x: field);
151}
152
153void UnknownFieldSet::AddFixed64(int number, uint64_t value) {
154 UnknownField field;
155 field.number_ = number;
156 field.SetType(UnknownField::TYPE_FIXED64);
157 field.data_.fixed64_ = value;
158 fields_.push_back(x: field);
159}
160
161std::string* UnknownFieldSet::AddLengthDelimited(int number) {
162 UnknownField field;
163 field.number_ = number;
164 field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
165 field.data_.length_delimited_.string_value = new std::string;
166 fields_.push_back(x: field);
167 return field.data_.length_delimited_.string_value;
168}
169
170
171UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
172 UnknownField field;
173 field.number_ = number;
174 field.SetType(UnknownField::TYPE_GROUP);
175 field.data_.group_ = new UnknownFieldSet;
176 fields_.push_back(x: field);
177 return field.data_.group_;
178}
179
180void UnknownFieldSet::AddField(const UnknownField& field) {
181 fields_.push_back(x: field);
182 fields_.back().DeepCopy(other: field);
183}
184
185void UnknownFieldSet::DeleteSubrange(int start, int num) {
186 // Delete the specified fields.
187 for (int i = 0; i < num; ++i) {
188 (fields_)[i + start].Delete();
189 }
190 // Slide down the remaining fields.
191 for (size_t i = start + num; i < fields_.size(); ++i) {
192 (fields_)[i - num] = (fields_)[i];
193 }
194 // Pop off the # of deleted fields.
195 for (int i = 0; i < num; ++i) {
196 fields_.pop_back();
197 }
198}
199
200void UnknownFieldSet::DeleteByNumber(int number) {
201 size_t left = 0; // The number of fields left after deletion.
202 for (size_t i = 0; i < fields_.size(); ++i) {
203 UnknownField* field = &(fields_)[i];
204 if (field->number() == number) {
205 field->Delete();
206 } else {
207 if (i != left) {
208 (fields_)[left] = (fields_)[i];
209 }
210 ++left;
211 }
212 }
213 fields_.resize(new_size: left);
214}
215
216bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
217 UnknownFieldSet other;
218 if (internal::WireFormat::SkipMessage(input, unknown_fields: &other) &&
219 input->ConsumedEntireMessage()) {
220 MergeFromAndDestroy(other: &other);
221 return true;
222 } else {
223 return false;
224 }
225}
226
227bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
228 Clear();
229 return MergeFromCodedStream(input);
230}
231
232bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
233 io::CodedInputStream coded_input(input);
234 return (ParseFromCodedStream(input: &coded_input) &&
235 coded_input.ConsumedEntireMessage());
236}
237
238bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
239 io::ArrayInputStream input(data, size);
240 return ParseFromZeroCopyStream(input: &input);
241}
242
243bool UnknownFieldSet::SerializeToString(std::string* output) const {
244 const size_t size =
245 google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(unknown_fields: *this);
246 STLStringResizeUninitializedAmortized(s: output, new_size: size);
247 google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
248 unknown_fields: *this, target: reinterpret_cast<uint8_t*>(const_cast<char*>(output->data())));
249 return true;
250}
251
252bool UnknownFieldSet::SerializeToCodedStream(
253 io::CodedOutputStream* output) const {
254 google::protobuf::internal::WireFormat::SerializeUnknownFields(unknown_fields: *this, output);
255 return !output->HadError();
256}
257void UnknownField::Delete() {
258 switch (type()) {
259 case UnknownField::TYPE_LENGTH_DELIMITED:
260 delete data_.length_delimited_.string_value;
261 break;
262 case UnknownField::TYPE_GROUP:
263 delete data_.group_;
264 break;
265 default:
266 break;
267 }
268}
269
270void UnknownField::DeepCopy(const UnknownField& other) {
271 (void)other; // Parameter is used by Google-internal code.
272 switch (type()) {
273 case UnknownField::TYPE_LENGTH_DELIMITED:
274 data_.length_delimited_.string_value =
275 new std::string(*data_.length_delimited_.string_value);
276 break;
277 case UnknownField::TYPE_GROUP: {
278 UnknownFieldSet* group = new UnknownFieldSet();
279 group->InternalMergeFrom(other: *data_.group_);
280 data_.group_ = group;
281 break;
282 }
283 default:
284 break;
285 }
286}
287
288
289uint8_t* UnknownField::InternalSerializeLengthDelimitedNoTag(
290 uint8_t* target, io::EpsCopyOutputStream* stream) const {
291 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
292 const std::string& data = *data_.length_delimited_.string_value;
293 target = io::CodedOutputStream::WriteVarint32ToArray(value: data.size(), target);
294 target = stream->WriteRaw(data: data.data(), size: data.size(), ptr: target);
295 return target;
296}
297
298namespace internal {
299
300class UnknownFieldParserHelper {
301 public:
302 explicit UnknownFieldParserHelper(UnknownFieldSet* unknown)
303 : unknown_(unknown) {}
304
305 void AddVarint(uint32_t num, uint64_t value) {
306 unknown_->AddVarint(number: num, value);
307 }
308 void AddFixed64(uint32_t num, uint64_t value) {
309 unknown_->AddFixed64(number: num, value);
310 }
311 const char* ParseLengthDelimited(uint32_t num, const char* ptr,
312 ParseContext* ctx) {
313 std::string* s = unknown_->AddLengthDelimited(number: num);
314 int size = ReadSize(pp: &ptr);
315 GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
316 return ctx->ReadString(ptr, size, s);
317 }
318 const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) {
319 UnknownFieldParserHelper child(unknown_->AddGroup(number: num));
320 return ctx->ParseGroup(msg: &child, ptr, tag: num * 8 + 3);
321 }
322 void AddFixed32(uint32_t num, uint32_t value) {
323 unknown_->AddFixed32(number: num, value);
324 }
325
326 const char* _InternalParse(const char* ptr, ParseContext* ctx) {
327 return WireFormatParser(field_parser&: *this, ptr, ctx);
328 }
329
330 private:
331 UnknownFieldSet* unknown_;
332};
333
334const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr,
335 ParseContext* ctx) {
336 UnknownFieldParserHelper field_parser(unknown);
337 return WireFormatParser(field_parser, ptr, ctx);
338}
339
340const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown,
341 const char* ptr, ParseContext* ctx) {
342 UnknownFieldParserHelper field_parser(unknown);
343 return FieldParser(tag, field_parser, ptr, ctx);
344}
345
346} // namespace internal
347} // namespace protobuf
348} // namespace google
349
350#include <google/protobuf/port_undef.inc>
351