• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include "google/protobuf/unknown_field_set.h"
13 
14 #include <cstring>
15 #include <string>
16 #include <utility>
17 
18 #include "absl/log/absl_check.h"
19 #include "absl/strings/cord.h"
20 #include "absl/strings/internal/resize_uninitialized.h"
21 #include "absl/strings/string_view.h"
22 #include "google/protobuf/extension_set.h"
23 #include "google/protobuf/generated_message_tctable_impl.h"
24 #include "google/protobuf/io/coded_stream.h"
25 #include "google/protobuf/io/zero_copy_stream.h"
26 #include "google/protobuf/io/zero_copy_stream_impl.h"
27 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
28 #include "google/protobuf/parse_context.h"
29 #include "google/protobuf/wire_format.h"
30 #include "google/protobuf/wire_format_lite.h"
31 
32 // Must be included last.
33 #include "google/protobuf/port_def.inc"
34 
35 namespace google {
36 namespace protobuf {
37 
ClearFallback()38 void UnknownFieldSet::ClearFallback() {
39   ABSL_DCHECK(!fields_.empty());
40   if (arena() == nullptr) {
41     int n = fields_.size();
42     do {
43       (fields_)[--n].Delete();
44     } while (n > 0);
45   }
46   fields_.Clear();
47 }
48 
MergeFrom(const UnknownFieldSet & other)49 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
50   int other_field_count = other.field_count();
51   if (other_field_count > 0) {
52     fields_.Reserve(fields_.size() + other_field_count);
53     for (auto elem : other.fields_) {
54       fields_.Add(elem.DeepCopy(arena()));
55     }
56   }
57 }
58 
59 // A specialized MergeFrom for performance when we are merging from an UFS that
60 // is temporary and can be destroyed in the process.
MergeFromAndDestroy(UnknownFieldSet * other)61 void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
62   if (arena() != other->arena()) {
63     MergeFrom(*other);
64   } else if (fields_.empty()) {
65     fields_.Swap(&other->fields_);
66   } else {
67     fields_.MergeFrom(other->fields_);
68     other->fields_.Clear();
69   }
70 }
71 
MergeToInternalMetadata(const UnknownFieldSet & other,internal::InternalMetadata * metadata)72 void UnknownFieldSet::MergeToInternalMetadata(
73     const UnknownFieldSet& other, internal::InternalMetadata* metadata) {
74   metadata->mutable_unknown_fields<UnknownFieldSet>()->MergeFrom(other);
75 }
76 
SpaceUsedExcludingSelfLong() const77 size_t UnknownFieldSet::SpaceUsedExcludingSelfLong() const {
78   if (fields_.empty()) return 0;
79 
80   size_t total_size = fields_.SpaceUsedExcludingSelfLong();
81 
82   for (const UnknownField& field : fields_) {
83     switch (field.type()) {
84       case UnknownField::TYPE_LENGTH_DELIMITED:
85         total_size += sizeof(*field.data_.string_value) +
86                       internal::StringSpaceUsedExcludingSelfLong(
87                           *field.data_.string_value);
88         break;
89       case UnknownField::TYPE_GROUP:
90         total_size += field.data_.group_->SpaceUsedLong();
91         break;
92       default:
93         break;
94     }
95   }
96   return total_size;
97 }
98 
SpaceUsedLong() const99 size_t UnknownFieldSet::SpaceUsedLong() const {
100   return sizeof(*this) + SpaceUsedExcludingSelf();
101 }
102 
AddVarint(int number,uint64_t value)103 void UnknownFieldSet::AddVarint(int number, uint64_t value) {
104   auto& field = *fields_.Add();
105   field.number_ = number;
106   field.SetType(UnknownField::TYPE_VARINT);
107   field.data_.varint_ = value;
108 }
109 
AddFixed32(int number,uint32_t value)110 void UnknownFieldSet::AddFixed32(int number, uint32_t value) {
111   auto& field = *fields_.Add();
112   field.number_ = number;
113   field.SetType(UnknownField::TYPE_FIXED32);
114   field.data_.fixed32_ = value;
115 }
116 
AddFixed64(int number,uint64_t value)117 void UnknownFieldSet::AddFixed64(int number, uint64_t value) {
118   auto& field = *fields_.Add();
119   field.number_ = number;
120   field.SetType(UnknownField::TYPE_FIXED64);
121   field.data_.fixed64_ = value;
122 }
123 
AddLengthDelimited(int number,const absl::Cord & value)124 void UnknownFieldSet::AddLengthDelimited(int number, const absl::Cord& value) {
125   absl::CopyCordToString(value, AddLengthDelimited(number));
126 }
127 
128 template <int&...>
AddLengthDelimited(int number,std::string && value)129 void UnknownFieldSet::AddLengthDelimited(int number, std::string&& value) {
130   auto& field = *fields_.Add();
131   field.number_ = number;
132   field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
133   field.data_.string_value =
134       Arena::Create<std::string>(arena(), std::move(value));
135 }
136 template void UnknownFieldSet::AddLengthDelimited(int, std::string&&);
137 
AddLengthDelimited(int number)138 std::string* UnknownFieldSet::AddLengthDelimited(int number) {
139   auto& field = *fields_.Add();
140   field.number_ = number;
141   field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
142   field.data_.string_value = Arena::Create<std::string>(arena());
143   return field.data_.string_value;
144 }
145 
AddGroup(int number)146 UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
147   auto& field = *fields_.Add();
148   field.number_ = number;
149   field.SetType(UnknownField::TYPE_GROUP);
150   field.data_.group_ = Arena::Create<UnknownFieldSet>(arena());
151   return field.data_.group_;
152 }
153 
AddField(const UnknownField & field)154 void UnknownFieldSet::AddField(const UnknownField& field) {
155   fields_.Add(field.DeepCopy(arena()));
156 }
157 
DeleteSubrange(int start,int num)158 void UnknownFieldSet::DeleteSubrange(int start, int num) {
159   if (arena() == nullptr) {
160     // Delete the specified fields.
161     for (int i = 0; i < num; ++i) {
162       (fields_)[i + start].Delete();
163     }
164   }
165   fields_.ExtractSubrange(start, num, nullptr);
166 }
167 
DeleteByNumber(int number)168 void UnknownFieldSet::DeleteByNumber(int number) {
169   size_t left = 0;  // The number of fields left after deletion.
170   for (size_t i = 0; i < fields_.size(); ++i) {
171     UnknownField* field = &(fields_)[i];
172     if (field->number() == number) {
173       if (arena() == nullptr) {
174         field->Delete();
175       }
176     } else {
177       if (i != left) {
178         (fields_)[left] = (fields_)[i];
179       }
180       ++left;
181     }
182   }
183   fields_.Truncate(left);
184 }
185 
MergeFromCodedStream(io::CodedInputStream * input)186 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
187   UnknownFieldSet other;
188   if (internal::WireFormat::SkipMessage(input, &other) &&
189       input->ConsumedEntireMessage()) {
190     MergeFromAndDestroy(&other);
191     return true;
192   } else {
193     return false;
194   }
195 }
196 
ParseFromCodedStream(io::CodedInputStream * input)197 bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
198   Clear();
199   return MergeFromCodedStream(input);
200 }
201 
ParseFromZeroCopyStream(io::ZeroCopyInputStream * input)202 bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
203   io::CodedInputStream coded_input(input);
204   return (ParseFromCodedStream(&coded_input) &&
205           coded_input.ConsumedEntireMessage());
206 }
207 
ParseFromArray(const void * data,int size)208 bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
209   io::ArrayInputStream input(data, size);
210   return ParseFromZeroCopyStream(&input);
211 }
212 
SerializeToString(std::string * output) const213 bool UnknownFieldSet::SerializeToString(std::string* output) const {
214   const size_t size =
215       google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(*this);
216   absl::strings_internal::STLStringResizeUninitializedAmortized(output, size);
217   google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
218       *this, reinterpret_cast<uint8_t*>(const_cast<char*>(output->data())));
219   return true;
220 }
221 
SerializeToCodedStream(io::CodedOutputStream * output) const222 bool UnknownFieldSet::SerializeToCodedStream(
223     io::CodedOutputStream* output) const {
224   google::protobuf::internal::WireFormat::SerializeUnknownFields(*this, output);
225   return !output->HadError();
226 }
227 
SerializeToCord(absl::Cord * output) const228 bool UnknownFieldSet::SerializeToCord(absl::Cord* output) const {
229   const size_t size =
230       google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(*this);
231   io::CordOutputStream cord_output_stream(size);
232   {
233     io::CodedOutputStream coded_output_stream(&cord_output_stream);
234     if (!SerializeToCodedStream(&coded_output_stream)) return false;
235   }
236   *output = cord_output_stream.Consume();
237   return true;
238 }
239 
Delete()240 void UnknownField::Delete() {
241   switch (type()) {
242     case UnknownField::TYPE_LENGTH_DELIMITED:
243       delete data_.string_value;
244       break;
245     case UnknownField::TYPE_GROUP:
246       delete data_.group_;
247       break;
248     default:
249       break;
250   }
251 }
252 
DeepCopy(Arena * arena) const253 UnknownField UnknownField::DeepCopy(Arena* arena) const {
254   UnknownField copy = *this;
255   switch (type()) {
256     case UnknownField::TYPE_LENGTH_DELIMITED:
257       copy.data_.string_value =
258           Arena::Create<std::string>(arena, *data_.string_value);
259       break;
260     case UnknownField::TYPE_GROUP: {
261       UnknownFieldSet* group = Arena::Create<UnknownFieldSet>(arena);
262       group->MergeFrom(*data_.group_);
263       copy.data_.group_ = group;
264       break;
265     }
266     default:
267       break;
268   }
269   return copy;
270 }
271 
SwapSlow(UnknownFieldSet * other)272 void UnknownFieldSet::SwapSlow(UnknownFieldSet* other) {
273   UnknownFieldSet tmp;
274   tmp.MergeFrom(*this);
275   this->Clear();
276   this->MergeFrom(*other);
277   other->Clear();
278   other->MergeFrom(tmp);
279 }
280 
InternalSerializeLengthDelimitedNoTag(uint8_t * target,io::EpsCopyOutputStream * stream) const281 uint8_t* UnknownField::InternalSerializeLengthDelimitedNoTag(
282     uint8_t* target, io::EpsCopyOutputStream* stream) const {
283   ABSL_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
284   const absl::string_view data = *data_.string_value;
285   target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
286   target = stream->WriteRaw(data.data(), data.size(), target);
287   return target;
288 }
289 
290 namespace internal {
291 
292 class UnknownFieldParserHelper {
293  public:
UnknownFieldParserHelper(UnknownFieldSet * unknown)294   explicit UnknownFieldParserHelper(UnknownFieldSet* unknown)
295       : unknown_(unknown) {}
296 
AddVarint(uint32_t num,uint64_t value)297   void AddVarint(uint32_t num, uint64_t value) {
298     unknown_->AddVarint(num, value);
299   }
AddFixed64(uint32_t num,uint64_t value)300   void AddFixed64(uint32_t num, uint64_t value) {
301     unknown_->AddFixed64(num, value);
302   }
ParseLengthDelimited(uint32_t num,const char * ptr,ParseContext * ctx)303   const char* ParseLengthDelimited(uint32_t num, const char* ptr,
304                                    ParseContext* ctx) {
305     std::string* s = unknown_->AddLengthDelimited(num);
306     int size = ReadSize(&ptr);
307     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
308     return ctx->ReadString(ptr, size, s);
309   }
ParseGroup(uint32_t num,const char * ptr,ParseContext * ctx)310   const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) {
311     return ctx->ParseGroupInlined(ptr, num * 8 + 3, [&](const char* ptr) {
312       UnknownFieldParserHelper child(unknown_->AddGroup(num));
313       return WireFormatParser(child, ptr, ctx);
314     });
315   }
AddFixed32(uint32_t num,uint32_t value)316   void AddFixed32(uint32_t num, uint32_t value) {
317     unknown_->AddFixed32(num, value);
318   }
319 
320  private:
321   UnknownFieldSet* unknown_;
322 };
323 
UnknownGroupParse(UnknownFieldSet * unknown,const char * ptr,ParseContext * ctx)324 const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr,
325                               ParseContext* ctx) {
326   UnknownFieldParserHelper field_parser(unknown);
327   return WireFormatParser(field_parser, ptr, ctx);
328 }
329 
UnknownFieldParse(uint64_t tag,UnknownFieldSet * unknown,const char * ptr,ParseContext * ctx)330 const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown,
331                               const char* ptr, ParseContext* ctx) {
332   UnknownFieldParserHelper field_parser(unknown);
333   return FieldParser(tag, field_parser, ptr, ctx);
334 }
335 
336 }  // namespace internal
337 }  // namespace protobuf
338 }  // namespace google
339 
340 #include "google/protobuf/port_undef.inc"
341