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/unknown_field_set.h> 36 37 #include <google/protobuf/stubs/common.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_lite.h> 41 #include <google/protobuf/wire_format_lite.h> 42 #include <google/protobuf/stubs/stl_util.h> 43 44 namespace google { 45 namespace protobuf { 46 47 namespace internal { 48 49 int StringSpaceUsedExcludingSelf(const string& str) { 50 const void* start = &str; 51 const void* end = &str + 1; 52 53 if (start <= str.data() && str.data() <= end) { 54 // The string's data is stored inside the string object itself. 55 return 0; 56 } else { 57 return str.capacity(); 58 } 59 } 60 61 } 62 63 UnknownFieldSet::UnknownFieldSet() 64 : fields_(NULL) {} 65 66 UnknownFieldSet::~UnknownFieldSet() { 67 Clear(); 68 delete fields_; 69 } 70 71 void UnknownFieldSet::ClearFallback() { 72 GOOGLE_DCHECK(fields_ != NULL); 73 for (int i = 0; i < fields_->size(); i++) { 74 (*fields_)[i].Delete(); 75 } 76 fields_->clear(); 77 } 78 79 void UnknownFieldSet::ClearAndFreeMemory() { 80 if (fields_ != NULL) { 81 Clear(); 82 delete fields_; 83 fields_ = NULL; 84 } 85 } 86 87 void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { 88 for (int i = 0; i < other.field_count(); i++) { 89 AddField(other.field(i)); 90 } 91 } 92 93 int UnknownFieldSet::SpaceUsedExcludingSelf() const { 94 if (fields_ == NULL) return 0; 95 96 int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size(); 97 for (int i = 0; i < fields_->size(); i++) { 98 const UnknownField& field = (*fields_)[i]; 99 switch (field.type()) { 100 case UnknownField::TYPE_LENGTH_DELIMITED: 101 total_size += sizeof(*field.length_delimited_.string_value_) + 102 internal::StringSpaceUsedExcludingSelf( 103 *field.length_delimited_.string_value_); 104 break; 105 case UnknownField::TYPE_GROUP: 106 total_size += field.group_->SpaceUsed(); 107 break; 108 default: 109 break; 110 } 111 } 112 return total_size; 113 } 114 115 int UnknownFieldSet::SpaceUsed() const { 116 return sizeof(*this) + SpaceUsedExcludingSelf(); 117 } 118 119 void UnknownFieldSet::AddVarint(int number, uint64 value) { 120 if (fields_ == NULL) fields_ = new vector<UnknownField>; 121 UnknownField field; 122 field.number_ = number; 123 field.type_ = UnknownField::TYPE_VARINT; 124 field.varint_ = value; 125 fields_->push_back(field); 126 } 127 128 void UnknownFieldSet::AddFixed32(int number, uint32 value) { 129 if (fields_ == NULL) fields_ = new vector<UnknownField>; 130 UnknownField field; 131 field.number_ = number; 132 field.type_ = UnknownField::TYPE_FIXED32; 133 field.fixed32_ = value; 134 fields_->push_back(field); 135 } 136 137 void UnknownFieldSet::AddFixed64(int number, uint64 value) { 138 if (fields_ == NULL) fields_ = new vector<UnknownField>; 139 UnknownField field; 140 field.number_ = number; 141 field.type_ = UnknownField::TYPE_FIXED64; 142 field.fixed64_ = value; 143 fields_->push_back(field); 144 } 145 146 string* UnknownFieldSet::AddLengthDelimited(int number) { 147 if (fields_ == NULL) fields_ = new vector<UnknownField>; 148 UnknownField field; 149 field.number_ = number; 150 field.type_ = UnknownField::TYPE_LENGTH_DELIMITED; 151 field.length_delimited_.string_value_ = new string; 152 fields_->push_back(field); 153 return field.length_delimited_.string_value_; 154 } 155 156 157 UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { 158 if (fields_ == NULL) fields_ = new vector<UnknownField>; 159 UnknownField field; 160 field.number_ = number; 161 field.type_ = UnknownField::TYPE_GROUP; 162 field.group_ = new UnknownFieldSet; 163 fields_->push_back(field); 164 return field.group_; 165 } 166 167 void UnknownFieldSet::AddField(const UnknownField& field) { 168 if (fields_ == NULL) fields_ = new vector<UnknownField>; 169 fields_->push_back(field); 170 fields_->back().DeepCopy(); 171 } 172 173 void UnknownFieldSet::DeleteSubrange(int start, int num) { 174 GOOGLE_DCHECK(fields_ != NULL); 175 // Delete the specified fields. 176 for (int i = 0; i < num; ++i) { 177 (*fields_)[i + start].Delete(); 178 } 179 // Slide down the remaining fields. 180 for (int i = start + num; i < fields_->size(); ++i) { 181 (*fields_)[i - num] = (*fields_)[i]; 182 } 183 // Pop off the # of deleted fields. 184 for (int i = 0; i < num; ++i) { 185 fields_->pop_back(); 186 } 187 } 188 189 void UnknownFieldSet::DeleteByNumber(int number) { 190 if (fields_ == NULL) return; 191 int left = 0; // The number of fields left after deletion. 192 for (int i = 0; i < fields_->size(); ++i) { 193 UnknownField* field = &(*fields_)[i]; 194 if (field->number() == number) { 195 field->Delete(); 196 } else { 197 if (i != left) { 198 (*fields_)[left] = (*fields_)[i]; 199 } 200 ++left; 201 } 202 } 203 fields_->resize(left); 204 } 205 206 bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { 207 208 UnknownFieldSet other; 209 if (internal::WireFormatLite::SkipMessage(input, &other) && 210 input->ConsumedEntireMessage()) { 211 MergeFrom(other); 212 return true; 213 } else { 214 return false; 215 } 216 } 217 218 bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) { 219 Clear(); 220 return MergeFromCodedStream(input); 221 } 222 223 bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { 224 io::CodedInputStream coded_input(input); 225 return ParseFromCodedStream(&coded_input) && 226 coded_input.ConsumedEntireMessage(); 227 } 228 229 bool UnknownFieldSet::ParseFromArray(const void* data, int size) { 230 io::ArrayInputStream input(data, size); 231 return ParseFromZeroCopyStream(&input); 232 } 233 234 void UnknownField::Delete() { 235 switch (type()) { 236 case UnknownField::TYPE_LENGTH_DELIMITED: 237 delete length_delimited_.string_value_; 238 break; 239 case UnknownField::TYPE_GROUP: 240 delete group_; 241 break; 242 default: 243 break; 244 } 245 } 246 247 void UnknownField::DeepCopy() { 248 switch (type()) { 249 case UnknownField::TYPE_LENGTH_DELIMITED: 250 length_delimited_.string_value_ = new string( 251 *length_delimited_.string_value_); 252 break; 253 case UnknownField::TYPE_GROUP: { 254 UnknownFieldSet* group = new UnknownFieldSet; 255 group->MergeFrom(*group_); 256 group_ = group; 257 break; 258 } 259 default: 260 break; 261 } 262 } 263 264 265 void UnknownField::SerializeLengthDelimitedNoTag( 266 io::CodedOutputStream* output) const { 267 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); 268 const string& data = *length_delimited_.string_value_; 269 output->WriteVarint32(data.size()); 270 output->WriteString(data); 271 } 272 273 uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const { 274 GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); 275 const string& data = *length_delimited_.string_value_; 276 target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); 277 target = io::CodedOutputStream::WriteStringToArray(data, target); 278 return target; 279 } 280 281 } // namespace protobuf 282 } // namespace google 283