// 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 <string>
#include <map>
#include <vector>
#include <google/protobuf/repeated_field.h>
namespace google {
namespace protobuf {
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.
void Clear();
// Is this set empty?
//
// Note that this is equivalent to field_count() == 0 but is NOT necessarily
// equivalent to begin() == end(). The iterator class skips fields which are
// themselves empty, so if field_count() is non-zero but field(i)->empty() is
// true for all i, then begin() will be equal to end() but empty() will return
// false. This inconsistency almost never occurs in practice because typical
// code does not add empty fields to an UnknownFieldSet.
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);
// Find a field by field number. Returns NULL if not found.
const UnknownField* FindFieldByNumber(int number) const;
// Add a field by field number. If the field number already exists, returns
// the existing UnknownField.
UnknownField* AddField(int number);
// 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;
// STL-style iteration ---------------------------------------------
// These iterate over the non-empty UnknownFields in order by field
// number. All iterators are invalidated whenever the UnknownFieldSet
// is modified.
class const_iterator;
class LIBPROTOBUF_EXPORT iterator {
public:
iterator() {}
bool operator==(const iterator& other) {
return inner_iterator_ == other.inner_iterator_;
}
bool operator!=(const iterator& other) {
return inner_iterator_ != other.inner_iterator_;
}
UnknownField& operator*() { return *inner_iterator_->second; }
UnknownField* operator->() { return inner_iterator_->second; }
iterator& operator++() {
++inner_iterator_;
AdvanceToNonEmpty();
return *this;
}
iterator operator++(int) {
iterator copy(*this);
++*this;
return copy;
}
private:
friend class UnknownFieldSet;
friend class LIBPROTOBUF_EXPORT UnknownFieldSet::const_iterator;
iterator(map<int, UnknownField*>::iterator inner_iterator,
map<int, UnknownField*>* inner_map)
: inner_iterator_(inner_iterator), inner_map_(inner_map) {}
void AdvanceToNonEmpty();
map<int, UnknownField*>::iterator inner_iterator_;
map<int, UnknownField*>* inner_map_;
};
class LIBPROTOBUF_EXPORT const_iterator {
public:
const_iterator() {}
const_iterator(const iterator& other)
: inner_iterator_(other.inner_iterator_), inner_map_(other.inner_map_) {}
bool operator==(const const_iterator& other) {
return inner_iterator_ == other.inner_iterator_;
}
bool operator!=(const const_iterator& other) {
return inner_iterator_ != other.inner_iterator_;
}
UnknownField& operator*() { return *inner_iterator_->second; }
UnknownField* operator->() { return inner_iterator_->second; }
const_iterator& operator++() {
++inner_iterator_;
AdvanceToNonEmpty();
return *this;
}
const_iterator operator++(int) {
const_iterator copy(*this);
++*this;
return copy;
}
private:
friend class UnknownFieldSet;
const_iterator(map<int, UnknownField*>::const_iterator inner_iterator,
const map<int, UnknownField*>* inner_map)
: inner_iterator_(inner_iterator), inner_map_(inner_map) {}
void AdvanceToNonEmpty();
map<int, UnknownField*>::const_iterator inner_iterator_;
const map<int, UnknownField*>* inner_map_;
};
iterator begin();
iterator end() {
return internal_ == NULL ? kEmptyIterator :
iterator(internal_->fields_.end(), &internal_->fields_);
}
const_iterator begin() const;
const_iterator end() const {
return internal_ == NULL ? kEmptyConstIterator :
const_iterator(internal_->fields_.end(), &internal_->fields_);
}
// Old-style iteration ---------------------------------------------
// New code should use begin() and end() rather than these methods.
// 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 arbitrary order.
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 arbitrary order.
inline UnknownField* mutable_field(int index);
// 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:
// "Active" fields are ones which have been added since the last time Clear()
// was called. Inactive fields are objects we are keeping around incase
// they become active again.
struct Internal {
// Contains all UnknownFields that have been allocated for this
// UnknownFieldSet, including ones not currently active. Keyed by
// field number. We intentionally try to reuse UnknownField objects for
// the same field number they were used for originally because this makes
// it more likely that the previously-allocated memory will have the right
// layout.
typedef map<int, UnknownField*> FieldMap;
FieldMap fields_;
// Contains the fields from fields_ that are currently active.
typedef vector<UnknownField*> FieldVector;
FieldVector active_fields_;
};
// We want an UnknownFieldSet to use no more space than a single pointer
// until the first field is added.
Internal* internal_;
// Don't keep more inactive fields than this.
static const int kMaxInactiveFields = 100;
// Used by begin() and end() when internal_ is NULL.
static Internal::FieldMap kEmptyMap;
static const iterator kEmptyIterator;
static const const_iterator kEmptyConstIterator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
};
// Represents one field in an UnknownFieldSet.
//
// UnknownField's accessors are similar to those that would be produced by the
// protocol compiler for the fields:
// repeated uint64 varint;
// repeated fixed32 fixed32;
// repeated fixed64 fixed64;
// repeated bytes length_delimited;
// repeated UnknownFieldSet group;
// (OK, so the last one isn't actually a valid field type but you get the
// idea.)
class LIBPROTOBUF_EXPORT UnknownField {
public:
~UnknownField();
// Clears all fields.
void Clear();
// Is this field empty? (I.e. all of the *_size() methods return zero.)
inline bool empty() const;
// Merge the contents of some other UnknownField with this one. For each
// wire type, the values are simply concatenated.
void MergeFrom(const UnknownField& other);
// The field's tag number, as seen on the wire.
inline int number() const;
// The index of this UnknownField within the UnknownFieldSet (e.g.
// set.field(field.index()) == field).
inline int index() const;
inline int varint_size () const;
inline int fixed32_size () const;
inline int fixed64_size () const;
inline int length_delimited_size() const;
inline int group_size () const;
inline uint64 varint (int index) const;
inline uint32 fixed32(int index) const;
inline uint64 fixed64(int index) const;
inline const string& length_delimited(int index) const;
inline const UnknownFieldSet& group(int index) const;
inline void set_varint (int index, uint64 value);
inline void set_fixed32(int index, uint32 value);
inline void set_fixed64(int index, uint64 value);
inline void set_length_delimited(int index, const string& value);
inline string* mutable_length_delimited(int index);
inline UnknownFieldSet* mutable_group(int index);
inline void add_varint (uint64 value);
inline void add_fixed32(uint32 value);
inline void add_fixed64(uint64 value);
inline void add_length_delimited(const string& value);
inline string* add_length_delimited();
inline UnknownFieldSet* add_group();
inline void clear_varint ();
inline void clear_fixed32();
inline void clear_fixed64();
inline void clear_length_delimited();
inline void clear_group();
inline const RepeatedField <uint64 >& varint () const;
inline const RepeatedField <uint32 >& fixed32 () const;
inline const RepeatedField <uint64 >& fixed64 () const;
inline const RepeatedPtrField<string >& length_delimited() const;
inline const RepeatedPtrField<UnknownFieldSet>& group () const;
inline RepeatedField <uint64 >* mutable_varint ();
inline RepeatedField <uint32 >* mutable_fixed32 ();
inline RepeatedField <uint64 >* mutable_fixed64 ();
inline RepeatedPtrField<string >* mutable_length_delimited();
inline RepeatedPtrField<UnknownFieldSet>* mutable_group ();
// Returns (an estimate of) the total number of bytes used to represent the
// unknown field.
int SpaceUsed() const;
private:
friend class UnknownFieldSet;
UnknownField(int number);
int number_;
int index_;
RepeatedField <uint64 > varint_;
RepeatedField <uint32 > fixed32_;
RepeatedField <uint64 > fixed64_;
RepeatedPtrField<string > length_delimited_;
RepeatedPtrField<UnknownFieldSet> group_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownField);
};
// ===================================================================
// inline implementations
inline bool UnknownFieldSet::empty() const {
return internal_ == NULL || internal_->active_fields_.empty();
}
inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
std::swap(internal_, x->internal_);
}
inline int UnknownFieldSet::field_count() const {
return (internal_ == NULL) ? 0 : internal_->active_fields_.size();
}
inline const UnknownField& UnknownFieldSet::field(int index) const {
return *(internal_->active_fields_[index]);
}
inline UnknownField* UnknownFieldSet::mutable_field(int index) {
return internal_->active_fields_[index];
}
inline bool UnknownField::empty() const {
return varint_.size() == 0 &&
fixed32_.size() == 0 &&
fixed64_.size() == 0 &&
length_delimited_.size() == 0 &&
group_.size() == 0;
}
inline int UnknownField::number() const { return number_; }
inline int UnknownField::index () const { return index_; }
inline int UnknownField::varint_size () const {return varint_.size();}
inline int UnknownField::fixed32_size () const {return fixed32_.size();}
inline int UnknownField::fixed64_size () const {return fixed64_.size();}
inline int UnknownField::length_delimited_size() const {
return length_delimited_.size();
}
inline int UnknownField::group_size () const {return group_.size();}
inline uint64 UnknownField::varint (int index) const {
return varint_.Get(index);
}
inline uint32 UnknownField::fixed32(int index) const {
return fixed32_.Get(index);
}
inline uint64 UnknownField::fixed64(int index) const {
return fixed64_.Get(index);
}
inline const string& UnknownField::length_delimited(int index) const {
return length_delimited_.Get(index);
}
inline const UnknownFieldSet& UnknownField::group(int index) const {
return group_.Get(index);
}
inline void UnknownField::set_varint (int index, uint64 value) {
varint_.Set(index, value);
}
inline void UnknownField::set_fixed32(int index, uint32 value) {
fixed32_.Set(index, value);
}
inline void UnknownField::set_fixed64(int index, uint64 value) {
fixed64_.Set(index, value);
}
inline void UnknownField::set_length_delimited(int index, const string& value) {
length_delimited_.Mutable(index)->assign(value);
}
inline string* UnknownField::mutable_length_delimited(int index) {
return length_delimited_.Mutable(index);
}
inline UnknownFieldSet* UnknownField::mutable_group(int index) {
return group_.Mutable(index);
}
inline void UnknownField::add_varint (uint64 value) {
varint_.Add(value);
}
inline void UnknownField::add_fixed32(uint32 value) {
fixed32_.Add(value);
}
inline void UnknownField::add_fixed64(uint64 value) {
fixed64_.Add(value);
}
inline void UnknownField::add_length_delimited(const string& value) {
length_delimited_.Add()->assign(value);
}
inline string* UnknownField::add_length_delimited() {
return length_delimited_.Add();
}
inline UnknownFieldSet* UnknownField::add_group() {
return group_.Add();
}
inline void UnknownField::clear_varint () { varint_.Clear(); }
inline void UnknownField::clear_fixed32() { fixed32_.Clear(); }
inline void UnknownField::clear_fixed64() { fixed64_.Clear(); }
inline void UnknownField::clear_length_delimited() {
length_delimited_.Clear();
}
inline void UnknownField::clear_group() { group_.Clear(); }
inline const RepeatedField<uint64>& UnknownField::varint () const {
return varint_;
}
inline const RepeatedField<uint32>& UnknownField::fixed32() const {
return fixed32_;
}
inline const RepeatedField<uint64>& UnknownField::fixed64() const {
return fixed64_;
}
inline const RepeatedPtrField<string>& UnknownField::length_delimited() const {
return length_delimited_;
}
inline const RepeatedPtrField<UnknownFieldSet>& UnknownField::group() const {
return group_;
}
inline RepeatedField<uint64>* UnknownField::mutable_varint () {
return &varint_;
}
inline RepeatedField<uint32>* UnknownField::mutable_fixed32() {
return &fixed32_;
}
inline RepeatedField<uint64>* UnknownField::mutable_fixed64() {
return &fixed64_;
}
inline RepeatedPtrField<string>* UnknownField::mutable_length_delimited() {
return &length_delimited_;
}
inline RepeatedPtrField<UnknownFieldSet>* UnknownField::mutable_group() {
return &group_;
}
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__