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