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 (at) 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 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 if (fields_) { 246 ClearFallback(); 247 } 248 } 249 250 inline bool UnknownFieldSet::empty() const { 251 // Invariant: fields_ is never empty if present. 252 return !fields_; 253 } 254 255 inline void UnknownFieldSet::Swap(UnknownFieldSet* x) { 256 std::swap(fields_, x->fields_); 257 } 258 259 inline int UnknownFieldSet::field_count() const { 260 return fields_ ? static_cast<int>(fields_->size()) : 0; 261 } 262 inline const UnknownField& UnknownFieldSet::field(int index) const { 263 GOOGLE_DCHECK(fields_ != NULL); 264 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 AddLengthDelimited(number)->assign(value); 273 } 274 275 276 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 return static_cast<int>(length_delimited_.string_value_->size()); 330 } 331 332 inline void UnknownField::SetType(Type type) { 333 type_ = type; 334 } 335 336 337 } // namespace protobuf 338 339 } // namespace google 340 #endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ 341