blob: 987b1979d5e37c42ba7247ee8b05f7d68ccbd431 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34//
35// Contains classes used to keep track of unrecognized fields seen while
36// parsing a protocol message.
37
38#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
39#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
40
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000041#include <assert.h>
temporal40ee5512008-07-10 02:12:20 +000042#include <string>
temporal40ee5512008-07-10 02:12:20 +000043#include <vector>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000044#include <google/protobuf/stubs/common.h>
temporal40ee5512008-07-10 02:12:20 +000045
46namespace google {
47namespace protobuf {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000048 namespace io {
49 class CodedInputStream; // coded_stream.h
50 class CodedOutputStream; // coded_stream.h
51 class ZeroCopyInputStream; // zero_copy_stream.h
52 }
53 namespace internal {
54 class WireFormat; // wire_format.h
jieluo@google.com4de8f552014-07-18 00:47:59 +000055 class MessageSetFieldSkipperUsingCord;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000056 // extension_set_heavy.cc
57 }
temporal40ee5512008-07-10 02:12:20 +000058
59class Message; // message.h
60class UnknownField; // below
61
62// An UnknownFieldSet contains fields that were encountered while parsing a
63// message but were not defined by its type. Keeping track of these can be
64// useful, especially in that they may be written if the message is serialized
65// again without being cleared in between. This means that software which
66// simply receives messages and forwards them to other servers does not need
67// to be updated every time a new field is added to the message definition.
68//
69// To get the UnknownFieldSet attached to any message, call
temporal779f61c2008-08-13 03:15:00 +000070// Reflection::GetUnknownFields().
temporal40ee5512008-07-10 02:12:20 +000071//
72// This class is necessarily tied to the protocol buffer wire format, unlike
73// the Reflection interface which is independent of any serialization scheme.
74class LIBPROTOBUF_EXPORT UnknownFieldSet {
75 public:
76 UnknownFieldSet();
77 ~UnknownFieldSet();
78
79 // Remove all fields.
kenton@google.comfccb1462009-12-18 02:11:36 +000080 inline void Clear();
temporal40ee5512008-07-10 02:12:20 +000081
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000082 // Remove all fields and deallocate internal data objects
83 void ClearAndFreeMemory();
84
temporal40ee5512008-07-10 02:12:20 +000085 // Is this set empty?
86 inline bool empty() const;
87
88 // Merge the contents of some other UnknownFieldSet with this one.
89 void MergeFrom(const UnknownFieldSet& other);
90
Feng Xiao6ef984a2014-11-10 17:34:54 -080091 // Similar to above, but this function will destroy the contents of other.
92 void MergeFromAndDestroy(UnknownFieldSet* other);
93
kenton@google.com26bd9ee2008-11-21 00:06:27 +000094 // Swaps the contents of some other UnknownFieldSet with this one.
95 inline void Swap(UnknownFieldSet* x);
96
kenton@google.com2d6daa72009-01-22 01:27:00 +000097 // Computes (an estimate of) the total number of bytes currently used for
98 // storing the unknown fields in memory. Does NOT include
99 // sizeof(*this) in the calculation.
100 int SpaceUsedExcludingSelf() const;
101
102 // Version of SpaceUsed() including sizeof(*this).
103 int SpaceUsed() const;
104
temporal40ee5512008-07-10 02:12:20 +0000105 // Returns the number of fields present in the UnknownFieldSet.
106 inline int field_count() const;
107 // Get a field in the set, where 0 <= index < field_count(). The fields
kenton@google.comd37d46d2009-04-25 02:53:47 +0000108 // appear in the order in which they were added.
temporal40ee5512008-07-10 02:12:20 +0000109 inline const UnknownField& field(int index) const;
110 // Get a mutable pointer to a field in the set, where
kenton@google.comd37d46d2009-04-25 02:53:47 +0000111 // 0 <= index < field_count(). The fields appear in the order in which
112 // they were added.
temporal40ee5512008-07-10 02:12:20 +0000113 inline UnknownField* mutable_field(int index);
114
kenton@google.comd37d46d2009-04-25 02:53:47 +0000115 // Adding fields ---------------------------------------------------
116
117 void AddVarint(int number, uint64 value);
118 void AddFixed32(int number, uint32 value);
119 void AddFixed64(int number, uint64 value);
120 void AddLengthDelimited(int number, const string& value);
121 string* AddLengthDelimited(int number);
122 UnknownFieldSet* AddGroup(int number);
123
124 // Adds an unknown field from another set.
125 void AddField(const UnknownField& field);
126
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000127 // Delete fields with indices in the range [start .. start+num-1].
128 // Caution: implementation moves all fields with indices [start+num .. ].
129 void DeleteSubrange(int start, int num);
130
131 // Delete all fields with a specific field number. The order of left fields
132 // is preserved.
133 // Caution: implementation moves all fields after the first deleted field.
134 void DeleteByNumber(int number);
135
temporala0f27fc2008-08-06 01:12:21 +0000136 // Parsing helpers -------------------------------------------------
137 // These work exactly like the similarly-named methods of Message.
138
139 bool MergeFromCodedStream(io::CodedInputStream* input);
140 bool ParseFromCodedStream(io::CodedInputStream* input);
141 bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
142 bool ParseFromArray(const void* data, int size);
143 inline bool ParseFromString(const string& data) {
Feng Xiao84731a12014-10-03 11:13:58 -0700144 return ParseFromArray(data.data(), static_cast<int>(data.size()));
temporala0f27fc2008-08-06 01:12:21 +0000145 }
146
Feng Xiao6ef984a2014-11-10 17:34:54 -0800147 static const UnknownFieldSet* default_instance();
temporal40ee5512008-07-10 02:12:20 +0000148 private:
Feng Xiao6ef984a2014-11-10 17:34:54 -0800149 // For InternalMergeFrom
150 friend class UnknownField;
151 // Merges from other UnknownFieldSet. This method assumes, that this object
152 // is newly created and has fields_ == NULL;
153 void InternalMergeFrom(const UnknownFieldSet& other);
kenton@google.comfccb1462009-12-18 02:11:36 +0000154 void ClearFallback();
155
Feng Xiao6ef984a2014-11-10 17:34:54 -0800156 // fields_ is either NULL, or a pointer to a vector that is *non-empty*. We
157 // never hold the empty vector because we want the 'do we have any unknown
158 // fields' check to be fast, and avoid a cache miss: the UFS instance gets
159 // embedded in the message object, so 'fields_ != NULL' tests a member
160 // variable hot in the cache, without the need to go touch a vector somewhere
161 // else in memory.
Fabrice de Gans-Riberi98db4952014-11-03 13:45:55 +0100162 std::vector<UnknownField>* fields_;
temporal40ee5512008-07-10 02:12:20 +0000163 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
164};
165
166// Represents one field in an UnknownFieldSet.
temporal40ee5512008-07-10 02:12:20 +0000167class LIBPROTOBUF_EXPORT UnknownField {
168 public:
kenton@google.comd37d46d2009-04-25 02:53:47 +0000169 enum Type {
170 TYPE_VARINT,
171 TYPE_FIXED32,
172 TYPE_FIXED64,
173 TYPE_LENGTH_DELIMITED,
174 TYPE_GROUP
175 };
temporal40ee5512008-07-10 02:12:20 +0000176
177 // The field's tag number, as seen on the wire.
178 inline int number() const;
179
kenton@google.comd37d46d2009-04-25 02:53:47 +0000180 // The field type.
181 inline Type type() const;
temporal40ee5512008-07-10 02:12:20 +0000182
kenton@google.comd37d46d2009-04-25 02:53:47 +0000183 // Accessors -------------------------------------------------------
184 // Each method works only for UnknownFields of the corresponding type.
temporal40ee5512008-07-10 02:12:20 +0000185
kenton@google.comd37d46d2009-04-25 02:53:47 +0000186 inline uint64 varint() const;
187 inline uint32 fixed32() const;
188 inline uint64 fixed64() const;
189 inline const string& length_delimited() const;
190 inline const UnknownFieldSet& group() const;
temporal40ee5512008-07-10 02:12:20 +0000191
kenton@google.comd37d46d2009-04-25 02:53:47 +0000192 inline void set_varint(uint64 value);
193 inline void set_fixed32(uint32 value);
194 inline void set_fixed64(uint64 value);
195 inline void set_length_delimited(const string& value);
196 inline string* mutable_length_delimited();
197 inline UnknownFieldSet* mutable_group();
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000198
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000199 // Serialization API.
200 // These methods can take advantage of the underlying implementation and may
201 // archieve a better performance than using getters to retrieve the data and
202 // do the serialization yourself.
203 void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const;
204 uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const;
205
206 inline int GetLengthDelimitedSize() const;
207
temporal40ee5512008-07-10 02:12:20 +0000208 private:
209 friend class UnknownFieldSet;
temporal40ee5512008-07-10 02:12:20 +0000210
kenton@google.comd37d46d2009-04-25 02:53:47 +0000211 // If this UnknownField contains a pointer, delete it.
212 void Delete();
temporal40ee5512008-07-10 02:12:20 +0000213
Feng Xiao6ef984a2014-11-10 17:34:54 -0800214 // Reset all the underlying pointers to NULL. A special function to be only
215 // used while merging from a temporary UFS.
216 void Reset();
217
kenton@google.comd37d46d2009-04-25 02:53:47 +0000218 // Make a deep copy of any pointers in this UnknownField.
219 void DeepCopy();
temporal40ee5512008-07-10 02:12:20 +0000220
jieluo@google.com4de8f552014-07-18 00:47:59 +0000221 // Set the wire type of this UnknownField. Should only be used when this
222 // UnknownField is being created.
223 inline void SetType(Type type);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000224
Łukasz Twarduśdd449e12014-11-25 19:25:38 +0100225 union LengthDelimited {
226 string* string_value_;
227 };
228
Jisi Liu885b6122015-02-28 14:51:22 -0800229 uint32 number_;
230 uint32 type_;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000231 union {
232 uint64 varint_;
233 uint32 fixed32_;
234 uint64 fixed64_;
Łukasz Twarduśdd449e12014-11-25 19:25:38 +0100235 mutable union LengthDelimited length_delimited_;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000236 UnknownFieldSet* group_;
237 };
temporal40ee5512008-07-10 02:12:20 +0000238};
239
240// ===================================================================
241// inline implementations
242
kenton@google.comfccb1462009-12-18 02:11:36 +0000243inline void UnknownFieldSet::Clear() {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800244 if (fields_) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000245 ClearFallback();
246 }
247}
248
temporal40ee5512008-07-10 02:12:20 +0000249inline bool UnknownFieldSet::empty() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800250 // Invariant: fields_ is never empty if present.
251 return !fields_;
temporal40ee5512008-07-10 02:12:20 +0000252}
253
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000254inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000255 std::swap(fields_, x->fields_);
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000256}
257
temporal40ee5512008-07-10 02:12:20 +0000258inline int UnknownFieldSet::field_count() const {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800259 return fields_ ? static_cast<int>(fields_->size()) : 0;
temporal40ee5512008-07-10 02:12:20 +0000260}
261inline const UnknownField& UnknownFieldSet::field(int index) const {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800262 GOOGLE_DCHECK(fields_ != NULL);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000263 return (*fields_)[index];
temporal40ee5512008-07-10 02:12:20 +0000264}
265inline UnknownField* UnknownFieldSet::mutable_field(int index) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000266 return &(*fields_)[index];
temporal40ee5512008-07-10 02:12:20 +0000267}
268
kenton@google.comd37d46d2009-04-25 02:53:47 +0000269inline void UnknownFieldSet::AddLengthDelimited(
270 int number, const string& value) {
271 AddLengthDelimited(number)->assign(value);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000272}
273
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000274
temporal40ee5512008-07-10 02:12:20 +0000275inline int UnknownField::number() const { return number_; }
kenton@google.comd37d46d2009-04-25 02:53:47 +0000276inline UnknownField::Type UnknownField::type() const {
277 return static_cast<Type>(type_);
temporal40ee5512008-07-10 02:12:20 +0000278}
279
jieluo@google.com4de8f552014-07-18 00:47:59 +0000280inline uint64 UnknownField::varint() const {
281 assert(type() == TYPE_VARINT);
temporal40ee5512008-07-10 02:12:20 +0000282 return varint_;
283}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000284inline uint32 UnknownField::fixed32() const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000285 assert(type() == TYPE_FIXED32);
temporal40ee5512008-07-10 02:12:20 +0000286 return fixed32_;
287}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000288inline uint64 UnknownField::fixed64() const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000289 assert(type() == TYPE_FIXED64);
temporal40ee5512008-07-10 02:12:20 +0000290 return fixed64_;
291}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000292inline const string& UnknownField::length_delimited() const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000293 assert(type() == TYPE_LENGTH_DELIMITED);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000294 return *length_delimited_.string_value_;
temporal40ee5512008-07-10 02:12:20 +0000295}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000296inline const UnknownFieldSet& UnknownField::group() const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000297 assert(type() == TYPE_GROUP);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000298 return *group_;
temporal40ee5512008-07-10 02:12:20 +0000299}
300
kenton@google.comd37d46d2009-04-25 02:53:47 +0000301inline void UnknownField::set_varint(uint64 value) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000302 assert(type() == TYPE_VARINT);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000303 varint_ = value;
temporal40ee5512008-07-10 02:12:20 +0000304}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000305inline void UnknownField::set_fixed32(uint32 value) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000306 assert(type() == TYPE_FIXED32);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000307 fixed32_ = value;
temporal40ee5512008-07-10 02:12:20 +0000308}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000309inline void UnknownField::set_fixed64(uint64 value) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000310 assert(type() == TYPE_FIXED64);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000311 fixed64_ = value;
temporal40ee5512008-07-10 02:12:20 +0000312}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000313inline void UnknownField::set_length_delimited(const string& value) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000314 assert(type() == TYPE_LENGTH_DELIMITED);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000315 length_delimited_.string_value_->assign(value);
temporal40ee5512008-07-10 02:12:20 +0000316}
kenton@google.comd37d46d2009-04-25 02:53:47 +0000317inline string* UnknownField::mutable_length_delimited() {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000318 assert(type() == TYPE_LENGTH_DELIMITED);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000319 return length_delimited_.string_value_;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000320}
321inline UnknownFieldSet* UnknownField::mutable_group() {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000322 assert(type() == TYPE_GROUP);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000323 return group_;
temporal40ee5512008-07-10 02:12:20 +0000324}
325
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000326inline int UnknownField::GetLengthDelimitedSize() const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000327 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
Feng Xiao84731a12014-10-03 11:13:58 -0700328 return static_cast<int>(length_delimited_.string_value_->size());
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000329}
330
jieluo@google.com4de8f552014-07-18 00:47:59 +0000331inline void UnknownField::SetType(Type type) {
332 type_ = type;
333}
334
335
temporal40ee5512008-07-10 02:12:20 +0000336} // namespace protobuf
337
338} // namespace google
339#endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__