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: [email protected] (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
53 namespace google {
54 namespace protobuf {
55 namespace 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.
60 const int WireFormatLite::kMessageSetItemStartTag;
61 const int WireFormatLite::kMessageSetItemEndTag;
62 const int WireFormatLite::kMessageSetTypeIdTag;
63 const int WireFormatLite::kMessageSetMessageTag;
64
65 #endif
66
67 // IBM xlC requires prefixing constants with WireFormatLite::
68 const 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
78 const 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
102 const 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
SkipField(io::CodedInputStream * input,uint32_t tag)125 bool 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)) return false;
132 return true;
133 }
134 case WireFormatLite::WIRETYPE_FIXED64: {
135 uint64_t value;
136 if (!input->ReadLittleEndian64(&value)) return false;
137 return true;
138 }
139 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
140 uint32_t length;
141 if (!input->ReadVarint32(&length)) return false;
142 if (!input->Skip(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 WireFormatLite::MakeTag(WireFormatLite::GetTagFieldNumber(tag),
152 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)) return false;
163 return true;
164 }
165 default: {
166 return false;
167 }
168 }
169 }
170
SkipField(io::CodedInputStream * input,uint32_t tag,io::CodedOutputStream * output)171 bool 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)) return false;
179 output->WriteVarint32(tag);
180 output->WriteVarint64(value);
181 return true;
182 }
183 case WireFormatLite::WIRETYPE_FIXED64: {
184 uint64_t value;
185 if (!input->ReadLittleEndian64(&value)) return false;
186 output->WriteVarint32(tag);
187 output->WriteLittleEndian64(value);
188 return true;
189 }
190 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
191 uint32_t length;
192 if (!input->ReadVarint32(&length)) return false;
193 output->WriteVarint32(tag);
194 output->WriteVarint32(length);
195 // TODO(mkilavuz): Provide API to prevent extra string copying.
196 std::string temp;
197 if (!input->ReadString(&temp, length)) return false;
198 output->WriteString(temp);
199 return true;
200 }
201 case WireFormatLite::WIRETYPE_START_GROUP: {
202 output->WriteVarint32(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 WireFormatLite::MakeTag(WireFormatLite::GetTagFieldNumber(tag),
209 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)) return false;
220 output->WriteVarint32(tag);
221 output->WriteLittleEndian32(value);
222 return true;
223 }
224 default: {
225 return false;
226 }
227 }
228 }
229
SkipMessage(io::CodedInputStream * input)230 bool 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
SkipMessage(io::CodedInputStream * input,io::CodedOutputStream * output)249 bool 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(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
SkipField(io::CodedInputStream * input,uint32_t tag)270 bool FieldSkipper::SkipField(io::CodedInputStream* input, uint32_t tag) {
271 return WireFormatLite::SkipField(input, tag);
272 }
273
SkipMessage(io::CodedInputStream * input)274 bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
275 return WireFormatLite::SkipMessage(input);
276 }
277
SkipUnknownEnum(int,int)278 void FieldSkipper::SkipUnknownEnum(int /* field_number */, int /* value */) {
279 // Nothing.
280 }
281
SkipField(io::CodedInputStream * input,uint32_t tag)282 bool CodedOutputStreamFieldSkipper::SkipField(io::CodedInputStream* input,
283 uint32_t tag) {
284 return WireFormatLite::SkipField(input, tag, unknown_fields_);
285 }
286
SkipMessage(io::CodedInputStream * input)287 bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) {
288 return WireFormatLite::SkipMessage(input, unknown_fields_);
289 }
290
SkipUnknownEnum(int field_number,int value)291 void CodedOutputStreamFieldSkipper::SkipUnknownEnum(int field_number,
292 int value) {
293 unknown_fields_->WriteVarint32(field_number);
294 unknown_fields_->WriteVarint64(value);
295 }
296
ReadPackedEnumPreserveUnknowns(io::CodedInputStream * input,int field_number,bool (* is_valid)(int),io::CodedOutputStream * unknown_fields_stream,RepeatedField<int> * values)297 bool 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(&length)) return false;
302 io::CodedInputStream::Limit limit = input->PushLimit(length);
303 while (input->BytesUntilLimit() > 0) {
304 int value;
305 if (!ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(input, &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 WireFormatLite::WIRETYPE_VARINT);
313 unknown_fields_stream->WriteVarint32(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
323 namespace {
EncodeFixedSizeValue(float v,uint8_t * dest)324 void EncodeFixedSizeValue(float v, uint8_t* dest) {
325 WireFormatLite::WriteFloatNoTagToArray(v, dest);
326 }
327
EncodeFixedSizeValue(double v,uint8_t * dest)328 void EncodeFixedSizeValue(double v, uint8_t* dest) {
329 WireFormatLite::WriteDoubleNoTagToArray(v, dest);
330 }
331
EncodeFixedSizeValue(uint32_t v,uint8_t * dest)332 void EncodeFixedSizeValue(uint32_t v, uint8_t* dest) {
333 WireFormatLite::WriteFixed32NoTagToArray(v, dest);
334 }
335
EncodeFixedSizeValue(uint64_t v,uint8_t * dest)336 void EncodeFixedSizeValue(uint64_t v, uint8_t* dest) {
337 WireFormatLite::WriteFixed64NoTagToArray(v, dest);
338 }
339
EncodeFixedSizeValue(int32_t v,uint8_t * dest)340 void EncodeFixedSizeValue(int32_t v, uint8_t* dest) {
341 WireFormatLite::WriteSFixed32NoTagToArray(v, dest);
342 }
343
EncodeFixedSizeValue(int64_t v,uint8_t * dest)344 void EncodeFixedSizeValue(int64_t v, uint8_t* dest) {
345 WireFormatLite::WriteSFixed64NoTagToArray(v, dest);
346 }
347
EncodeFixedSizeValue(bool v,uint8_t * dest)348 void EncodeFixedSizeValue(bool v, uint8_t* dest) {
349 WireFormatLite::WriteBoolNoTagToArray(v, dest);
350 }
351 } // anonymous namespace
352
353 #endif // !defined(PROTOBUF_LITTLE_ENDIAN)
354
355 template <typename CType>
WriteArray(const CType * a,int n,io::CodedOutputStream * output)356 static void WriteArray(const CType* a, int n, io::CodedOutputStream* output) {
357 #if defined(PROTOBUF_LITTLE_ENDIAN)
358 output->WriteRaw(reinterpret_cast<const char*>(a), 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
WriteFloatArray(const float * a,int n,io::CodedOutputStream * output)374 void WireFormatLite::WriteFloatArray(const float* a, int n,
375 io::CodedOutputStream* output) {
376 WriteArray<float>(a, n, output);
377 }
378
WriteDoubleArray(const double * a,int n,io::CodedOutputStream * output)379 void WireFormatLite::WriteDoubleArray(const double* a, int n,
380 io::CodedOutputStream* output) {
381 WriteArray<double>(a, n, output);
382 }
383
WriteFixed32Array(const uint32_t * a,int n,io::CodedOutputStream * output)384 void WireFormatLite::WriteFixed32Array(const uint32_t* a, int n,
385 io::CodedOutputStream* output) {
386 WriteArray<uint32_t>(a, n, output);
387 }
388
WriteFixed64Array(const uint64_t * a,int n,io::CodedOutputStream * output)389 void WireFormatLite::WriteFixed64Array(const uint64_t* a, int n,
390 io::CodedOutputStream* output) {
391 WriteArray<uint64_t>(a, n, output);
392 }
393
WriteSFixed32Array(const int32_t * a,int n,io::CodedOutputStream * output)394 void WireFormatLite::WriteSFixed32Array(const int32_t* a, int n,
395 io::CodedOutputStream* output) {
396 WriteArray<int32_t>(a, n, output);
397 }
398
WriteSFixed64Array(const int64_t * a,int n,io::CodedOutputStream * output)399 void WireFormatLite::WriteSFixed64Array(const int64_t* a, int n,
400 io::CodedOutputStream* output) {
401 WriteArray<int64_t>(a, n, output);
402 }
403
WriteBoolArray(const bool * a,int n,io::CodedOutputStream * output)404 void WireFormatLite::WriteBoolArray(const bool* a, int n,
405 io::CodedOutputStream* output) {
406 WriteArray<bool>(a, n, output);
407 }
408
WriteInt32(int field_number,int32_t value,io::CodedOutputStream * output)409 void WireFormatLite::WriteInt32(int field_number, int32_t value,
410 io::CodedOutputStream* output) {
411 WriteTag(field_number, WIRETYPE_VARINT, output);
412 WriteInt32NoTag(value, output);
413 }
WriteInt64(int field_number,int64_t value,io::CodedOutputStream * output)414 void WireFormatLite::WriteInt64(int field_number, int64_t value,
415 io::CodedOutputStream* output) {
416 WriteTag(field_number, WIRETYPE_VARINT, output);
417 WriteInt64NoTag(value, output);
418 }
WriteUInt32(int field_number,uint32_t value,io::CodedOutputStream * output)419 void WireFormatLite::WriteUInt32(int field_number, uint32_t value,
420 io::CodedOutputStream* output) {
421 WriteTag(field_number, WIRETYPE_VARINT, output);
422 WriteUInt32NoTag(value, output);
423 }
WriteUInt64(int field_number,uint64_t value,io::CodedOutputStream * output)424 void WireFormatLite::WriteUInt64(int field_number, uint64_t value,
425 io::CodedOutputStream* output) {
426 WriteTag(field_number, WIRETYPE_VARINT, output);
427 WriteUInt64NoTag(value, output);
428 }
WriteSInt32(int field_number,int32_t value,io::CodedOutputStream * output)429 void WireFormatLite::WriteSInt32(int field_number, int32_t value,
430 io::CodedOutputStream* output) {
431 WriteTag(field_number, WIRETYPE_VARINT, output);
432 WriteSInt32NoTag(value, output);
433 }
WriteSInt64(int field_number,int64_t value,io::CodedOutputStream * output)434 void WireFormatLite::WriteSInt64(int field_number, int64_t value,
435 io::CodedOutputStream* output) {
436 WriteTag(field_number, WIRETYPE_VARINT, output);
437 WriteSInt64NoTag(value, output);
438 }
WriteFixed32(int field_number,uint32_t value,io::CodedOutputStream * output)439 void WireFormatLite::WriteFixed32(int field_number, uint32_t value,
440 io::CodedOutputStream* output) {
441 WriteTag(field_number, WIRETYPE_FIXED32, output);
442 WriteFixed32NoTag(value, output);
443 }
WriteFixed64(int field_number,uint64_t value,io::CodedOutputStream * output)444 void WireFormatLite::WriteFixed64(int field_number, uint64_t value,
445 io::CodedOutputStream* output) {
446 WriteTag(field_number, WIRETYPE_FIXED64, output);
447 WriteFixed64NoTag(value, output);
448 }
WriteSFixed32(int field_number,int32_t value,io::CodedOutputStream * output)449 void WireFormatLite::WriteSFixed32(int field_number, int32_t value,
450 io::CodedOutputStream* output) {
451 WriteTag(field_number, WIRETYPE_FIXED32, output);
452 WriteSFixed32NoTag(value, output);
453 }
WriteSFixed64(int field_number,int64_t value,io::CodedOutputStream * output)454 void WireFormatLite::WriteSFixed64(int field_number, int64_t value,
455 io::CodedOutputStream* output) {
456 WriteTag(field_number, WIRETYPE_FIXED64, output);
457 WriteSFixed64NoTag(value, output);
458 }
WriteFloat(int field_number,float value,io::CodedOutputStream * output)459 void WireFormatLite::WriteFloat(int field_number, float value,
460 io::CodedOutputStream* output) {
461 WriteTag(field_number, WIRETYPE_FIXED32, output);
462 WriteFloatNoTag(value, output);
463 }
WriteDouble(int field_number,double value,io::CodedOutputStream * output)464 void WireFormatLite::WriteDouble(int field_number, double value,
465 io::CodedOutputStream* output) {
466 WriteTag(field_number, WIRETYPE_FIXED64, output);
467 WriteDoubleNoTag(value, output);
468 }
WriteBool(int field_number,bool value,io::CodedOutputStream * output)469 void WireFormatLite::WriteBool(int field_number, bool value,
470 io::CodedOutputStream* output) {
471 WriteTag(field_number, WIRETYPE_VARINT, output);
472 WriteBoolNoTag(value, output);
473 }
WriteEnum(int field_number,int value,io::CodedOutputStream * output)474 void WireFormatLite::WriteEnum(int field_number, int value,
475 io::CodedOutputStream* output) {
476 WriteTag(field_number, WIRETYPE_VARINT, output);
477 WriteEnumNoTag(value, output);
478 }
479
480 constexpr size_t kInt32MaxSize = std::numeric_limits<int32_t>::max();
481
WriteString(int field_number,const std::string & value,io::CodedOutputStream * output)482 void 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, WIRETYPE_LENGTH_DELIMITED, output);
486 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
487 output->WriteVarint32(value.size());
488 output->WriteString(value);
489 }
WriteStringMaybeAliased(int field_number,const std::string & value,io::CodedOutputStream * output)490 void 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, WIRETYPE_LENGTH_DELIMITED, output);
495 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
496 output->WriteVarint32(value.size());
497 output->WriteRawMaybeAliased(value.data(), value.size());
498 }
WriteBytes(int field_number,const std::string & value,io::CodedOutputStream * output)499 void WireFormatLite::WriteBytes(int field_number, const std::string& value,
500 io::CodedOutputStream* output) {
501 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
502 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
503 output->WriteVarint32(value.size());
504 output->WriteString(value);
505 }
WriteBytesMaybeAliased(int field_number,const std::string & value,io::CodedOutputStream * output)506 void WireFormatLite::WriteBytesMaybeAliased(int field_number,
507 const std::string& value,
508 io::CodedOutputStream* output) {
509 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
510 GOOGLE_CHECK_LE(value.size(), kInt32MaxSize);
511 output->WriteVarint32(value.size());
512 output->WriteRawMaybeAliased(value.data(), value.size());
513 }
514
515
WriteGroup(int field_number,const MessageLite & value,io::CodedOutputStream * output)516 void WireFormatLite::WriteGroup(int field_number, const MessageLite& value,
517 io::CodedOutputStream* output) {
518 WriteTag(field_number, WIRETYPE_START_GROUP, output);
519 value.SerializeWithCachedSizes(output);
520 WriteTag(field_number, WIRETYPE_END_GROUP, output);
521 }
522
WriteMessage(int field_number,const MessageLite & value,io::CodedOutputStream * output)523 void WireFormatLite::WriteMessage(int field_number, const MessageLite& value,
524 io::CodedOutputStream* output) {
525 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
526 const int size = value.GetCachedSize();
527 output->WriteVarint32(size);
528 value.SerializeWithCachedSizes(output);
529 }
530
InternalWriteGroup(int field_number,const MessageLite & value,uint8_t * target,io::EpsCopyOutputStream * stream)531 uint8_t* WireFormatLite::InternalWriteGroup(int field_number,
532 const MessageLite& value,
533 uint8_t* target,
534 io::EpsCopyOutputStream* stream) {
535 target = stream->EnsureSpace(target);
536 target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
537 target = value._InternalSerialize(target, stream);
538 target = stream->EnsureSpace(target);
539 return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
540 }
541
InternalWriteMessage(int field_number,const MessageLite & value,int cached_size,uint8_t * target,io::EpsCopyOutputStream * stream)542 uint8_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(target);
547 target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
548 target = io::CodedOutputStream::WriteVarint32ToArray(
549 static_cast<uint32_t>(cached_size), target);
550 return value._InternalSerialize(target, stream);
551 }
552
WriteSubMessageMaybeToArray(int,const MessageLite & value,io::CodedOutputStream * output)553 void WireFormatLite::WriteSubMessageMaybeToArray(
554 int /*size*/, const MessageLite& value, io::CodedOutputStream* output) {
555 output->SetCur(value._InternalSerialize(output->Cur(), output->EpsCopy()));
556 }
557
WriteGroupMaybeToArray(int field_number,const MessageLite & value,io::CodedOutputStream * output)558 void WireFormatLite::WriteGroupMaybeToArray(int field_number,
559 const MessageLite& value,
560 io::CodedOutputStream* output) {
561 WriteTag(field_number, WIRETYPE_START_GROUP, output);
562 const int size = value.GetCachedSize();
563 WriteSubMessageMaybeToArray(size, value, output);
564 WriteTag(field_number, WIRETYPE_END_GROUP, output);
565 }
566
WriteMessageMaybeToArray(int field_number,const MessageLite & value,io::CodedOutputStream * output)567 void WireFormatLite::WriteMessageMaybeToArray(int field_number,
568 const MessageLite& value,
569 io::CodedOutputStream* output) {
570 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
571 const int size = value.GetCachedSize();
572 output->WriteVarint32(size);
573 WriteSubMessageMaybeToArray(size, value, output);
574 }
575
576 PROTOBUF_NDEBUG_INLINE static bool ReadBytesToString(
577 io::CodedInputStream* input, std::string* value);
ReadBytesToString(io::CodedInputStream * input,std::string * value)578 inline static bool ReadBytesToString(io::CodedInputStream* input,
579 std::string* value) {
580 uint32_t length;
581 return input->ReadVarint32(&length) && input->ReadString(value, length);
582 }
583
ReadBytes(io::CodedInputStream * input,std::string * value)584 bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
585 std::string* value) {
586 return ReadBytesToString(input, value);
587 }
588
ReadBytes(io::CodedInputStream * input,std::string ** p)589 bool WireFormatLite::ReadBytes(io::CodedInputStream* input, std::string** p) {
590 if (*p == &GetEmptyStringAlreadyInited()) {
591 *p = new std::string();
592 }
593 return ReadBytesToString(input, *p);
594 }
595
PrintUTF8ErrorLog(StringPiece message_name,StringPiece field_name,const char * operation_str,bool emit_stacktrace)596 void 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(" '", message_name, ".", field_name, "'");
606 } else {
607 quoted_field_name = StrCat(" '", field_name, "'");
608 }
609 }
610 std::string error_message =
611 StrCat("String field", quoted_field_name,
612 " contains invalid UTF-8 data "
613 "when ",
614 operation_str,
615 " a protocol buffer. Use the 'bytes' type if you intend to "
616 "send raw bytes. ",
617 stacktrace);
618 GOOGLE_LOG(ERROR) << error_message;
619 }
620
VerifyUtf8String(const char * data,int size,Operation op,const char * field_name)621 bool WireFormatLite::VerifyUtf8String(const char* data, int size, Operation op,
622 const char* field_name) {
623 if (!IsStructurallyValidUTF8(data, 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("", field_name, operation_str, 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.
642 template <bool ZigZag, bool SignExtended, typename T>
VarintSize(const T * data,const int n)643 static 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(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
677 template <bool ZigZag, typename T>
VarintSize64(const T * data,const int n)678 static 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(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__)
Int32Size(const RepeatedField<int32_t> & value)708 size_t WireFormatLite::Int32Size(const RepeatedField<int32_t>& value) {
709 return VarintSize<false, true>(value.data(), value.size());
710 }
711
UInt32Size(const RepeatedField<uint32_t> & value)712 size_t WireFormatLite::UInt32Size(const RepeatedField<uint32_t>& value) {
713 return VarintSize<false, false>(value.data(), value.size());
714 }
715
SInt32Size(const RepeatedField<int32_t> & value)716 size_t WireFormatLite::SInt32Size(const RepeatedField<int32_t>& value) {
717 return VarintSize<true, false>(value.data(), value.size());
718 }
719
EnumSize(const RepeatedField<int> & value)720 size_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
Int32Size(const RepeatedField<int32_t> & value)727 size_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.Get(i));
732 }
733 return out;
734 }
735
UInt32Size(const RepeatedField<uint32_t> & value)736 size_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.Get(i));
741 }
742 return out;
743 }
744
SInt32Size(const RepeatedField<int32_t> & value)745 size_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.Get(i));
750 }
751 return out;
752 }
753
EnumSize(const RepeatedField<int> & value)754 size_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.Get(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
Int64Size(const RepeatedField<int64_t> & value)771 size_t WireFormatLite::Int64Size(const RepeatedField<int64_t>& value) {
772 return VarintSize64<false>(value.data(), value.size());
773 }
774
UInt64Size(const RepeatedField<uint64_t> & value)775 size_t WireFormatLite::UInt64Size(const RepeatedField<uint64_t>& value) {
776 return VarintSize64<false>(value.data(), value.size());
777 }
778
SInt64Size(const RepeatedField<int64_t> & value)779 size_t WireFormatLite::SInt64Size(const RepeatedField<int64_t>& value) {
780 return VarintSize64<true>(value.data(), value.size());
781 }
782
783 #else
784
Int64Size(const RepeatedField<int64_t> & value)785 size_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.Get(i));
790 }
791 return out;
792 }
793
UInt64Size(const RepeatedField<uint64_t> & value)794 size_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.Get(i));
799 }
800 return out;
801 }
802
SInt64Size(const RepeatedField<int64_t> & value)803 size_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.Get(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