unknown_field_set.h revision d0332953cda33fb4f8e24ebff9c49159b69c43d6
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
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 <string>
42#include <vector>
43#include <google/protobuf/repeated_field.h>
44
45namespace google {
46namespace protobuf {
47
48class Message;                      // message.h
49class UnknownField;                 // below
50
51// An UnknownFieldSet contains fields that were encountered while parsing a
52// message but were not defined by its type.  Keeping track of these can be
53// useful, especially in that they may be written if the message is serialized
54// again without being cleared in between.  This means that software which
55// simply receives messages and forwards them to other servers does not need
56// to be updated every time a new field is added to the message definition.
57//
58// To get the UnknownFieldSet attached to any message, call
59// Reflection::GetUnknownFields().
60//
61// This class is necessarily tied to the protocol buffer wire format, unlike
62// the Reflection interface which is independent of any serialization scheme.
63class LIBPROTOBUF_EXPORT UnknownFieldSet {
64 public:
65  UnknownFieldSet();
66  ~UnknownFieldSet();
67
68  // Remove all fields.
69  inline void Clear();
70
71  // Is this set empty?
72  inline bool empty() const;
73
74  // Merge the contents of some other UnknownFieldSet with this one.
75  void MergeFrom(const UnknownFieldSet& other);
76
77  // Swaps the contents of some other UnknownFieldSet with this one.
78  inline void Swap(UnknownFieldSet* x);
79
80  // Computes (an estimate of) the total number of bytes currently used for
81  // storing the unknown fields in memory. Does NOT include
82  // sizeof(*this) in the calculation.
83  int SpaceUsedExcludingSelf() const;
84
85  // Version of SpaceUsed() including sizeof(*this).
86  int SpaceUsed() const;
87
88  // Returns the number of fields present in the UnknownFieldSet.
89  inline int field_count() const;
90  // Get a field in the set, where 0 <= index < field_count().  The fields
91  // appear in the order in which they were added.
92  inline const UnknownField& field(int index) const;
93  // Get a mutable pointer to a field in the set, where
94  // 0 <= index < field_count().  The fields appear in the order in which
95  // they were added.
96  inline UnknownField* mutable_field(int index);
97
98  // Adding fields ---------------------------------------------------
99
100  void AddVarint(int number, uint64 value);
101  void AddFixed32(int number, uint32 value);
102  void AddFixed64(int number, uint64 value);
103  void AddLengthDelimited(int number, const string& value);
104  string* AddLengthDelimited(int number);
105  UnknownFieldSet* AddGroup(int number);
106
107  // Adds an unknown field from another set.
108  void AddField(const UnknownField& field);
109
110  // Parsing helpers -------------------------------------------------
111  // These work exactly like the similarly-named methods of Message.
112
113  bool MergeFromCodedStream(io::CodedInputStream* input);
114  bool ParseFromCodedStream(io::CodedInputStream* input);
115  bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
116  bool ParseFromArray(const void* data, int size);
117  inline bool ParseFromString(const string& data) {
118    return ParseFromArray(data.data(), data.size());
119  }
120
121 private:
122  void ClearFallback();
123
124  vector<UnknownField>* fields_;
125
126  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
127};
128
129// Represents one field in an UnknownFieldSet.
130class LIBPROTOBUF_EXPORT UnknownField {
131 public:
132  enum Type {
133    TYPE_VARINT,
134    TYPE_FIXED32,
135    TYPE_FIXED64,
136    TYPE_LENGTH_DELIMITED,
137    TYPE_GROUP
138  };
139
140  // The field's tag number, as seen on the wire.
141  inline int number() const;
142
143  // The field type.
144  inline Type type() const;
145
146  // Accessors -------------------------------------------------------
147  // Each method works only for UnknownFields of the corresponding type.
148
149  inline uint64 varint() const;
150  inline uint32 fixed32() const;
151  inline uint64 fixed64() const;
152  inline const string& length_delimited() const;
153  inline const UnknownFieldSet& group() const;
154
155  inline void set_varint(uint64 value);
156  inline void set_fixed32(uint32 value);
157  inline void set_fixed64(uint64 value);
158  inline void set_length_delimited(const string& value);
159  inline string* mutable_length_delimited();
160  inline UnknownFieldSet* mutable_group();
161
162 private:
163  friend class UnknownFieldSet;
164
165  // If this UnknownField contains a pointer, delete it.
166  void Delete();
167
168  // Make a deep copy of any pointers in this UnknownField.
169  void DeepCopy();
170
171  unsigned int number_ : 29;
172  unsigned int type_   : 3;
173  union {
174    uint64 varint_;
175    uint32 fixed32_;
176    uint64 fixed64_;
177    string* length_delimited_;
178    UnknownFieldSet* group_;
179  };
180};
181
182// ===================================================================
183// inline implementations
184
185inline void UnknownFieldSet::Clear() {
186  if (fields_ != NULL) {
187    ClearFallback();
188  }
189}
190
191inline bool UnknownFieldSet::empty() const {
192  return fields_ == NULL || fields_->empty();
193}
194
195inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
196  std::swap(fields_, x->fields_);
197}
198
199inline int UnknownFieldSet::field_count() const {
200  return (fields_ == NULL) ? 0 : fields_->size();
201}
202inline const UnknownField& UnknownFieldSet::field(int index) const {
203  return (*fields_)[index];
204}
205inline UnknownField* UnknownFieldSet::mutable_field(int index) {
206  return &(*fields_)[index];
207}
208
209inline void UnknownFieldSet::AddLengthDelimited(
210    int number, const string& value) {
211  AddLengthDelimited(number)->assign(value);
212}
213
214inline int UnknownField::number() const { return number_; }
215inline UnknownField::Type UnknownField::type() const {
216  return static_cast<Type>(type_);
217}
218
219inline uint64 UnknownField::varint () const {
220  GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
221  return varint_;
222}
223inline uint32 UnknownField::fixed32() const {
224  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
225  return fixed32_;
226}
227inline uint64 UnknownField::fixed64() const {
228  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
229  return fixed64_;
230}
231inline const string& UnknownField::length_delimited() const {
232  GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
233  return *length_delimited_;
234}
235inline const UnknownFieldSet& UnknownField::group() const {
236  GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
237  return *group_;
238}
239
240inline void UnknownField::set_varint(uint64 value) {
241  GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
242  varint_ = value;
243}
244inline void UnknownField::set_fixed32(uint32 value) {
245  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
246  fixed32_ = value;
247}
248inline void UnknownField::set_fixed64(uint64 value) {
249  GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
250  fixed64_ = value;
251}
252inline void UnknownField::set_length_delimited(const string& value) {
253  GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
254  length_delimited_->assign(value);
255}
256inline string* UnknownField::mutable_length_delimited() {
257  GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
258  return length_delimited_;
259}
260inline UnknownFieldSet* UnknownField::mutable_group() {
261  GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
262  return group_;
263}
264
265}  // namespace protobuf
266
267}  // namespace google
268#endif  // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
269