aboutsummaryrefslogblamecommitdiff
path: root/src/google/protobuf/unknown_field_set.cc
blob: 3d45002ece09605eb546d7c8c217d556ea31750f (plain) (tree)





















                                                                           



                                                     




































                                                                               



























                                                                               




















































                                                                           
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.
// http://code.google.com/p/protobuf/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: kenton@google.com (Kenton Varda)
//  Based on original Protocol Buffers design by
//  Sanjay Ghemawat, Jeff Dean, and others.

#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/wire_format.h>

namespace google {
namespace protobuf {

UnknownFieldSet::UnknownFieldSet()
  : internal_(NULL) {}

UnknownFieldSet::~UnknownFieldSet() {
  if (internal_ != NULL) {
    STLDeleteValues(&internal_->fields_);
    delete internal_;
  }
}

void UnknownFieldSet::Clear() {
  if (internal_ == NULL) return;

  if (internal_->fields_.size() > kMaxInactiveFields) {
    STLDeleteValues(&internal_->fields_);
  } else {
    // Don't delete the UnknownField objects.  Just remove them from the active
    // set.
    for (int i = 0; i < internal_->active_fields_.size(); i++) {
      internal_->active_fields_[i]->Clear();
      internal_->active_fields_[i]->index_ = -1;
    }
  }

  internal_->active_fields_.clear();
}

void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
  for (int i = 0; i < other.field_count(); i++) {
    AddField(other.field(i).number())->MergeFrom(other.field(i));
  }
}

bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {

  UnknownFieldSet other;
  if (internal::WireFormat::SkipMessage(input, &other) &&
                                  input->ConsumedEntireMessage()) {
    MergeFrom(other);
    return true;
  } else {
    return false;
  }
}

bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) {
  Clear();
  return MergeFromCodedStream(input);
}

bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
  io::CodedInputStream coded_input(input);
  return ParseFromCodedStream(&coded_input) &&
    coded_input.ConsumedEntireMessage();
}

bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
  io::ArrayInputStream input(data, size);
  return ParseFromZeroCopyStream(&input);
}

const UnknownField* UnknownFieldSet::FindFieldByNumber(int number) const {
  if (internal_ == NULL) return NULL;

  map<int, UnknownField*>::iterator iter = internal_->fields_.find(number);
  if (iter != internal_->fields_.end() && iter->second->index() != -1) {
    return iter->second;
  } else {
    return NULL;
  }
}

UnknownField* UnknownFieldSet::AddField(int number) {
  if (internal_ == NULL) internal_ = new Internal;

  UnknownField** map_slot = &internal_->fields_[number];
  if (*map_slot == NULL) {
    *map_slot = new UnknownField(number);
  }

  UnknownField* field = *map_slot;
  if (field->index() == -1) {
    field->index_ = internal_->active_fields_.size();
    internal_->active_fields_.push_back(field);
  }
  return field;
}

UnknownField::UnknownField(int number)
  : number_(number),
    index_(-1) {
}

UnknownField::~UnknownField() {
}

void UnknownField::Clear() {
  clear_varint();
  clear_fixed32();
  clear_fixed64();
  clear_length_delimited();
  clear_group();
}

void UnknownField::MergeFrom(const UnknownField& other) {
  varint_          .MergeFrom(other.varint_          );
  fixed32_         .MergeFrom(other.fixed32_         );
  fixed64_         .MergeFrom(other.fixed64_         );
  length_delimited_.MergeFrom(other.length_delimited_);
  group_           .MergeFrom(other.group_           );
}

}  // namespace protobuf
}  // namespace google