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 : // 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 :
41 : #include <assert.h>
42 : #include <string>
43 : #include <vector>
44 : #include <google/protobuf/stubs/common.h>
45 : #include <google/protobuf/stubs/logging.h>
46 :
47 : namespace google {
48 : namespace protobuf {
49 : namespace io {
50 : class CodedInputStream; // coded_stream.h
51 : class CodedOutputStream; // coded_stream.h
52 : class ZeroCopyInputStream; // zero_copy_stream.h
53 : }
54 : namespace internal {
55 : class WireFormat; // wire_format.h
56 : class MessageSetFieldSkipperUsingCord;
57 : // extension_set_heavy.cc
58 : }
59 :
60 : class Message; // message.h
61 : class UnknownField; // below
62 :
63 : // An UnknownFieldSet contains fields that were encountered while parsing a
64 : // message but were not defined by its type. Keeping track of these can be
65 : // useful, especially in that they may be written if the message is serialized
66 : // again without being cleared in between. This means that software which
67 : // simply receives messages and forwards them to other servers does not need
68 : // to be updated every time a new field is added to the message definition.
69 : //
70 : // To get the UnknownFieldSet attached to any message, call
71 : // Reflection::GetUnknownFields().
72 : //
73 : // This class is necessarily tied to the protocol buffer wire format, unlike
74 : // the Reflection interface which is independent of any serialization scheme.
75 : class LIBPROTOBUF_EXPORT UnknownFieldSet {
76 : public:
77 : UnknownFieldSet();
78 : ~UnknownFieldSet();
79 :
80 : // Remove all fields.
81 : inline void Clear();
82 :
83 : // Remove all fields and deallocate internal data objects
84 : void ClearAndFreeMemory();
85 :
86 : // Is this set empty?
87 : inline bool empty() const;
88 :
89 : // Merge the contents of some other UnknownFieldSet with this one.
90 : void MergeFrom(const UnknownFieldSet& other);
91 :
92 : // Similar to above, but this function will destroy the contents of other.
93 : void MergeFromAndDestroy(UnknownFieldSet* other);
94 :
95 : // Swaps the contents of some other UnknownFieldSet with this one.
96 : inline void Swap(UnknownFieldSet* x);
97 :
98 : // Computes (an estimate of) the total number of bytes currently used for
99 : // storing the unknown fields in memory. Does NOT include
100 : // sizeof(*this) in the calculation.
101 : int SpaceUsedExcludingSelf() const;
102 :
103 : // Version of SpaceUsed() including sizeof(*this).
104 : int SpaceUsed() const;
105 :
106 : // Returns the number of fields present in the UnknownFieldSet.
107 : inline int field_count() const;
108 : // Get a field in the set, where 0 <= index < field_count(). The fields
109 : // appear in the order in which they were added.
110 : inline const UnknownField& field(int index) const;
111 : // Get a mutable pointer to a field in the set, where
112 : // 0 <= index < field_count(). The fields appear in the order in which
113 : // they were added.
114 : inline UnknownField* mutable_field(int index);
115 :
116 : // Adding fields ---------------------------------------------------
117 :
118 : void AddVarint(int number, uint64 value);
119 : void AddFixed32(int number, uint32 value);
120 : void AddFixed64(int number, uint64 value);
121 : void AddLengthDelimited(int number, const string& value);
122 : string* AddLengthDelimited(int number);
123 : UnknownFieldSet* AddGroup(int number);
124 :
125 : // Adds an unknown field from another set.
126 : void AddField(const UnknownField& field);
127 :
128 : // Delete fields with indices in the range [start .. start+num-1].
129 : // Caution: implementation moves all fields with indices [start+num .. ].
130 : void DeleteSubrange(int start, int num);
131 :
132 : // Delete all fields with a specific field number. The order of left fields
133 : // is preserved.
134 : // Caution: implementation moves all fields after the first deleted field.
135 : void DeleteByNumber(int number);
136 :
137 : // Parsing helpers -------------------------------------------------
138 : // These work exactly like the similarly-named methods of Message.
139 :
140 : bool MergeFromCodedStream(io::CodedInputStream* input);
141 : bool ParseFromCodedStream(io::CodedInputStream* input);
142 : bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
143 : bool ParseFromArray(const void* data, int size);
144 : inline bool ParseFromString(const string& data) {
145 46 : return ParseFromArray(data.data(), static_cast<int>(data.size()));
146 : }
147 :
148 : static const UnknownFieldSet* default_instance();
149 : private:
150 : // For InternalMergeFrom
151 : friend class UnknownField;
152 : // Merges from other UnknownFieldSet. This method assumes, that this object
153 : // is newly created and has fields_ == NULL;
154 : void InternalMergeFrom(const UnknownFieldSet& other);
155 : void ClearFallback();
156 :
157 : // fields_ is either NULL, or a pointer to a vector that is *non-empty*. We
158 : // never hold the empty vector because we want the 'do we have any unknown
159 : // fields' check to be fast, and avoid a cache miss: the UFS instance gets
160 : // embedded in the message object, so 'fields_ != NULL' tests a member
161 : // variable hot in the cache, without the need to go touch a vector somewhere
162 : // else in memory.
163 : std::vector<UnknownField>* fields_;
164 : GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
165 : };
166 :
167 : // Represents one field in an UnknownFieldSet.
168 : class LIBPROTOBUF_EXPORT UnknownField {
169 : public:
170 : enum Type {
171 : TYPE_VARINT,
172 : TYPE_FIXED32,
173 : TYPE_FIXED64,
174 : TYPE_LENGTH_DELIMITED,
175 : TYPE_GROUP
176 : };
177 :
178 : // The field's tag number, as seen on the wire.
179 : inline int number() const;
180 :
181 : // The field type.
182 : inline Type type() const;
183 :
184 : // Accessors -------------------------------------------------------
185 : // Each method works only for UnknownFields of the corresponding type.
186 :
187 : inline uint64 varint() const;
188 : inline uint32 fixed32() const;
189 : inline uint64 fixed64() const;
190 : inline const string& length_delimited() const;
191 : inline const UnknownFieldSet& group() const;
192 :
193 : inline void set_varint(uint64 value);
194 : inline void set_fixed32(uint32 value);
195 : inline void set_fixed64(uint64 value);
196 : inline void set_length_delimited(const string& value);
197 : inline string* mutable_length_delimited();
198 : inline UnknownFieldSet* mutable_group();
199 :
200 : // Serialization API.
201 : // These methods can take advantage of the underlying implementation and may
202 : // archieve a better performance than using getters to retrieve the data and
203 : // do the serialization yourself.
204 : void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const;
205 : uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const;
206 :
207 : inline int GetLengthDelimitedSize() const;
208 :
209 : private:
210 : friend class UnknownFieldSet;
211 :
212 : // If this UnknownField contains a pointer, delete it.
213 : void Delete();
214 :
215 : // Reset all the underlying pointers to NULL. A special function to be only
216 : // used while merging from a temporary UFS.
217 : void Reset();
218 :
219 : // Make a deep copy of any pointers in this UnknownField.
220 : void DeepCopy(const UnknownField& other);
221 :
222 : // Set the wire type of this UnknownField. Should only be used when this
223 : // UnknownField is being created.
224 : inline void SetType(Type type);
225 :
226 : union LengthDelimited {
227 : string* string_value_;
228 : };
229 :
230 : uint32 number_;
231 : uint32 type_;
232 : union {
233 : uint64 varint_;
234 : uint32 fixed32_;
235 : uint64 fixed64_;
236 : mutable union LengthDelimited length_delimited_;
237 : UnknownFieldSet* group_;
238 : };
239 : };
240 :
241 : // ===================================================================
242 : // inline implementations
243 :
244 : inline void UnknownFieldSet::Clear() {
245 1365 : if (fields_) {
246 809 : ClearFallback();
247 : }
248 : }
249 :
250 : inline bool UnknownFieldSet::empty() const {
251 : // Invariant: fields_ is never empty if present.
252 : return !fields_;
253 : }
254 :
255 0 : inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
256 0 : std::swap(fields_, x->fields_);
257 0 : }
258 :
259 : inline int UnknownFieldSet::field_count() const {
260 6496 : return fields_ ? static_cast<int>(fields_->size()) : 0;
261 : }
262 : inline const UnknownField& UnknownFieldSet::field(int index) const {
263 1536 : GOOGLE_DCHECK(fields_ != NULL);
264 3118 : return (*fields_)[index];
265 : }
266 : inline UnknownField* UnknownFieldSet::mutable_field(int index) {
267 : return &(*fields_)[index];
268 : }
269 :
270 : inline void UnknownFieldSet::AddLengthDelimited(
271 : int number, const string& value) {
272 76 : AddLengthDelimited(number)->assign(value);
273 : }
274 :
275 :
276 1541 : inline int UnknownField::number() const { return number_; }
277 : inline UnknownField::Type UnknownField::type() const {
278 : return static_cast<Type>(type_);
279 : }
280 :
281 : inline uint64 UnknownField::varint() const {
282 : assert(type() == TYPE_VARINT);
283 : return varint_;
284 : }
285 : inline uint32 UnknownField::fixed32() const {
286 : assert(type() == TYPE_FIXED32);
287 : return fixed32_;
288 : }
289 : inline uint64 UnknownField::fixed64() const {
290 : assert(type() == TYPE_FIXED64);
291 : return fixed64_;
292 : }
293 : inline const string& UnknownField::length_delimited() const {
294 : assert(type() == TYPE_LENGTH_DELIMITED);
295 : return *length_delimited_.string_value_;
296 : }
297 : inline const UnknownFieldSet& UnknownField::group() const {
298 : assert(type() == TYPE_GROUP);
299 : return *group_;
300 : }
301 :
302 : inline void UnknownField::set_varint(uint64 value) {
303 : assert(type() == TYPE_VARINT);
304 : varint_ = value;
305 : }
306 : inline void UnknownField::set_fixed32(uint32 value) {
307 : assert(type() == TYPE_FIXED32);
308 : fixed32_ = value;
309 : }
310 : inline void UnknownField::set_fixed64(uint64 value) {
311 : assert(type() == TYPE_FIXED64);
312 : fixed64_ = value;
313 : }
314 : inline void UnknownField::set_length_delimited(const string& value) {
315 : assert(type() == TYPE_LENGTH_DELIMITED);
316 : length_delimited_.string_value_->assign(value);
317 : }
318 : inline string* UnknownField::mutable_length_delimited() {
319 : assert(type() == TYPE_LENGTH_DELIMITED);
320 : return length_delimited_.string_value_;
321 : }
322 : inline UnknownFieldSet* UnknownField::mutable_group() {
323 : assert(type() == TYPE_GROUP);
324 : return group_;
325 : }
326 :
327 : inline int UnknownField::GetLengthDelimitedSize() const {
328 : GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
329 0 : return static_cast<int>(length_delimited_.string_value_->size());
330 : }
331 :
332 : inline void UnknownField::SetType(Type type) {
333 554 : type_ = type;
334 : }
335 :
336 :
337 : } // namespace protobuf
338 :
339 : } // namespace google
340 : #endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
|