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// wink@google.com (Wink Saville) (refactored from wire_format.h) 33// Based on original Protocol Buffers design by 34// Sanjay Ghemawat, Jeff Dean, and others. 35 36#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ 37#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ 38 39#ifdef _MSC_VER 40// This is required for min/max on VS2013 only. 41#include <algorithm> 42#endif 43 44#include <string> 45#include <google/protobuf/stubs/common.h> 46#include <google/protobuf/message_lite.h> 47#include <google/protobuf/repeated_field.h> 48#include <google/protobuf/wire_format_lite.h> 49#include <google/protobuf/io/coded_stream.h> 50 51 52namespace google { 53namespace protobuf { 54namespace internal { 55 56// Implementation details of ReadPrimitive. 57 58template <> 59inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>( 60 io::CodedInputStream* input, 61 int32* value) { 62 uint32 temp; 63 if (!input->ReadVarint32(&temp)) return false; 64 *value = static_cast<int32>(temp); 65 return true; 66} 67template <> 68inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_INT64>( 69 io::CodedInputStream* input, 70 int64* value) { 71 uint64 temp; 72 if (!input->ReadVarint64(&temp)) return false; 73 *value = static_cast<int64>(temp); 74 return true; 75} 76template <> 77inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>( 78 io::CodedInputStream* input, 79 uint32* value) { 80 return input->ReadVarint32(value); 81} 82template <> 83inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>( 84 io::CodedInputStream* input, 85 uint64* value) { 86 return input->ReadVarint64(value); 87} 88template <> 89inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>( 90 io::CodedInputStream* input, 91 int32* value) { 92 uint32 temp; 93 if (!input->ReadVarint32(&temp)) return false; 94 *value = ZigZagDecode32(temp); 95 return true; 96} 97template <> 98inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>( 99 io::CodedInputStream* input, 100 int64* value) { 101 uint64 temp; 102 if (!input->ReadVarint64(&temp)) return false; 103 *value = ZigZagDecode64(temp); 104 return true; 105} 106template <> 107inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_FIXED32>( 108 io::CodedInputStream* input, 109 uint32* value) { 110 return input->ReadLittleEndian32(value); 111} 112template <> 113inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_FIXED64>( 114 io::CodedInputStream* input, 115 uint64* value) { 116 return input->ReadLittleEndian64(value); 117} 118template <> 119inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SFIXED32>( 120 io::CodedInputStream* input, 121 int32* value) { 122 uint32 temp; 123 if (!input->ReadLittleEndian32(&temp)) return false; 124 *value = static_cast<int32>(temp); 125 return true; 126} 127template <> 128inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SFIXED64>( 129 io::CodedInputStream* input, 130 int64* value) { 131 uint64 temp; 132 if (!input->ReadLittleEndian64(&temp)) return false; 133 *value = static_cast<int64>(temp); 134 return true; 135} 136template <> 137inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>( 138 io::CodedInputStream* input, 139 float* value) { 140 uint32 temp; 141 if (!input->ReadLittleEndian32(&temp)) return false; 142 *value = DecodeFloat(temp); 143 return true; 144} 145template <> 146inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>( 147 io::CodedInputStream* input, 148 double* value) { 149 uint64 temp; 150 if (!input->ReadLittleEndian64(&temp)) return false; 151 *value = DecodeDouble(temp); 152 return true; 153} 154template <> 155inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>( 156 io::CodedInputStream* input, 157 bool* value) { 158 uint64 temp; 159 if (!input->ReadVarint64(&temp)) return false; 160 *value = temp != 0; 161 return true; 162} 163template <> 164inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( 165 io::CodedInputStream* input, 166 int* value) { 167 uint32 temp; 168 if (!input->ReadVarint32(&temp)) return false; 169 *value = static_cast<int>(temp); 170 return true; 171} 172 173template <> 174inline const uint8* WireFormatLite::ReadPrimitiveFromArray< 175 uint32, WireFormatLite::TYPE_FIXED32>( 176 const uint8* buffer, 177 uint32* value) { 178 return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value); 179} 180template <> 181inline const uint8* WireFormatLite::ReadPrimitiveFromArray< 182 uint64, WireFormatLite::TYPE_FIXED64>( 183 const uint8* buffer, 184 uint64* value) { 185 return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value); 186} 187template <> 188inline const uint8* WireFormatLite::ReadPrimitiveFromArray< 189 int32, WireFormatLite::TYPE_SFIXED32>( 190 const uint8* buffer, 191 int32* value) { 192 uint32 temp; 193 buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); 194 *value = static_cast<int32>(temp); 195 return buffer; 196} 197template <> 198inline const uint8* WireFormatLite::ReadPrimitiveFromArray< 199 int64, WireFormatLite::TYPE_SFIXED64>( 200 const uint8* buffer, 201 int64* value) { 202 uint64 temp; 203 buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); 204 *value = static_cast<int64>(temp); 205 return buffer; 206} 207template <> 208inline const uint8* WireFormatLite::ReadPrimitiveFromArray< 209 float, WireFormatLite::TYPE_FLOAT>( 210 const uint8* buffer, 211 float* value) { 212 uint32 temp; 213 buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); 214 *value = DecodeFloat(temp); 215 return buffer; 216} 217template <> 218inline const uint8* WireFormatLite::ReadPrimitiveFromArray< 219 double, WireFormatLite::TYPE_DOUBLE>( 220 const uint8* buffer, 221 double* value) { 222 uint64 temp; 223 buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); 224 *value = DecodeDouble(temp); 225 return buffer; 226} 227 228template <typename CType, enum WireFormatLite::FieldType DeclaredType> 229inline bool WireFormatLite::ReadRepeatedPrimitive( 230 int, // tag_size, unused. 231 uint32 tag, 232 io::CodedInputStream* input, 233 RepeatedField<CType>* values) { 234 CType value; 235 if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; 236 values->Add(value); 237 int elements_already_reserved = values->Capacity() - values->size(); 238 while (elements_already_reserved > 0 && input->ExpectTag(tag)) { 239 if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; 240 values->AddAlreadyReserved(value); 241 elements_already_reserved--; 242 } 243 return true; 244} 245 246template <typename CType, enum WireFormatLite::FieldType DeclaredType> 247inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( 248 int tag_size, 249 uint32 tag, 250 io::CodedInputStream* input, 251 RepeatedField<CType>* values) { 252 GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size); 253 CType value; 254 if (!ReadPrimitive<CType, DeclaredType>(input, &value)) 255 return false; 256 values->Add(value); 257 258 // For fixed size values, repeated values can be read more quickly by 259 // reading directly from a raw array. 260 // 261 // We can get a tight loop by only reading as many elements as can be 262 // added to the RepeatedField without having to do any resizing. Additionally, 263 // we only try to read as many elements as are available from the current 264 // buffer space. Doing so avoids having to perform boundary checks when 265 // reading the value: the maximum number of elements that can be read is 266 // known outside of the loop. 267 const void* void_pointer; 268 int size; 269 input->GetDirectBufferPointerInline(&void_pointer, &size); 270 if (size > 0) { 271 const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer); 272 // The number of bytes each type occupies on the wire. 273 const int per_value_size = tag_size + sizeof(value); 274 275 int elements_available = min(values->Capacity() - values->size(), 276 size / per_value_size); 277 int num_read = 0; 278 while (num_read < elements_available && 279 (buffer = io::CodedInputStream::ExpectTagFromArray( 280 buffer, tag)) != NULL) { 281 buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value); 282 values->AddAlreadyReserved(value); 283 ++num_read; 284 } 285 const int read_bytes = num_read * per_value_size; 286 if (read_bytes > 0) { 287 input->Skip(read_bytes); 288 } 289 } 290 return true; 291} 292 293// Specializations of ReadRepeatedPrimitive for the fixed size types, which use 294// the optimized code path. 295#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ 296template <> \ 297inline bool WireFormatLite::ReadRepeatedPrimitive< \ 298 CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ 299 int tag_size, \ 300 uint32 tag, \ 301 io::CodedInputStream* input, \ 302 RepeatedField<CPPTYPE>* values) { \ 303 return ReadRepeatedFixedSizePrimitive< \ 304 CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ 305 tag_size, tag, input, values); \ 306} 307 308READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32) 309READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64) 310READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32) 311READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64) 312READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) 313READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) 314 315#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE 316 317template <typename CType, enum WireFormatLite::FieldType DeclaredType> 318bool WireFormatLite::ReadRepeatedPrimitiveNoInline( 319 int tag_size, 320 uint32 tag, 321 io::CodedInputStream* input, 322 RepeatedField<CType>* value) { 323 return ReadRepeatedPrimitive<CType, DeclaredType>( 324 tag_size, tag, input, value); 325} 326 327template <typename CType, enum WireFormatLite::FieldType DeclaredType> 328inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, 329 RepeatedField<CType>* values) { 330 uint32 length; 331 if (!input->ReadVarint32(&length)) return false; 332 io::CodedInputStream::Limit limit = input->PushLimit(length); 333 while (input->BytesUntilLimit() > 0) { 334 CType value; 335 if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; 336 values->Add(value); 337 } 338 input->PopLimit(limit); 339 return true; 340} 341 342template <typename CType, enum WireFormatLite::FieldType DeclaredType> 343inline bool WireFormatLite::ReadPackedFixedSizePrimitive( 344 io::CodedInputStream* input, RepeatedField<CType>* values) { 345 uint32 length; 346 if (!input->ReadVarint32(&length)) return false; 347 const uint32 old_entries = values->size(); 348 const uint32 new_entries = length / sizeof(CType); 349 const uint32 new_bytes = new_entries * sizeof(CType); 350 if (new_bytes != length) return false; 351 // We would *like* to pre-allocate the buffer to write into (for 352 // speed), but *must* avoid performing a very large allocation due 353 // to a malicious user-supplied "length" above. So we have a fast 354 // path that pre-allocates when the "length" is less than a bound. 355 // We determine the bound by calling BytesUntilTotalBytesLimit() and 356 // BytesUntilLimit(). These return -1 to mean "no limit set". 357 // There are four cases: 358 // TotalBytesLimit Limit 359 // -1 -1 Use slow path. 360 // -1 >= 0 Use fast path if length <= Limit. 361 // >= 0 -1 Use slow path. 362 // >= 0 >= 0 Use fast path if length <= min(both limits). 363 int64 bytes_limit = input->BytesUntilTotalBytesLimit(); 364 if (bytes_limit == -1) { 365 bytes_limit = input->BytesUntilLimit(); 366 } else { 367 bytes_limit = 368 min(bytes_limit, static_cast<int64>(input->BytesUntilLimit())); 369 } 370 if (bytes_limit >= new_bytes) { 371 // Fast-path that pre-allocates *values to the final size. 372#if defined(PROTOBUF_LITTLE_ENDIAN) 373 values->Resize(old_entries + new_entries, 0); 374 // values->mutable_data() may change after Resize(), so do this after: 375 void* dest = reinterpret_cast<void*>(values->mutable_data() + old_entries); 376 if (!input->ReadRaw(dest, new_bytes)) { 377 values->Truncate(old_entries); 378 return false; 379 } 380#else 381 values->Reserve(old_entries + new_entries); 382 CType value; 383 for (uint32 i = 0; i < new_entries; ++i) { 384 if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; 385 values->AddAlreadyReserved(value); 386 } 387#endif 388 } else { 389 // This is the slow-path case where "length" may be too large to 390 // safely allocate. We read as much as we can into *values 391 // without pre-allocating "length" bytes. 392 CType value; 393 for (uint32 i = 0; i < new_entries; ++i) { 394 if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; 395 values->Add(value); 396 } 397 } 398 return true; 399} 400 401// Specializations of ReadPackedPrimitive for the fixed size types, which use 402// an optimized code path. 403#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ 404template <> \ 405inline bool WireFormatLite::ReadPackedPrimitive< \ 406 CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ 407 io::CodedInputStream* input, \ 408 RepeatedField<CPPTYPE>* values) { \ 409 return ReadPackedFixedSizePrimitive< \ 410 CPPTYPE, WireFormatLite::DECLARED_TYPE>(input, values); \ 411} 412 413READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32); 414READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64); 415READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32); 416READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64); 417READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT); 418READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE); 419 420#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE 421 422template <typename CType, enum WireFormatLite::FieldType DeclaredType> 423bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, 424 RepeatedField<CType>* values) { 425 return ReadPackedPrimitive<CType, DeclaredType>(input, values); 426} 427 428 429inline bool WireFormatLite::ReadGroup(int field_number, 430 io::CodedInputStream* input, 431 MessageLite* value) { 432 if (!input->IncrementRecursionDepth()) return false; 433 if (!value->MergePartialFromCodedStream(input)) return false; 434 input->DecrementRecursionDepth(); 435 // Make sure the last thing read was an end tag for this group. 436 if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { 437 return false; 438 } 439 return true; 440} 441inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, 442 MessageLite* value) { 443 uint32 length; 444 if (!input->ReadVarint32(&length)) return false; 445 if (!input->IncrementRecursionDepth()) return false; 446 io::CodedInputStream::Limit limit = input->PushLimit(length); 447 if (!value->MergePartialFromCodedStream(input)) return false; 448 // Make sure that parsing stopped when the limit was hit, not at an endgroup 449 // tag. 450 if (!input->ConsumedEntireMessage()) return false; 451 input->PopLimit(limit); 452 input->DecrementRecursionDepth(); 453 return true; 454} 455 456// We name the template parameter something long and extremely unlikely to occur 457// elsewhere because a *qualified* member access expression designed to avoid 458// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the 459// name of the qualifying class to be looked up both in the context of the full 460// expression (finding the template parameter) and in the context of the object 461// whose member we are accessing. This could potentially find a nested type 462// within that object. The standard goes on to require these names to refer to 463// the same entity, which this collision would violate. The lack of a safe way 464// to avoid this collision appears to be a defect in the standard, but until it 465// is corrected, we choose the name to avoid accidental collisions. 466template<typename MessageType_WorkAroundCppLookupDefect> 467inline bool WireFormatLite::ReadGroupNoVirtual( 468 int field_number, io::CodedInputStream* input, 469 MessageType_WorkAroundCppLookupDefect* value) { 470 if (!input->IncrementRecursionDepth()) return false; 471 if (!value-> 472 MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) 473 return false; 474 input->DecrementRecursionDepth(); 475 // Make sure the last thing read was an end tag for this group. 476 if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { 477 return false; 478 } 479 return true; 480} 481template<typename MessageType_WorkAroundCppLookupDefect> 482inline bool WireFormatLite::ReadMessageNoVirtual( 483 io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { 484 uint32 length; 485 if (!input->ReadVarint32(&length)) return false; 486 if (!input->IncrementRecursionDepth()) return false; 487 io::CodedInputStream::Limit limit = input->PushLimit(length); 488 if (!value-> 489 MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) 490 return false; 491 // Make sure that parsing stopped when the limit was hit, not at an endgroup 492 // tag. 493 if (!input->ConsumedEntireMessage()) return false; 494 input->PopLimit(limit); 495 input->DecrementRecursionDepth(); 496 return true; 497} 498 499// =================================================================== 500 501inline void WireFormatLite::WriteTag(int field_number, WireType type, 502 io::CodedOutputStream* output) { 503 output->WriteTag(MakeTag(field_number, type)); 504} 505 506inline void WireFormatLite::WriteInt32NoTag(int32 value, 507 io::CodedOutputStream* output) { 508 output->WriteVarint32SignExtended(value); 509} 510inline void WireFormatLite::WriteInt64NoTag(int64 value, 511 io::CodedOutputStream* output) { 512 output->WriteVarint64(static_cast<uint64>(value)); 513} 514inline void WireFormatLite::WriteUInt32NoTag(uint32 value, 515 io::CodedOutputStream* output) { 516 output->WriteVarint32(value); 517} 518inline void WireFormatLite::WriteUInt64NoTag(uint64 value, 519 io::CodedOutputStream* output) { 520 output->WriteVarint64(value); 521} 522inline void WireFormatLite::WriteSInt32NoTag(int32 value, 523 io::CodedOutputStream* output) { 524 output->WriteVarint32(ZigZagEncode32(value)); 525} 526inline void WireFormatLite::WriteSInt64NoTag(int64 value, 527 io::CodedOutputStream* output) { 528 output->WriteVarint64(ZigZagEncode64(value)); 529} 530inline void WireFormatLite::WriteFixed32NoTag(uint32 value, 531 io::CodedOutputStream* output) { 532 output->WriteLittleEndian32(value); 533} 534inline void WireFormatLite::WriteFixed64NoTag(uint64 value, 535 io::CodedOutputStream* output) { 536 output->WriteLittleEndian64(value); 537} 538inline void WireFormatLite::WriteSFixed32NoTag(int32 value, 539 io::CodedOutputStream* output) { 540 output->WriteLittleEndian32(static_cast<uint32>(value)); 541} 542inline void WireFormatLite::WriteSFixed64NoTag(int64 value, 543 io::CodedOutputStream* output) { 544 output->WriteLittleEndian64(static_cast<uint64>(value)); 545} 546inline void WireFormatLite::WriteFloatNoTag(float value, 547 io::CodedOutputStream* output) { 548 output->WriteLittleEndian32(EncodeFloat(value)); 549} 550inline void WireFormatLite::WriteDoubleNoTag(double value, 551 io::CodedOutputStream* output) { 552 output->WriteLittleEndian64(EncodeDouble(value)); 553} 554inline void WireFormatLite::WriteBoolNoTag(bool value, 555 io::CodedOutputStream* output) { 556 output->WriteVarint32(value ? 1 : 0); 557} 558inline void WireFormatLite::WriteEnumNoTag(int value, 559 io::CodedOutputStream* output) { 560 output->WriteVarint32SignExtended(value); 561} 562 563// See comment on ReadGroupNoVirtual to understand the need for this template 564// parameter name. 565template<typename MessageType_WorkAroundCppLookupDefect> 566inline void WireFormatLite::WriteGroupNoVirtual( 567 int field_number, const MessageType_WorkAroundCppLookupDefect& value, 568 io::CodedOutputStream* output) { 569 WriteTag(field_number, WIRETYPE_START_GROUP, output); 570 value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); 571 WriteTag(field_number, WIRETYPE_END_GROUP, output); 572} 573template<typename MessageType_WorkAroundCppLookupDefect> 574inline void WireFormatLite::WriteMessageNoVirtual( 575 int field_number, const MessageType_WorkAroundCppLookupDefect& value, 576 io::CodedOutputStream* output) { 577 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); 578 output->WriteVarint32( 579 value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()); 580 value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); 581} 582 583// =================================================================== 584 585inline uint8* WireFormatLite::WriteTagToArray(int field_number, 586 WireType type, 587 uint8* target) { 588 return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type), 589 target); 590} 591 592inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value, 593 uint8* target) { 594 return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); 595} 596inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value, 597 uint8* target) { 598 return io::CodedOutputStream::WriteVarint64ToArray( 599 static_cast<uint64>(value), target); 600} 601inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value, 602 uint8* target) { 603 return io::CodedOutputStream::WriteVarint32ToArray(value, target); 604} 605inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value, 606 uint8* target) { 607 return io::CodedOutputStream::WriteVarint64ToArray(value, target); 608} 609inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value, 610 uint8* target) { 611 return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value), 612 target); 613} 614inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value, 615 uint8* target) { 616 return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value), 617 target); 618} 619inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value, 620 uint8* target) { 621 return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target); 622} 623inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value, 624 uint8* target) { 625 return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target); 626} 627inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value, 628 uint8* target) { 629 return io::CodedOutputStream::WriteLittleEndian32ToArray( 630 static_cast<uint32>(value), target); 631} 632inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value, 633 uint8* target) { 634 return io::CodedOutputStream::WriteLittleEndian64ToArray( 635 static_cast<uint64>(value), target); 636} 637inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value, 638 uint8* target) { 639 return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value), 640 target); 641} 642inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value, 643 uint8* target) { 644 return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value), 645 target); 646} 647inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value, 648 uint8* target) { 649 return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target); 650} 651inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value, 652 uint8* target) { 653 return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); 654} 655 656inline uint8* WireFormatLite::WriteInt32ToArray(int field_number, 657 int32 value, 658 uint8* target) { 659 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 660 return WriteInt32NoTagToArray(value, target); 661} 662inline uint8* WireFormatLite::WriteInt64ToArray(int field_number, 663 int64 value, 664 uint8* target) { 665 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 666 return WriteInt64NoTagToArray(value, target); 667} 668inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number, 669 uint32 value, 670 uint8* target) { 671 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 672 return WriteUInt32NoTagToArray(value, target); 673} 674inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number, 675 uint64 value, 676 uint8* target) { 677 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 678 return WriteUInt64NoTagToArray(value, target); 679} 680inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number, 681 int32 value, 682 uint8* target) { 683 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 684 return WriteSInt32NoTagToArray(value, target); 685} 686inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number, 687 int64 value, 688 uint8* target) { 689 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 690 return WriteSInt64NoTagToArray(value, target); 691} 692inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number, 693 uint32 value, 694 uint8* target) { 695 target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); 696 return WriteFixed32NoTagToArray(value, target); 697} 698inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number, 699 uint64 value, 700 uint8* target) { 701 target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); 702 return WriteFixed64NoTagToArray(value, target); 703} 704inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number, 705 int32 value, 706 uint8* target) { 707 target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); 708 return WriteSFixed32NoTagToArray(value, target); 709} 710inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number, 711 int64 value, 712 uint8* target) { 713 target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); 714 return WriteSFixed64NoTagToArray(value, target); 715} 716inline uint8* WireFormatLite::WriteFloatToArray(int field_number, 717 float value, 718 uint8* target) { 719 target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); 720 return WriteFloatNoTagToArray(value, target); 721} 722inline uint8* WireFormatLite::WriteDoubleToArray(int field_number, 723 double value, 724 uint8* target) { 725 target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); 726 return WriteDoubleNoTagToArray(value, target); 727} 728inline uint8* WireFormatLite::WriteBoolToArray(int field_number, 729 bool value, 730 uint8* target) { 731 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 732 return WriteBoolNoTagToArray(value, target); 733} 734inline uint8* WireFormatLite::WriteEnumToArray(int field_number, 735 int value, 736 uint8* target) { 737 target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); 738 return WriteEnumNoTagToArray(value, target); 739} 740 741inline uint8* WireFormatLite::WriteStringToArray(int field_number, 742 const string& value, 743 uint8* target) { 744 // String is for UTF-8 text only 745 // WARNING: In wire_format.cc, both strings and bytes are handled by 746 // WriteString() to avoid code duplication. If the implementations become 747 // different, you will need to update that usage. 748 target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); 749 return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); 750} 751inline uint8* WireFormatLite::WriteBytesToArray(int field_number, 752 const string& value, 753 uint8* target) { 754 target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); 755 return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); 756} 757 758 759inline uint8* WireFormatLite::WriteGroupToArray(int field_number, 760 const MessageLite& value, 761 uint8* target) { 762 target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); 763 target = value.SerializeWithCachedSizesToArray(target); 764 return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); 765} 766inline uint8* WireFormatLite::WriteMessageToArray(int field_number, 767 const MessageLite& value, 768 uint8* target) { 769 target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); 770 target = io::CodedOutputStream::WriteVarint32ToArray( 771 value.GetCachedSize(), target); 772 return value.SerializeWithCachedSizesToArray(target); 773} 774 775// See comment on ReadGroupNoVirtual to understand the need for this template 776// parameter name. 777template<typename MessageType_WorkAroundCppLookupDefect> 778inline uint8* WireFormatLite::WriteGroupNoVirtualToArray( 779 int field_number, const MessageType_WorkAroundCppLookupDefect& value, 780 uint8* target) { 781 target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); 782 target = value.MessageType_WorkAroundCppLookupDefect 783 ::SerializeWithCachedSizesToArray(target); 784 return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); 785} 786template<typename MessageType_WorkAroundCppLookupDefect> 787inline uint8* WireFormatLite::WriteMessageNoVirtualToArray( 788 int field_number, const MessageType_WorkAroundCppLookupDefect& value, 789 uint8* target) { 790 target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); 791 target = io::CodedOutputStream::WriteVarint32ToArray( 792 value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target); 793 return value.MessageType_WorkAroundCppLookupDefect 794 ::SerializeWithCachedSizesToArray(target); 795} 796 797// =================================================================== 798 799inline int WireFormatLite::Int32Size(int32 value) { 800 return io::CodedOutputStream::VarintSize32SignExtended(value); 801} 802inline int WireFormatLite::Int64Size(int64 value) { 803 return io::CodedOutputStream::VarintSize64(static_cast<uint64>(value)); 804} 805inline int WireFormatLite::UInt32Size(uint32 value) { 806 return io::CodedOutputStream::VarintSize32(value); 807} 808inline int WireFormatLite::UInt64Size(uint64 value) { 809 return io::CodedOutputStream::VarintSize64(value); 810} 811inline int WireFormatLite::SInt32Size(int32 value) { 812 return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); 813} 814inline int WireFormatLite::SInt64Size(int64 value) { 815 return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); 816} 817inline int WireFormatLite::EnumSize(int value) { 818 return io::CodedOutputStream::VarintSize32SignExtended(value); 819} 820 821inline int WireFormatLite::StringSize(const string& value) { 822 return io::CodedOutputStream::VarintSize32(value.size()) + 823 value.size(); 824} 825inline int WireFormatLite::BytesSize(const string& value) { 826 return io::CodedOutputStream::VarintSize32(value.size()) + 827 value.size(); 828} 829 830 831inline int WireFormatLite::GroupSize(const MessageLite& value) { 832 return value.ByteSize(); 833} 834inline int WireFormatLite::MessageSize(const MessageLite& value) { 835 return LengthDelimitedSize(value.ByteSize()); 836} 837 838// See comment on ReadGroupNoVirtual to understand the need for this template 839// parameter name. 840template<typename MessageType_WorkAroundCppLookupDefect> 841inline int WireFormatLite::GroupSizeNoVirtual( 842 const MessageType_WorkAroundCppLookupDefect& value) { 843 return value.MessageType_WorkAroundCppLookupDefect::ByteSize(); 844} 845template<typename MessageType_WorkAroundCppLookupDefect> 846inline int WireFormatLite::MessageSizeNoVirtual( 847 const MessageType_WorkAroundCppLookupDefect& value) { 848 return LengthDelimitedSize( 849 value.MessageType_WorkAroundCppLookupDefect::ByteSize()); 850} 851 852inline int WireFormatLite::LengthDelimitedSize(int length) { 853 return io::CodedOutputStream::VarintSize32(length) + length; 854} 855 856} // namespace internal 857} // namespace protobuf 858 859} // namespace google 860#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ 861