xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/wire_format_lite.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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