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/wire_format_lite.h>
36
37#include <limits>
38#include <stack>
39#include <string>
40#include <vector>
41
42#include <google/protobuf/stubs/logging.h>
43#include <google/protobuf/stubs/common.h>
44#include <google/protobuf/io/coded_stream.h>
45#include <google/protobuf/io/zero_copy_stream.h>
46#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
47#include <google/protobuf/stubs/stringprintf.h>
48
49
50// Must be included last.
51#include <google/protobuf/port_def.inc>
52
53namespace google {
54namespace protobuf {
55namespace internal {
56
57#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)
58// Old version of MSVC doesn't like definitions of inline constants, GCC
59// requires them.
60const int WireFormatLite::kMessageSetItemStartTag;
61const int WireFormatLite::kMessageSetItemEndTag;
62const int WireFormatLite::kMessageSetTypeIdTag;
63const int WireFormatLite::kMessageSetMessageTag;
64
65#endif
66
67// IBM xlC requires prefixing constants with WireFormatLite::
68const size_t WireFormatLite::kMessageSetItemTagsSize =
69 io::CodedOutputStream::StaticVarintSize32<
70 WireFormatLite::kMessageSetItemStartTag>::value +
71 io::CodedOutputStream::StaticVarintSize32<
72 WireFormatLite::kMessageSetItemEndTag>::value +
73 io::CodedOutputStream::StaticVarintSize32<
74 WireFormatLite::kMessageSetTypeIdTag>::value +
75 io::CodedOutputStream::StaticVarintSize32<
76 WireFormatLite::kMessageSetMessageTag>::value;
77
78const WireFormatLite::CppType
79 WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
80 static_cast<CppType>(0), // 0 is reserved for errors
81
82 CPPTYPE_DOUBLE, // TYPE_DOUBLE
83 CPPTYPE_FLOAT, // TYPE_FLOAT
84 CPPTYPE_INT64, // TYPE_INT64
85 CPPTYPE_UINT64, // TYPE_UINT64
86 CPPTYPE_INT32, // TYPE_INT32
87 CPPTYPE_UINT64, // TYPE_FIXED64
88 CPPTYPE_UINT32, // TYPE_FIXED32
89 CPPTYPE_BOOL, // TYPE_BOOL
90 CPPTYPE_STRING, // TYPE_STRING
91 CPPTYPE_MESSAGE, // TYPE_GROUP
92 CPPTYPE_MESSAGE, // TYPE_MESSAGE
93 CPPTYPE_STRING, // TYPE_BYTES
94 CPPTYPE_UINT32, // TYPE_UINT32
95 CPPTYPE_ENUM, // TYPE_ENUM
96 CPPTYPE_INT32, // TYPE_SFIXED32
97 CPPTYPE_INT64, // TYPE_SFIXED64
98 CPPTYPE_INT32, // TYPE_SINT32
99 CPPTYPE_INT64, // TYPE_SINT64
100};
101
102const WireFormatLite::WireType
103 WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
104 static_cast<WireFormatLite::WireType>(-1), // invalid
105 WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE
106 WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT
107 WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64
108 WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64
109 WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32
110 WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64
111 WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32
112 WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL
113 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING
114 WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP
115 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE
116 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES
117 WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32
118 WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM
119 WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32
120 WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64
121 WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32
122 WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64
123};
124
125bool WireFormatLite::SkipField(io::CodedInputStream* input, uint32_t tag) {
126 // Field number 0 is illegal.
127 if (WireFormatLite::GetTagFieldNumber(tag) == 0) return false;
128 switch (WireFormatLite::GetTagWireType(tag)) {
129 case WireFormatLite::WIRETYPE_VARINT: {
130 uint64_t value;
131 if (!input->ReadVarint64(value: &value)) return false;
132 return true;
133 }
134 case WireFormatLite::WIRETYPE_FIXED64: {
135 uint64_t value;
136 if (!input->ReadLittleEndian64(value: &value)) return false;
137 return true;
138 }
139 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
140 uint32_t length;
141 if (!input->ReadVarint32(value: &length)) return false;
142 if (!input->Skip(count: length)) return false;
143 return true;
144 }
145 case WireFormatLite::WIRETYPE_START_GROUP: {
146 if (!input->IncrementRecursionDepth()) return false;
147 if (!SkipMessage(input)) return false;
148 input->DecrementRecursionDepth();
149 // Check that the ending tag matched the starting tag.
150 if (!input->LastTagWas(
151 expected: WireFormatLite::MakeTag(field_number: WireFormatLite::GetTagFieldNumber(tag),
152 type: WireFormatLite::WIRETYPE_END_GROUP))) {
153 return false;
154 }
155 return true;
156 }
157 case WireFormatLite::WIRETYPE_END_GROUP: {
158 return false;
159 }
160 case WireFormatLite::WIRETYPE_FIXED32: {
161 uint32_t value;
162 if (!input->ReadLittleEndian32(value: &value)) return false;
163 return true;
164 }
165 default: {
166 return false;
167 }
168 }
169}
170
171bool WireFormatLite::SkipField(io::CodedInputStream* input, uint32_t tag,
172 io::CodedOutputStream* output) {
173 // Field number 0 is illegal.
174 if (WireFormatLite::GetTagFieldNumber(tag) == 0) return false;
175 switch (WireFormatLite::GetTagWireType(tag)) {
176 case WireFormatLite::WIRETYPE_VARINT: {
177 uint64_t value;
178 if (!input->ReadVarint64(value: &value)) return false;
179 output->WriteVarint32(value: tag);
180 output->WriteVarint64(value);
181 return true;
182 }
183 case WireFormatLite::WIRETYPE_FIXED64: {
184 uint64_t value;
185 if (!input->ReadLittleEndian64(value: &value)) return false;
186 output->WriteVarint32(value: tag);
187 output->WriteLittleEndian64(value);
188 return true;
189 }
190 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
191 uint32_t length;
192 if (!input->ReadVarint32(value: &length)) return false;
193 output->WriteVarint32(value: tag);
194 output->WriteVarint32(value: length);
195 // TODO(mkilavuz): Provide API to prevent extra string copying.
196 std::string temp;
197 if (!input->ReadString(buffer: &temp, size: length)) return false;
198 output->WriteString(str: temp);
199 return true;
200 }
201 case WireFormatLite::WIRETYPE_START_GROUP: {
202 output->WriteVarint32(value: tag);
203 if (!input->IncrementRecursionDepth()) return false;
204 if (!SkipMessage(input, output)) return false;
205 input->DecrementRecursionDepth();
206 // Check that the ending tag matched the starting tag.
207 if (!input->LastTagWas(
208 expected: WireFormatLite::MakeTag(field_number: WireFormatLite::GetTagFieldNumber(tag),
209 type: WireFormatLite::WIRETYPE_END_GROUP))) {
210 return false;
211 }
212 return true;
213 }
214 case WireFormatLite::WIRETYPE_END_GROUP: {
215 return false;
216 }
217 case WireFormatLite::WIRETYPE_FIXED32: {
218 uint32_t value;
219 if (!input->ReadLittleEndian32(value: &value)) return false;
220 output->WriteVarint32(value: tag);
221 output->WriteLittleEndian32(value);
222 return true;
223 }
224 default: {
225 return false;
226 }
227 }
228}
229
230bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
231 while (true) {
232 uint32_t tag = input->ReadTag();
233 if (tag == 0) {
234 // End of input. This is a valid place to end, so return true.
235 return true;
236 }
237
238 WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
239
240 if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
241 // Must be the end of the message.
242 return true;
243 }
244
245 if (!SkipField(input, tag)) return false;
246 }
247}
248
249bool WireFormatLite::SkipMessage(io::CodedInputStream* input,
250 io::CodedOutputStream* output) {
251 while (true) {
252 uint32_t tag = input->ReadTag();
253 if (tag == 0) {
254 // End of input. This is a valid place to end, so return true.
255 return true;
256 }
257
258 WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
259
260 if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
261 output->WriteVarint32(value: tag);
262 // Must be the end of the message.
263 return true;
264 }
265
266 if (!SkipField(input, tag, output)) return false;
267 }
268}
269
270bool FieldSkipper::SkipField(io::CodedInputStream* input, uint32_t tag) {
271 return WireFormatLite::SkipField(input, tag);
272}
273
274bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
275 return WireFormatLite::SkipMessage(input);
276}
277
278void FieldSkipper::SkipUnknownEnum(int /* field_number */, int /* value */) {
279 // Nothing.
280}
281
282bool CodedOutputStreamFieldSkipper::SkipField(io::CodedInputStream* input,
283 uint32_t tag) {
284 return WireFormatLite::SkipField(input, tag, output: unknown_fields_);
285}
286
287bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) {
288 return WireFormatLite::SkipMessage(input, output: unknown_fields_);
289}
290
291void CodedOutputStreamFieldSkipper::SkipUnknownEnum(int field_number,
292 int value) {
293 unknown_fields_->WriteVarint32(value: field_number);
294 unknown_fields_->WriteVarint64(value);
295}
296
297bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
298 io::CodedInputStream* input, int field_number, bool (*is_valid)(int),
299 io::CodedOutputStream* unknown_fields_stream, RepeatedField<int>* values) {
300 uint32_t length;
301 if (!input->ReadVarint32(value: &length)) return false;
302 io::CodedInputStream::Limit limit = input->PushLimit(byte_limit: length);
303 while (input->BytesUntilLimit() > 0) {
304 int value;
305 if (!ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(input, value: &value)) {
306 return false;
307 }
308 if (is_valid == nullptr || is_valid(value)) {
309 values->Add(value);
310 } else {
311 uint32_t tag = WireFormatLite::MakeTag(field_number,
312 type: WireFormatLite::WIRETYPE_VARINT);
313 unknown_fields_stream->WriteVarint32(value: tag);
314 unknown_fields_stream->WriteVarint32(value);
315 }
316 }
317 input->PopLimit(limit);
318 return true;
319}
320
321#if !defined(PROTOBUF_LITTLE_ENDIAN)
322
323namespace {
324void EncodeFixedSizeValue(float v, uint8_t* dest) {
325 WireFormatLite::WriteFloatNoTagToArray(v, dest);
326}
327
328void EncodeFixedSizeValue(double v, uint8_t* dest) {
329 WireFormatLite::WriteDoubleNoTagToArray(v, dest);
330}
331
332void EncodeFixedSizeValue(uint32_t v, uint8_t* dest) {
333 WireFormatLite::WriteFixed32NoTagToArray(v, dest);
334}
335
336void EncodeFixedSizeValue(uint64_t v, uint8_t* dest) {
337 WireFormatLite::WriteFixed64NoTagToArray(v, dest);
338}
339
340void EncodeFixedSizeValue(int32_t v, uint8_t* dest) {
341 WireFormatLite::WriteSFixed32NoTagToArray(v, dest);
342}
343
344void EncodeFixedSizeValue(int64_t v, uint8_t* dest) {
345 WireFormatLite::WriteSFixed64NoTagToArray(v, dest);
346}
347
348void EncodeFixedSizeValue(bool v, uint8_t* dest) {
349 WireFormatLite::WriteBoolNoTagToArray(v, dest);
350}
351} // anonymous namespace
352
353#endif // !defined(PROTOBUF_LITTLE_ENDIAN)
354
355template <typename CType>
356static void WriteArray(const CType* a, int n, io::CodedOutputStream* output) {
357#if defined(PROTOBUF_LITTLE_ENDIAN)
358 output->WriteRaw(buffer: reinterpret_cast<const char*>(a), size: n * sizeof(a[0]));
359#else
360 const int kAtATime = 128;
361 uint8_t buf[sizeof(CType) * kAtATime];
362 for (int i = 0; i < n; i += kAtATime) {
363 int to_do = std::min(kAtATime, n - i);
364 uint8_t* ptr = buf;
365 for (int j = 0; j < to_do; j++) {
366 EncodeFixedSizeValue(a[i + j], ptr);
367 ptr += sizeof(a[0]);
368 }
369 output->WriteRaw(buf, to_do * sizeof(a[0]));
370 }
371#endif
372}
373
374void WireFormatLite::WriteFloatArray(const float* a, int n,
375 io::CodedOutputStream* output) {
376 WriteArray<float>(a, n, output);
377}
378
379void WireFormatLite::WriteDoubleArray(const double* a, int n,
380 io::CodedOutputStream* output) {
381 WriteArray<double>(a, n, output);
382}
383
384void WireFormatLite::WriteFixed32Array(const uint32_t* a, int n,
385 io::CodedOutputStream* output) {
386 WriteArray<uint32_t>(a, n, output);
387}
388
389void WireFormatLite::WriteFixed64Array(const uint64_t* a, int n,
390 io::CodedOutputStream* output) {
391 WriteArray<uint64_t>(a, n, output);
392}
393
394void WireFormatLite::WriteSFixed32Array(const int32_t* a, int n,
395 io::CodedOutputStream* output) {
396 WriteArray<int32_t>(a, n, output);
397}
398
399void WireFormatLite::WriteSFixed64Array(const int64_t* a, int n,
400 io::CodedOutputStream* output) {
401 WriteArray<int64_t>(a, n, output);
402}
403
404void WireFormatLite::WriteBoolArray(const bool* a, int n,
405 io::CodedOutputStream* output) {
406 WriteArray<bool>(a, n, output);
407}
408
409void WireFormatLite::WriteInt32(int field_number, int32_t value,
410 io::CodedOutputStream* output) {
411 WriteTag(field_number, type: WIRETYPE_VARINT, output);
412 WriteInt32NoTag(value, output);
413}
414void WireFormatLite::WriteInt64(int field_number, int64_t value,
415 io::CodedOutputStream* output) {
416 WriteTag(field_number, type: WIRETYPE_VARINT, output);
417 WriteInt64NoTag(value, output);
418}
419void WireFormatLite::WriteUInt32(int field_number, uint32_t value,
420 io::CodedOutputStream* output) {
421 WriteTag(field_number, type: WIRETYPE_VARINT, output);
422 WriteUInt32NoTag(value, output);
423}
424void WireFormatLite::WriteUInt64(int field_number, uint64_t value,
425 io::CodedOutputStream* output) {
426 WriteTag(field_number, type: WIRETYPE_VARINT, output);
427 WriteUInt64NoTag(value, output);
428}
429void WireFormatLite::WriteSInt32(int field_number, int32_t value,
430 io::CodedOutputStream* output) {
431 WriteTag(field_number, type: WIRETYPE_VARINT, output);
432 WriteSInt32NoTag(value, output);
433}
434void WireFormatLite::WriteSInt64(int field_number, int64_t value,
435 io::CodedOutputStream* output) {
436 WriteTag(field_number, type: WIRETYPE_VARINT, output);
437 WriteSInt64NoTag(value, output);
438}
439void WireFormatLite::WriteFixed32(int field_number, uint32_t value,
440 io::CodedOutputStream* output) {
441 WriteTag(field_number, type: WIRETYPE_FIXED32, output);
442 WriteFixed32NoTag(value, output);
443}
444void WireFormatLite::WriteFixed64(int field_number, uint64_t value,
445 io::CodedOutputStream* output) {
446 WriteTag(field_number, type: WIRETYPE_FIXED64, output);
447 WriteFixed64NoTag(value, output);
448}
449void WireFormatLite::WriteSFixed32(int field_number, int32_t value,
450 io::CodedOutputStream* output) {
451 WriteTag(field_number, type: WIRETYPE_FIXED32, output);
452 WriteSFixed32NoTag(value, output);
453}
454void WireFormatLite::WriteSFixed64(int field_number, int64_t value,
455 io::CodedOutputStream* output) {
456 WriteTag(field_number, type: WIRETYPE_FIXED64, output);
457 WriteSFixed64NoTag(value, output);
458}
459void WireFormatLite::WriteFloat(int field_number, float value,
460 io::CodedOutputStream* output) {
461 WriteTag(field_number, type: WIRETYPE_FIXED32, output);
462 WriteFloatNoTag(value, output);
463}
464void WireFormatLite::WriteDouble(int field_number, double value,
465 io::CodedOutputStream* output) {
466 WriteTag(field_number, type: WIRETYPE_FIXED64, output);
467 WriteDoubleNoTag(value, output);
468}
469void WireFormatLite::WriteBool(int field_number, bool value,
470 io::CodedOutputStream* output) {
471 WriteTag(field_number, type: WIRETYPE_VARINT, output);
472 WriteBoolNoTag(value, output);
473}
474void WireFormatLite::WriteEnum(int field_number, int value,
475 io::CodedOutputStream* output) {
476 WriteTag(field_number, type: WIRETYPE_VARINT, output);
477 WriteEnumNoTag(value, output);
478}
479
480constexpr size_t kInt32MaxSize = std::numeric_limits<int32_t>::max();
481
482void WireFormatLite::WriteString(int field_number, const std::string& value,
483 io::CodedOutputStream* output) {
484 // String is for UTF-8 text only
485 WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output);
486 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
487 output->WriteVarint32(value: value.size());
488 output->WriteString(str: value);
489}
490void WireFormatLite::WriteStringMaybeAliased(int field_number,
491 const std::string& value,
492 io::CodedOutputStream* output) {
493 // String is for UTF-8 text only
494 WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output);
495 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
496 output->WriteVarint32(value: value.size());
497 output->WriteRawMaybeAliased(data: value.data(), size: value.size());
498}
499void WireFormatLite::WriteBytes(int field_number, const std::string& value,
500 io::CodedOutputStream* output) {
501 WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output);
502 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
503 output->WriteVarint32(value: value.size());
504 output->WriteString(str: value);
505}
506void WireFormatLite::WriteBytesMaybeAliased(int field_number,
507 const std::string& value,
508 io::CodedOutputStream* output) {
509 WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output);
510 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
511 output->WriteVarint32(value: value.size());
512 output->WriteRawMaybeAliased(data: value.data(), size: value.size());
513}
514
515
516void WireFormatLite::WriteGroup(int field_number, const MessageLite& value,
517 io::CodedOutputStream* output) {
518 WriteTag(field_number, type: WIRETYPE_START_GROUP, output);
519 value.SerializeWithCachedSizes(output);
520 WriteTag(field_number, type: WIRETYPE_END_GROUP, output);
521}
522
523void WireFormatLite::WriteMessage(int field_number, const MessageLite& value,
524 io::CodedOutputStream* output) {
525 WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output);
526 const int size = value.GetCachedSize();
527 output->WriteVarint32(value: size);
528 value.SerializeWithCachedSizes(output);
529}
530
531uint8_t* WireFormatLite::InternalWriteGroup(int field_number,
532 const MessageLite& value,
533 uint8_t* target,
534 io::EpsCopyOutputStream* stream) {
535 target = stream->EnsureSpace(ptr: target);
536 target = WriteTagToArray(field_number, type: WIRETYPE_START_GROUP, target);
537 target = value._InternalSerialize(ptr: target, stream);
538 target = stream->EnsureSpace(ptr: target);
539 return WriteTagToArray(field_number, type: WIRETYPE_END_GROUP, target);
540}
541
542uint8_t* WireFormatLite::InternalWriteMessage(int field_number,
543 const MessageLite& value,
544 int cached_size, uint8_t* target,
545 io::EpsCopyOutputStream* stream) {
546 target = stream->EnsureSpace(ptr: target);
547 target = WriteTagToArray(field_number, type: WIRETYPE_LENGTH_DELIMITED, target);
548 target = io::CodedOutputStream::WriteVarint32ToArray(
549 value: static_cast<uint32_t>(cached_size), target);
550 return value._InternalSerialize(ptr: target, stream);
551}
552
553void WireFormatLite::WriteSubMessageMaybeToArray(
554 int /*size*/, const MessageLite& value, io::CodedOutputStream* output) {
555 output->SetCur(value._InternalSerialize(ptr: output->Cur(), stream: output->EpsCopy()));
556}
557
558void WireFormatLite::WriteGroupMaybeToArray(int field_number,
559 const MessageLite& value,
560 io::CodedOutputStream* output) {
561 WriteTag(field_number, type: WIRETYPE_START_GROUP, output);
562 const int size = value.GetCachedSize();
563 WriteSubMessageMaybeToArray(size, value, output);
564 WriteTag(field_number, type: WIRETYPE_END_GROUP, output);
565}
566
567void WireFormatLite::WriteMessageMaybeToArray(int field_number,
568 const MessageLite& value,
569 io::CodedOutputStream* output) {
570 WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output);
571 const int size = value.GetCachedSize();
572 output->WriteVarint32(value: size);
573 WriteSubMessageMaybeToArray(size, value, output);
574}
575
576PROTOBUF_NDEBUG_INLINE static bool ReadBytesToString(
577 io::CodedInputStream* input, std::string* value);
578inline static bool ReadBytesToString(io::CodedInputStream* input,
579 std::string* value) {
580 uint32_t length;
581 return input->ReadVarint32(value: &length) && input->ReadString(buffer: value, size: length);
582}
583
584bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
585 std::string* value) {
586 return ReadBytesToString(input, value);
587}
588
589bool WireFormatLite::ReadBytes(io::CodedInputStream* input, std::string** p) {
590 if (*p == &GetEmptyStringAlreadyInited()) {
591 *p = new std::string();
592 }
593 return ReadBytesToString(input, value: *p);
594}
595
596void PrintUTF8ErrorLog(StringPiece message_name,
597 StringPiece field_name, const char* operation_str,
598 bool emit_stacktrace) {
599 std::string stacktrace;
600 (void)emit_stacktrace; // Parameter is used by Google-internal code.
601 std::string quoted_field_name = "";
602 if (!field_name.empty()) {
603 if (!message_name.empty()) {
604 quoted_field_name =
605 StrCat(a: " '", b: message_name, c: ".", d: field_name, e: "'");
606 } else {
607 quoted_field_name = StrCat(a: " '", b: field_name, c: "'");
608 }
609 }
610 std::string error_message =
611 StrCat(a: "String field", b: quoted_field_name,
612 c: " contains invalid UTF-8 data "
613 "when ",
614 d: operation_str,
615 e: " a protocol buffer. Use the 'bytes' type if you intend to "
616 "send raw bytes. ",
617 f: stacktrace);
618 GOOGLE_LOG(ERROR) << error_message;
619}
620
621bool WireFormatLite::VerifyUtf8String(const char* data, int size, Operation op,
622 const char* field_name) {
623 if (!IsStructurallyValidUTF8(buf: data, len: size)) {
624 const char* operation_str = nullptr;
625 switch (op) {
626 case PARSE:
627 operation_str = "parsing";
628 break;
629 case SERIALIZE:
630 operation_str = "serializing";
631 break;
632 // no default case: have the compiler warn if a case is not covered.
633 }
634 PrintUTF8ErrorLog(message_name: "", field_name, operation_str, emit_stacktrace: false);
635 return false;
636 }
637 return true;
638}
639
640// this code is deliberately written such that clang makes it into really
641// efficient SSE code.
642template <bool ZigZag, bool SignExtended, typename T>
643static size_t VarintSize(const T* data, const int n) {
644 static_assert(sizeof(T) == 4, "This routine only works for 32 bit integers");
645 // is_unsigned<T> => !ZigZag
646 static_assert(
647 (std::is_unsigned<T>::value ^ ZigZag) || std::is_signed<T>::value,
648 "Cannot ZigZag encode unsigned types");
649 // is_unsigned<T> => !SignExtended
650 static_assert(
651 (std::is_unsigned<T>::value ^ SignExtended) || std::is_signed<T>::value,
652 "Cannot SignExtended unsigned types");
653 static_assert(!(SignExtended && ZigZag),
654 "Cannot SignExtended and ZigZag on the same type");
655 uint32_t sum = n;
656 uint32_t msb_sum = 0;
657 for (int i = 0; i < n; i++) {
658 uint32_t x = data[i];
659 if (ZigZag) {
660 x = WireFormatLite::ZigZagEncode32(n: x);
661 } else if (SignExtended) {
662 msb_sum += x >> 31;
663 }
664 // clang is so smart that it produces optimal SSE sequence unrolling
665 // the loop 8 ints at a time. With a sequence of 4
666 // cmpres = cmpgt x, sizeclass ( -1 or 0)
667 // sum = sum - cmpres
668 if (x > 0x7F) sum++;
669 if (x > 0x3FFF) sum++;
670 if (x > 0x1FFFFF) sum++;
671 if (x > 0xFFFFFFF) sum++;
672 }
673 if (SignExtended) sum += msb_sum * 5;
674 return sum;
675}
676
677template <bool ZigZag, typename T>
678static size_t VarintSize64(const T* data, const int n) {
679 static_assert(sizeof(T) == 8, "This routine only works for 64 bit integers");
680 // is_unsigned<T> => !ZigZag
681 static_assert(!ZigZag || !std::is_unsigned<T>::value,
682 "Cannot ZigZag encode unsigned types");
683 uint64_t sum = n;
684 for (int i = 0; i < n; i++) {
685 uint64_t x = data[i];
686 if (ZigZag) {
687 x = WireFormatLite::ZigZagEncode64(n: x);
688 }
689 // First step is a binary search, we can't branch in sse so we use the
690 // result of the compare to adjust sum and appropriately. This code is
691 // written to make clang recognize the vectorization.
692 uint64_t tmp = x >= (static_cast<uint64_t>(1) << 35) ? -1 : 0;
693 sum += 5 & tmp;
694 x >>= 35 & tmp;
695 if (x > 0x7F) sum++;
696 if (x > 0x3FFF) sum++;
697 if (x > 0x1FFFFF) sum++;
698 if (x > 0xFFFFFFF) sum++;
699 }
700 return sum;
701}
702
703// GCC does not recognize the vectorization opportunity
704// and other platforms are untested, in those cases using the optimized
705// varint size routine for each element is faster.
706// Hence we enable it only for clang
707#if defined(__SSE__) && defined(__clang__)
708size_t WireFormatLite::Int32Size(const RepeatedField<int32_t>& value) {
709 return VarintSize<false, true>(value.data(), value.size());
710}
711
712size_t WireFormatLite::UInt32Size(const RepeatedField<uint32_t>& value) {
713 return VarintSize<false, false>(value.data(), value.size());
714}
715
716size_t WireFormatLite::SInt32Size(const RepeatedField<int32_t>& value) {
717 return VarintSize<true, false>(value.data(), value.size());
718}
719
720size_t WireFormatLite::EnumSize(const RepeatedField<int>& value) {
721 // On ILP64, sizeof(int) == 8, which would require a different template.
722 return VarintSize<false, true>(value.data(), value.size());
723}
724
725#else // !(defined(__SSE4_1__) && defined(__clang__))
726
727size_t WireFormatLite::Int32Size(const RepeatedField<int32_t>& value) {
728 size_t out = 0;
729 const int n = value.size();
730 for (int i = 0; i < n; i++) {
731 out += Int32Size(value: value.Get(index: i));
732 }
733 return out;
734}
735
736size_t WireFormatLite::UInt32Size(const RepeatedField<uint32_t>& value) {
737 size_t out = 0;
738 const int n = value.size();
739 for (int i = 0; i < n; i++) {
740 out += UInt32Size(value: value.Get(index: i));
741 }
742 return out;
743}
744
745size_t WireFormatLite::SInt32Size(const RepeatedField<int32_t>& value) {
746 size_t out = 0;
747 const int n = value.size();
748 for (int i = 0; i < n; i++) {
749 out += SInt32Size(value: value.Get(index: i));
750 }
751 return out;
752}
753
754size_t WireFormatLite::EnumSize(const RepeatedField<int>& value) {
755 size_t out = 0;
756 const int n = value.size();
757 for (int i = 0; i < n; i++) {
758 out += EnumSize(value: value.Get(index: i));
759 }
760 return out;
761}
762
763#endif
764
765// Micro benchmarks show that the SSE improved loop only starts beating
766// the normal loop on Haswell platforms and then only for >32 ints. We
767// disable this for now. Some specialized users might find it worthwhile to
768// enable this.
769#define USE_SSE_FOR_64_BIT_INTEGER_ARRAYS 0
770#if USE_SSE_FOR_64_BIT_INTEGER_ARRAYS
771size_t WireFormatLite::Int64Size(const RepeatedField<int64_t>& value) {
772 return VarintSize64<false>(value.data(), value.size());
773}
774
775size_t WireFormatLite::UInt64Size(const RepeatedField<uint64_t>& value) {
776 return VarintSize64<false>(value.data(), value.size());
777}
778
779size_t WireFormatLite::SInt64Size(const RepeatedField<int64_t>& value) {
780 return VarintSize64<true>(value.data(), value.size());
781}
782
783#else
784
785size_t WireFormatLite::Int64Size(const RepeatedField<int64_t>& value) {
786 size_t out = 0;
787 const int n = value.size();
788 for (int i = 0; i < n; i++) {
789 out += Int64Size(value: value.Get(index: i));
790 }
791 return out;
792}
793
794size_t WireFormatLite::UInt64Size(const RepeatedField<uint64_t>& value) {
795 size_t out = 0;
796 const int n = value.size();
797 for (int i = 0; i < n; i++) {
798 out += UInt64Size(value: value.Get(index: i));
799 }
800 return out;
801}
802
803size_t WireFormatLite::SInt64Size(const RepeatedField<int64_t>& value) {
804 size_t out = 0;
805 const int n = value.size();
806 for (int i = 0; i < n; i++) {
807 out += SInt64Size(value: value.Get(index: i));
808 }
809 return out;
810}
811
812#endif
813
814} // namespace internal
815} // namespace protobuf
816} // namespace google
817
818#include <google/protobuf/port_undef.inc>
819