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@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <google/protobuf/unknown_field_set.h> 36 37#include <google/protobuf/stubs/logging.h> 38#include <google/protobuf/stubs/common.h> 39#include <google/protobuf/io/coded_stream.h> 40#include <google/protobuf/io/zero_copy_stream.h> 41#include <google/protobuf/io/zero_copy_stream_impl.h> 42#include <google/protobuf/wire_format.h> 43#include <google/protobuf/stubs/stl_util.h> 44 45namespace google { 46namespace protobuf { 47 48namespace { 49// This global instance is returned by unknown_fields() on any message class 50// when the object has no unknown fields. This is necessary because we now 51// instantiate the UnknownFieldSet dynamically only when required. 52UnknownFieldSet* default_unknown_field_set_instance_ = NULL; 53 54void DeleteDefaultUnknownFieldSet() { 55 delete default_unknown_field_set_instance_; 56} 57 58void InitDefaultUnknownFieldSet() { 59 default_unknown_field_set_instance_ = new UnknownFieldSet(); 60 internal::OnShutdown(&DeleteDefaultUnknownFieldSet); 61} 62 63GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_); 64} 65 66const UnknownFieldSet* UnknownFieldSet::default_instance() { 67 ::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_, 68 &InitDefaultUnknownFieldSet); 69 return default_unknown_field_set_instance_; 70} 71 72UnknownFieldSet::UnknownFieldSet() 73 : fields_(NULL) {} 74 75UnknownFieldSet::~UnknownFieldSet() { 76 Clear(); 77 delete fields_; 78} 79 80void UnknownFieldSet::ClearFallback() { 81 if (fields_ != NULL) { 82 for (int i = 0; i < fields_->size(); i++) { 83 (*fields_)[i].Delete(); 84 } 85 delete fields_; 86 fields_ = NULL; 87 } 88} 89 90void UnknownFieldSet::ClearAndFreeMemory() { 91 if (fields_ != NULL) { 92 Clear(); 93 } 94} 95 96void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) { 97 int other_field_count = other.field_count(); 98 if (other_field_count > 0) { 99 fields_ = new vector<UnknownField>(); 100 for (int i = 0; i < other_field_count; i++) { 101 fields_->push_back((*other.fields_)[i]); 102 fields_->back().DeepCopy((*other.fields_)[i]); 103 } 104 } 105} 106 107void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { 108 int other_field_count = other.field_count(); 109 if (other_field_count > 0) { 110 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 111 for (int i = 0; i < other_field_count; i++) { 112 fields_->push_back((*other.fields_)[i]); 113 fields_->back().DeepCopy((*other.fields_)[i]); 114 } 115 } 116} 117 118// A specialized MergeFrom for performance when we are merging from an UFS that 119// is temporary and can be destroyed in the process. 120void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) { 121 int other_field_count = other->field_count(); 122 if (other_field_count > 0) { 123 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 124 for (int i = 0; i < other_field_count; i++) { 125 fields_->push_back((*other->fields_)[i]); 126 (*other->fields_)[i].Reset(); 127 } 128 } 129 delete other->fields_; 130 other->fields_ = NULL; 131} 132 133int UnknownFieldSet::SpaceUsedExcludingSelf() const { 134 if (fields_ == NULL) return 0; 135 136 int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size(); 137 138 for (int i = 0; i < fields_->size(); i++) { 139 const UnknownField& field = (*fields_)[i]; 140 switch (field.type()) { 141 case UnknownField::TYPE_LENGTH_DELIMITED: 142 total_size += sizeof(*field.length_delimited_.string_value_) + 143 internal::StringSpaceUsedExcludingSelf( 144 *field.length_delimited_.string_value_); 145 break; 146 case UnknownField::TYPE_GROUP: 147 total_size += field.group_->SpaceUsed(); 148 break; 149 default: 150 break; 151 } 152 } 153 return total_size; 154} 155 156int UnknownFieldSet::SpaceUsed() const { 157 return sizeof(*this) + SpaceUsedExcludingSelf(); 158} 159 160void UnknownFieldSet::AddVarint(int number, uint64 value) { 161 UnknownField field; 162 field.number_ = number; 163 field.SetType(UnknownField::TYPE_VARINT); 164 field.varint_ = value; 165 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 166 fields_->push_back(field); 167} 168 169void UnknownFieldSet::AddFixed32(int number, uint32 value) { 170 UnknownField field; 171 field.number_ = number; 172 field.SetType(UnknownField::TYPE_FIXED32); 173 field.fixed32_ = value; 174 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 175 fields_->push_back(field); 176} 177 178void UnknownFieldSet::AddFixed64(int number, uint64 value) { 179 UnknownField field; 180 field.number_ = number; 181 field.SetType(UnknownField::TYPE_FIXED64); 182 field.fixed64_ = value; 183 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 184 fields_->push_back(field); 185} 186 187string* UnknownFieldSet::AddLengthDelimited(int number) { 188 UnknownField field; 189 field.number_ = number; 190 field.SetType(UnknownField::TYPE_LENGTH_DELIMITED); 191 field.length_delimited_.string_value_ = new string; 192 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 193 fields_->push_back(field); 194 return field.length_delimited_.string_value_; 195} 196 197 198UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { 199 UnknownField field; 200 field.number_ = number; 201 field.SetType(UnknownField::TYPE_GROUP); 202 field.group_ = new UnknownFieldSet; 203 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 204 fields_->push_back(field); 205 return field.group_; 206} 207 208void UnknownFieldSet::AddField(const UnknownField& field) { 209 if (fields_ == NULL) fields_ = new vector<UnknownField>(); 210 fields_->push_back(field); 211 fields_->back().DeepCopy(field); 212} 213 214void UnknownFieldSet::DeleteSubrange(int start, int num) { 215 // Delete the specified fields. 216 for (int i = 0; i < num; ++i) { 217 (*fields_)[i + start].Delete(); 218 } 219 // Slide down the remaining fields. 220 for (int i = start + num; i < fields_->size(); ++i) { 221 (*fields_)[i - num] = (*fields_)[i]; 222 } 223 // Pop off the # of deleted fields. 224 for (int i = 0; i < num; ++i) { 225 fields_->pop_back(); 226 } 227 if (fields_ && fields_->size() == 0) { 228 // maintain invariant: never hold fields_ if empty. 229 delete fields_; 230 fields_ = NULL; 231 } 232} 233 234void UnknownFieldSet::DeleteByNumber(int number) { 235 if (fields_ == NULL) return; 236 int left = 0; // The number of fields left after deletion. 237 for (int i = 0; i < fields_->size(); ++i) { 238 UnknownField* field = &(*fields_)[i]; 239 if (field->number() == number) { 240 field->Delete(); 241 } else { 242 if (i != left) { 243 (*fields_)[left] = (*fields_)[i]; 244 } 245 ++left; 246 } 247 } 248 fields_->resize(left); 249 if (left == 0) { 250 // maintain invariant: never hold fields_ if empty. 251 delete fields_; 252 fields_ = NULL; 253 } 254} 255 256bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { 257 UnknownFieldSet other; 258 if (internal::WireFormat::SkipMessage(input, &other) && 259 input->ConsumedEntireMessage()) { 260 MergeFromAndDestroy(&other); 261 return true; 262 } else { 263 return false; 264 } 265} 266 267bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) { 268 Clear(); 269 return MergeFromCodedStream(input); 270} 271 272bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { 273 io::CodedInputStream coded_input(input); 274 return (ParseFromCodedStream(&coded_input) && 275 coded_input.ConsumedEntireMessage()); 276} 277 278bool UnknownFieldSet::ParseFromArray(const void* data, int size) { 279 io::ArrayInputStream input(data, size); 280 return ParseFromZeroCopyStream(&input); 281} 282 283void UnknownField::Delete() { 284 switch (type()) { 285 case UnknownField::TYPE_LENGTH_DELIMITED: 286 delete length_delimited_.string_value_; 287 break; 288 case UnknownField::TYPE_GROUP: 289 delete group_; 290 break; 291 default: 292 break; 293 } 294} 295 296// Reset all owned ptrs, a special function for performance, to avoid double 297// owning the ptrs, when we merge from a temporary UnknownFieldSet objects. 298void UnknownField::Reset() { 299 switch (type()) { 300 case UnknownField::TYPE_LENGTH_DELIMITED: 301 length_delimited_.string_value_ = NULL; 302 break; 303 case UnknownField::TYPE_GROUP: { 304 group_ = NULL; 305 break; 306 } 307 default: 308 break; 309 } 310} 311 312void UnknownField::DeepCopy(const UnknownField& other) { 313 switch (type()) { 314 case UnknownField::TYPE_LENGTH_DELIMITED: 315 length_delimited_.string_value_ = new string( 316 *length_delimited_.string_value_); 317 break; 318 case UnknownField::TYPE_GROUP: { 319 UnknownFieldSet* group = new UnknownFieldSet(); 320 group->InternalMergeFrom(*group_); 321 group_ = group; 322 break; 323 } 324 default: 325 break; 326 } 327} 328 329 330void UnknownField::SerializeLengthDelimitedNoTag( 331 io::CodedOutputStream* output) const { 332 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); 333 const string& data = *length_delimited_.string_value_; 334 output->WriteVarint32(data.size()); 335 output->WriteRawMaybeAliased(data.data(), data.size()); 336} 337 338uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const { 339 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); 340 const string& data = *length_delimited_.string_value_; 341 target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); 342 target = io::CodedOutputStream::WriteStringToArray(data, target); 343 return target; 344} 345 346} // namespace protobuf 347} // namespace google 348