Home | History | Annotate | Download | only in protobuf
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      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 #include <google/protobuf/stubs/common.h>
     36 #include <google/protobuf/unknown_field_set.h>
     37 #include <google/protobuf/stubs/stl_util-inl.h>
     38 #include <google/protobuf/io/coded_stream.h>
     39 #include <google/protobuf/io/zero_copy_stream.h>
     40 #include <google/protobuf/io/zero_copy_stream_impl.h>
     41 #include <google/protobuf/wire_format.h>
     42 
     43 namespace google {
     44 namespace protobuf {
     45 
     46 UnknownFieldSet::UnknownFieldSet()
     47   : fields_(NULL) {}
     48 
     49 UnknownFieldSet::~UnknownFieldSet() {
     50   Clear();
     51   delete fields_;
     52 }
     53 
     54 void UnknownFieldSet::ClearFallback() {
     55   GOOGLE_DCHECK(fields_ != NULL);
     56   for (int i = 0; i < fields_->size(); i++) {
     57     (*fields_)[i].Delete();
     58   }
     59   fields_->clear();
     60 }
     61 
     62 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
     63   for (int i = 0; i < other.field_count(); i++) {
     64     AddField(other.field(i));
     65   }
     66 }
     67 
     68 int UnknownFieldSet::SpaceUsedExcludingSelf() const {
     69   if (fields_ == NULL) return 0;
     70 
     71   int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
     72   for (int i = 0; i < fields_->size(); i++) {
     73     const UnknownField& field = (*fields_)[i];
     74     switch (field.type()) {
     75       case UnknownField::TYPE_LENGTH_DELIMITED:
     76         total_size += sizeof(*field.length_delimited_) +
     77           internal::StringSpaceUsedExcludingSelf(*field.length_delimited_);
     78         break;
     79       case UnknownField::TYPE_GROUP:
     80         total_size += field.group_->SpaceUsed();
     81         break;
     82       default:
     83         break;
     84     }
     85   }
     86   return total_size;
     87 }
     88 
     89 int UnknownFieldSet::SpaceUsed() const {
     90   return sizeof(*this) + SpaceUsedExcludingSelf();
     91 }
     92 
     93 void UnknownFieldSet::AddVarint(int number, uint64 value) {
     94   if (fields_ == NULL) fields_ = new vector<UnknownField>;
     95   UnknownField field;
     96   field.number_ = number;
     97   field.type_ = UnknownField::TYPE_VARINT;
     98   field.varint_ = value;
     99   fields_->push_back(field);
    100 }
    101 
    102 void UnknownFieldSet::AddFixed32(int number, uint32 value) {
    103   if (fields_ == NULL) fields_ = new vector<UnknownField>;
    104   UnknownField field;
    105   field.number_ = number;
    106   field.type_ = UnknownField::TYPE_FIXED32;
    107   field.fixed32_ = value;
    108   fields_->push_back(field);
    109 }
    110 
    111 void UnknownFieldSet::AddFixed64(int number, uint64 value) {
    112   if (fields_ == NULL) fields_ = new vector<UnknownField>;
    113   UnknownField field;
    114   field.number_ = number;
    115   field.type_ = UnknownField::TYPE_FIXED64;
    116   field.fixed64_ = value;
    117   fields_->push_back(field);
    118 }
    119 
    120 string* UnknownFieldSet::AddLengthDelimited(int number) {
    121   if (fields_ == NULL) fields_ = new vector<UnknownField>;
    122   UnknownField field;
    123   field.number_ = number;
    124   field.type_ = UnknownField::TYPE_LENGTH_DELIMITED;
    125   field.length_delimited_ = new string;
    126   fields_->push_back(field);
    127   return field.length_delimited_;
    128 }
    129 
    130 UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
    131   if (fields_ == NULL) fields_ = new vector<UnknownField>;
    132   UnknownField field;
    133   field.number_ = number;
    134   field.type_ = UnknownField::TYPE_GROUP;
    135   field.group_ = new UnknownFieldSet;
    136   fields_->push_back(field);
    137   return field.group_;
    138 }
    139 
    140 void UnknownFieldSet::AddField(const UnknownField& field) {
    141   if (fields_ == NULL) fields_ = new vector<UnknownField>;
    142   fields_->push_back(field);
    143   fields_->back().DeepCopy();
    144 }
    145 
    146 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
    147 
    148   UnknownFieldSet other;
    149   if (internal::WireFormat::SkipMessage(input, &other) &&
    150                                   input->ConsumedEntireMessage()) {
    151     MergeFrom(other);
    152     return true;
    153   } else {
    154     return false;
    155   }
    156 }
    157 
    158 bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
    159   Clear();
    160   return MergeFromCodedStream(input);
    161 }
    162 
    163 bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
    164   io::CodedInputStream coded_input(input);
    165   return ParseFromCodedStream(&coded_input) &&
    166     coded_input.ConsumedEntireMessage();
    167 }
    168 
    169 bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
    170   io::ArrayInputStream input(data, size);
    171   return ParseFromZeroCopyStream(&input);
    172 }
    173 
    174 void UnknownField::Delete() {
    175   switch (type()) {
    176     case UnknownField::TYPE_LENGTH_DELIMITED:
    177       delete length_delimited_;
    178       break;
    179     case UnknownField::TYPE_GROUP:
    180       delete group_;
    181       break;
    182     default:
    183       break;
    184   }
    185 }
    186 
    187 void UnknownField::DeepCopy() {
    188   switch (type()) {
    189     case UnknownField::TYPE_LENGTH_DELIMITED:
    190       length_delimited_ = new string(*length_delimited_);
    191       break;
    192     case UnknownField::TYPE_GROUP: {
    193       UnknownFieldSet* group = new UnknownFieldSet;
    194       group->MergeFrom(*group_);
    195       group_ = group;
    196       break;
    197     }
    198     default:
    199       break;
    200   }
    201 }
    202 
    203 }  // namespace protobuf
    204 }  // namespace google
    205