Home | History | Annotate | Download | only in protobuf
      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