aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/unknown_field_set.h
diff options
context:
space:
mode:
authorkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-01-22 01:27:00 +0000
committerkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-01-22 01:27:00 +0000
commit2d6daa72ab5832bf4cab38df0d911f32df547021 (patch)
tree5f9304a6ff2c7c0cb7ed62eead92bf05411666f8 /src/google/protobuf/unknown_field_set.h
parent87e64e1ceeff224043078e7e31fe0b1a119c8b1a (diff)
downloadprotobuf-2d6daa72ab5832bf4cab38df0d911f32df547021.tar.gz
protobuf-2d6daa72ab5832bf4cab38df0d911f32df547021.tar.bz2
protobuf-2d6daa72ab5832bf4cab38df0d911f32df547021.zip
Push out changes from internal codebase.
All Languages * Repeated fields of primitive types (types other that string, group, and nested messages) may now use the option [packed = true] to get a more efficient encoding. In the new encoding, the entire list is written as a single byte blob using the "length-delimited" wire type. Within this blob, the individual values are encoded the same way they would be normally except without a tag before each value (thus, they are tightly "packed"). C++ * UnknownFieldSet now supports STL-like iteration. * Message interface has method ParseFromBoundedZeroCopyStream() which parses a limited number of bytes from an input stream rather than parsing until EOF. Java * Fixed bug where Message.mergeFrom(Message) failed to merge extensions. * Message interface has new method toBuilder() which is equivalent to newBuilderForType().mergeFrom(this). * All enums now implement the ProtocolMessageEnum interface. * Setting a field to null now throws NullPointerException. * Fixed tendency for TextFormat's parsing to overflow the stack when parsing large string values. The underlying problem is with Java's regex implementation (which unfortunately uses recursive backtracking rather than building an NFA). Worked around by making use of possesive quantifiers. Python * Updated RPC interfaces to allow for blocking operation. A client may now pass None for a callback when making an RPC, in which case the call will block until the response is received, and the response object will be returned directly to the caller. This interface change cannot be used in practice until RPC implementations are updated to implement it.
Diffstat (limited to 'src/google/protobuf/unknown_field_set.h')
-rw-r--r--src/google/protobuf/unknown_field_set.h152
1 files changed, 136 insertions, 16 deletions
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 55eec6e2..f17012df 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -70,6 +70,13 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
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.
@@ -78,6 +85,117 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// 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
@@ -87,13 +205,6 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// 0 <= index < field_count(). The fields appear in arbitrary order.
inline UnknownField* mutable_field(int index);
- // 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);
-
// Parsing helpers -------------------------------------------------
// These work exactly like the similarly-named methods of Message.
@@ -105,13 +216,6 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
return ParseFromArray(data.data(), data.size());
}
- // 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;
-
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
@@ -139,6 +243,11 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// 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);
};
@@ -160,6 +269,9 @@ class LIBPROTOBUF_EXPORT 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);
@@ -256,6 +368,14 @@ 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_; }
@@ -322,8 +442,8 @@ inline UnknownFieldSet* UnknownField::add_group() {
}
inline void UnknownField::clear_varint () { varint_.Clear(); }
-inline void UnknownField::clear_fixed32() { varint_.Clear(); }
-inline void UnknownField::clear_fixed64() { 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();
}