// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // Contains classes used to keep track of unrecognized fields seen while // parsing a protocol message. #ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ #define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ #include <assert.h> #include <string> #include <vector> #include <google/protobuf/stubs/common.h> // TODO(jasonh): some people seem to rely on protobufs to include this for them! namespace google { namespace protobuf { namespace io { class CodedInputStream; // coded_stream.h class CodedOutputStream; // coded_stream.h class ZeroCopyInputStream; // zero_copy_stream.h } namespace internal { class WireFormat; // wire_format.h class UnknownFieldSetFieldSkipperUsingCord; // extension_set_heavy.cc } class Message; // message.h class UnknownField; // below // An UnknownFieldSet contains fields that were encountered while parsing a // message but were not defined by its type. Keeping track of these can be // useful, especially in that they may be written if the message is serialized // again without being cleared in between. This means that software which // simply receives messages and forwards them to other servers does not need // to be updated every time a new field is added to the message definition. // // To get the UnknownFieldSet attached to any message, call // Reflection::GetUnknownFields(). // // This class is necessarily tied to the protocol buffer wire format, unlike // the Reflection interface which is independent of any serialization scheme. class LIBPROTOBUF_EXPORT UnknownFieldSet { public: UnknownFieldSet(); ~UnknownFieldSet(); // Remove all fields. inline void Clear(); // Remove all fields and deallocate internal data objects void ClearAndFreeMemory(); // Is this set empty? inline bool empty() const; // Merge the contents of some other UnknownFieldSet with this one. void MergeFrom(const UnknownFieldSet& other); // Swaps the contents of some other UnknownFieldSet with this one. inline void Swap(UnknownFieldSet* x); // Computes (an estimate of) the total number of bytes currently used for // storing the unknown fields in memory. Does NOT include // sizeof(*this) in the calculation. int SpaceUsedExcludingSelf() const; // Version of SpaceUsed() including sizeof(*this). int SpaceUsed() const; // Returns the number of fields present in the UnknownFieldSet. inline int field_count() const; // Get a field in the set, where 0 <= index < field_count(). The fields // appear in the order in which they were added. inline const UnknownField& field(int index) const; // Get a mutable pointer to a field in the set, where // 0 <= index < field_count(). The fields appear in the order in which // they were added. inline UnknownField* mutable_field(int index); // Adding fields --------------------------------------------------- void AddVarint(int number, uint64 value); void AddFixed32(int number, uint32 value); void AddFixed64(int number, uint64 value); void AddLengthDelimited(int number, const string& value); string* AddLengthDelimited(int number); UnknownFieldSet* AddGroup(int number); // Adds an unknown field from another set. void AddField(const UnknownField& field); // Delete fields with indices in the range [start .. start+num-1]. // Caution: implementation moves all fields with indices [start+num .. ]. void DeleteSubrange(int start, int num); // Delete all fields with a specific field number. The order of left fields // is preserved. // Caution: implementation moves all fields after the first deleted field. void DeleteByNumber(int number); // Parsing helpers ------------------------------------------------- // These work exactly like the similarly-named methods of Message. bool MergeFromCodedStream(io::CodedInputStream* input); bool ParseFromCodedStream(io::CodedInputStream* input); bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); bool ParseFromArray(const void* data, int size); inline bool ParseFromString(const string& data) { return ParseFromArray(data.data(), data.size()); } private: void ClearFallback(); vector<UnknownField>* fields_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet); }; // Represents one field in an UnknownFieldSet. class LIBPROTOBUF_EXPORT UnknownField { public: enum Type { TYPE_VARINT, TYPE_FIXED32, TYPE_FIXED64, TYPE_LENGTH_DELIMITED, TYPE_GROUP }; // The field's tag number, as seen on the wire. inline int number() const; // The field type. inline Type type() const; // Accessors ------------------------------------------------------- // Each method works only for UnknownFields of the corresponding type. inline uint64 varint() const; inline uint32 fixed32() const; inline uint64 fixed64() const; inline const string& length_delimited() const; inline const UnknownFieldSet& group() const; inline void set_varint(uint64 value); inline void set_fixed32(uint32 value); inline void set_fixed64(uint64 value); inline void set_length_delimited(const string& value); inline string* mutable_length_delimited(); inline UnknownFieldSet* mutable_group(); // Serialization API. // These methods can take advantage of the underlying implementation and may // archieve a better performance than using getters to retrieve the data and // do the serialization yourself. void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const; uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const; inline int GetLengthDelimitedSize() const; private: friend class UnknownFieldSet; // If this UnknownField contains a pointer, delete it. void Delete(); // Make a deep copy of any pointers in this UnknownField. void DeepCopy(); unsigned int number_ : 29; unsigned int type_ : 3; union { uint64 varint_; uint32 fixed32_; uint64 fixed64_; mutable union { string* string_value_; } length_delimited_; UnknownFieldSet* group_; }; }; // =================================================================== // inline implementations inline void UnknownFieldSet::Clear() { if (fields_ != NULL) { ClearFallback(); } } inline bool UnknownFieldSet::empty() const { return fields_ == NULL || fields_->empty(); } inline void UnknownFieldSet::Swap(UnknownFieldSet* x) { std::swap(fields_, x->fields_); } inline int UnknownFieldSet::field_count() const { return (fields_ == NULL) ? 0 : fields_->size(); } inline const UnknownField& UnknownFieldSet::field(int index) const { return (*fields_)[index]; } inline UnknownField* UnknownFieldSet::mutable_field(int index) { return &(*fields_)[index]; } inline void UnknownFieldSet::AddLengthDelimited( int number, const string& value) { AddLengthDelimited(number)->assign(value); } inline int UnknownField::number() const { return number_; } inline UnknownField::Type UnknownField::type() const { return static_cast<Type>(type_); } inline uint64 UnknownField::varint () const { assert(type_ == TYPE_VARINT); return varint_; } inline uint32 UnknownField::fixed32() const { assert(type_ == TYPE_FIXED32); return fixed32_; } inline uint64 UnknownField::fixed64() const { assert(type_ == TYPE_FIXED64); return fixed64_; } inline const string& UnknownField::length_delimited() const { assert(type_ == TYPE_LENGTH_DELIMITED); return *length_delimited_.string_value_; } inline const UnknownFieldSet& UnknownField::group() const { assert(type_ == TYPE_GROUP); return *group_; } inline void UnknownField::set_varint(uint64 value) { assert(type_ == TYPE_VARINT); varint_ = value; } inline void UnknownField::set_fixed32(uint32 value) { assert(type_ == TYPE_FIXED32); fixed32_ = value; } inline void UnknownField::set_fixed64(uint64 value) { assert(type_ == TYPE_FIXED64); fixed64_ = value; } inline void UnknownField::set_length_delimited(const string& value) { assert(type_ == TYPE_LENGTH_DELIMITED); length_delimited_.string_value_->assign(value); } inline string* UnknownField::mutable_length_delimited() { assert(type_ == TYPE_LENGTH_DELIMITED); return length_delimited_.string_value_; } inline UnknownFieldSet* UnknownField::mutable_group() { assert(type_ == TYPE_GROUP); return group_; } inline int UnknownField::GetLengthDelimitedSize() const { GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); return length_delimited_.string_value_->size(); } } // namespace protobuf } // namespace google #endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__