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