1 | // Protocol Buffers - Google's data interchange format |
2 | // Copyright 2008 Google Inc. All rights reserved. |
3 | // https://developers.google.com/protocol-buffers/ |
4 | // |
5 | // Redistribution and use in source and binary forms, with or without |
6 | // modification, are permitted provided that the following conditions are |
7 | // met: |
8 | // |
9 | // * Redistributions of source code must retain the above copyright |
10 | // notice, this list of conditions and the following disclaimer. |
11 | // * Redistributions in binary form must reproduce the above |
12 | // copyright notice, this list of conditions and the following disclaimer |
13 | // in the documentation and/or other materials provided with the |
14 | // distribution. |
15 | // * Neither the name of Google Inc. nor the names of its |
16 | // contributors may be used to endorse or promote products derived from |
17 | // this software without specific prior written permission. |
18 | // |
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | |
31 | // Author: kenton@google.com (Kenton Varda) |
32 | // Based on original Protocol Buffers design by |
33 | // Sanjay Ghemawat, Jeff Dean, and others. |
34 | |
35 | #include <google/protobuf/wire_format_lite.h> |
36 | |
37 | #include <limits> |
38 | #include <stack> |
39 | #include <string> |
40 | #include <vector> |
41 | |
42 | #include <google/protobuf/stubs/logging.h> |
43 | #include <google/protobuf/stubs/common.h> |
44 | #include <google/protobuf/io/coded_stream.h> |
45 | #include <google/protobuf/io/zero_copy_stream.h> |
46 | #include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
47 | #include <google/protobuf/stubs/stringprintf.h> |
48 | |
49 | |
50 | // Must be included last. |
51 | #include <google/protobuf/port_def.inc> |
52 | |
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 | |
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: &value)) return false; |
132 | return true; |
133 | } |
134 | case WireFormatLite::WIRETYPE_FIXED64: { |
135 | uint64_t value; |
136 | if (!input->ReadLittleEndian64(value: &value)) return false; |
137 | return true; |
138 | } |
139 | case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { |
140 | uint32_t length; |
141 | if (!input->ReadVarint32(value: &length)) return false; |
142 | if (!input->Skip(count: length)) return false; |
143 | return true; |
144 | } |
145 | case WireFormatLite::WIRETYPE_START_GROUP: { |
146 | if (!input->IncrementRecursionDepth()) return false; |
147 | if (!SkipMessage(input)) return false; |
148 | input->DecrementRecursionDepth(); |
149 | // Check that the ending tag matched the starting tag. |
150 | if (!input->LastTagWas( |
151 | expected: WireFormatLite::MakeTag(field_number: WireFormatLite::GetTagFieldNumber(tag), |
152 | type: WireFormatLite::WIRETYPE_END_GROUP))) { |
153 | return false; |
154 | } |
155 | return true; |
156 | } |
157 | case WireFormatLite::WIRETYPE_END_GROUP: { |
158 | return false; |
159 | } |
160 | case WireFormatLite::WIRETYPE_FIXED32: { |
161 | uint32_t value; |
162 | if (!input->ReadLittleEndian32(value: &value)) return false; |
163 | return true; |
164 | } |
165 | default: { |
166 | return false; |
167 | } |
168 | } |
169 | } |
170 | |
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: &value)) return false; |
179 | output->WriteVarint32(value: tag); |
180 | output->WriteVarint64(value); |
181 | return true; |
182 | } |
183 | case WireFormatLite::WIRETYPE_FIXED64: { |
184 | uint64_t value; |
185 | if (!input->ReadLittleEndian64(value: &value)) return false; |
186 | output->WriteVarint32(value: tag); |
187 | output->WriteLittleEndian64(value); |
188 | return true; |
189 | } |
190 | case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { |
191 | uint32_t length; |
192 | if (!input->ReadVarint32(value: &length)) return false; |
193 | output->WriteVarint32(value: tag); |
194 | output->WriteVarint32(value: length); |
195 | // TODO(mkilavuz): Provide API to prevent extra string copying. |
196 | std::string temp; |
197 | if (!input->ReadString(buffer: &temp, size: length)) return false; |
198 | output->WriteString(str: temp); |
199 | return true; |
200 | } |
201 | case WireFormatLite::WIRETYPE_START_GROUP: { |
202 | output->WriteVarint32(value: tag); |
203 | if (!input->IncrementRecursionDepth()) return false; |
204 | if (!SkipMessage(input, output)) return false; |
205 | input->DecrementRecursionDepth(); |
206 | // Check that the ending tag matched the starting tag. |
207 | if (!input->LastTagWas( |
208 | expected: WireFormatLite::MakeTag(field_number: WireFormatLite::GetTagFieldNumber(tag), |
209 | type: WireFormatLite::WIRETYPE_END_GROUP))) { |
210 | return false; |
211 | } |
212 | return true; |
213 | } |
214 | case WireFormatLite::WIRETYPE_END_GROUP: { |
215 | return false; |
216 | } |
217 | case WireFormatLite::WIRETYPE_FIXED32: { |
218 | uint32_t value; |
219 | if (!input->ReadLittleEndian32(value: &value)) return false; |
220 | output->WriteVarint32(value: tag); |
221 | output->WriteLittleEndian32(value); |
222 | return true; |
223 | } |
224 | default: { |
225 | return false; |
226 | } |
227 | } |
228 | } |
229 | |
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 | |
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(value: tag); |
262 | // Must be the end of the message. |
263 | return true; |
264 | } |
265 | |
266 | if (!SkipField(input, tag, output)) return false; |
267 | } |
268 | } |
269 | |
270 | bool FieldSkipper::SkipField(io::CodedInputStream* input, uint32_t tag) { |
271 | return WireFormatLite::SkipField(input, tag); |
272 | } |
273 | |
274 | bool FieldSkipper::SkipMessage(io::CodedInputStream* input) { |
275 | return WireFormatLite::SkipMessage(input); |
276 | } |
277 | |
278 | void FieldSkipper::SkipUnknownEnum(int /* field_number */, int /* value */) { |
279 | // Nothing. |
280 | } |
281 | |
282 | bool CodedOutputStreamFieldSkipper::SkipField(io::CodedInputStream* input, |
283 | uint32_t tag) { |
284 | return WireFormatLite::SkipField(input, tag, output: unknown_fields_); |
285 | } |
286 | |
287 | bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) { |
288 | return WireFormatLite::SkipMessage(input, output: unknown_fields_); |
289 | } |
290 | |
291 | void CodedOutputStreamFieldSkipper::SkipUnknownEnum(int field_number, |
292 | int value) { |
293 | unknown_fields_->WriteVarint32(value: field_number); |
294 | unknown_fields_->WriteVarint64(value); |
295 | } |
296 | |
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(value: &length)) return false; |
302 | io::CodedInputStream::Limit limit = input->PushLimit(byte_limit: length); |
303 | while (input->BytesUntilLimit() > 0) { |
304 | int value; |
305 | if (!ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(input, value: &value)) { |
306 | return false; |
307 | } |
308 | if (is_valid == nullptr || is_valid(value)) { |
309 | values->Add(value); |
310 | } else { |
311 | uint32_t tag = WireFormatLite::MakeTag(field_number, |
312 | type: WireFormatLite::WIRETYPE_VARINT); |
313 | unknown_fields_stream->WriteVarint32(value: tag); |
314 | unknown_fields_stream->WriteVarint32(value); |
315 | } |
316 | } |
317 | input->PopLimit(limit); |
318 | return true; |
319 | } |
320 | |
321 | #if !defined(PROTOBUF_LITTLE_ENDIAN) |
322 | |
323 | namespace { |
324 | void EncodeFixedSizeValue(float v, uint8_t* dest) { |
325 | WireFormatLite::WriteFloatNoTagToArray(v, dest); |
326 | } |
327 | |
328 | void EncodeFixedSizeValue(double v, uint8_t* dest) { |
329 | WireFormatLite::WriteDoubleNoTagToArray(v, dest); |
330 | } |
331 | |
332 | void EncodeFixedSizeValue(uint32_t v, uint8_t* dest) { |
333 | WireFormatLite::WriteFixed32NoTagToArray(v, dest); |
334 | } |
335 | |
336 | void EncodeFixedSizeValue(uint64_t v, uint8_t* dest) { |
337 | WireFormatLite::WriteFixed64NoTagToArray(v, dest); |
338 | } |
339 | |
340 | void EncodeFixedSizeValue(int32_t v, uint8_t* dest) { |
341 | WireFormatLite::WriteSFixed32NoTagToArray(v, dest); |
342 | } |
343 | |
344 | void EncodeFixedSizeValue(int64_t v, uint8_t* dest) { |
345 | WireFormatLite::WriteSFixed64NoTagToArray(v, dest); |
346 | } |
347 | |
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> |
356 | static void WriteArray(const CType* a, int n, io::CodedOutputStream* output) { |
357 | #if defined(PROTOBUF_LITTLE_ENDIAN) |
358 | output->WriteRaw(buffer: reinterpret_cast<const char*>(a), size: n * sizeof(a[0])); |
359 | #else |
360 | const int kAtATime = 128; |
361 | uint8_t buf[sizeof(CType) * kAtATime]; |
362 | for (int i = 0; i < n; i += kAtATime) { |
363 | int to_do = std::min(kAtATime, n - i); |
364 | uint8_t* ptr = buf; |
365 | for (int j = 0; j < to_do; j++) { |
366 | EncodeFixedSizeValue(a[i + j], ptr); |
367 | ptr += sizeof(a[0]); |
368 | } |
369 | output->WriteRaw(buf, to_do * sizeof(a[0])); |
370 | } |
371 | #endif |
372 | } |
373 | |
374 | void WireFormatLite::WriteFloatArray(const float* a, int n, |
375 | io::CodedOutputStream* output) { |
376 | WriteArray<float>(a, n, output); |
377 | } |
378 | |
379 | void WireFormatLite::WriteDoubleArray(const double* a, int n, |
380 | io::CodedOutputStream* output) { |
381 | WriteArray<double>(a, n, output); |
382 | } |
383 | |
384 | void WireFormatLite::WriteFixed32Array(const uint32_t* a, int n, |
385 | io::CodedOutputStream* output) { |
386 | WriteArray<uint32_t>(a, n, output); |
387 | } |
388 | |
389 | void WireFormatLite::WriteFixed64Array(const uint64_t* a, int n, |
390 | io::CodedOutputStream* output) { |
391 | WriteArray<uint64_t>(a, n, output); |
392 | } |
393 | |
394 | void WireFormatLite::WriteSFixed32Array(const int32_t* a, int n, |
395 | io::CodedOutputStream* output) { |
396 | WriteArray<int32_t>(a, n, output); |
397 | } |
398 | |
399 | void WireFormatLite::WriteSFixed64Array(const int64_t* a, int n, |
400 | io::CodedOutputStream* output) { |
401 | WriteArray<int64_t>(a, n, output); |
402 | } |
403 | |
404 | void WireFormatLite::WriteBoolArray(const bool* a, int n, |
405 | io::CodedOutputStream* output) { |
406 | WriteArray<bool>(a, n, output); |
407 | } |
408 | |
409 | void WireFormatLite::WriteInt32(int field_number, int32_t value, |
410 | io::CodedOutputStream* output) { |
411 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
412 | WriteInt32NoTag(value, output); |
413 | } |
414 | void WireFormatLite::WriteInt64(int field_number, int64_t value, |
415 | io::CodedOutputStream* output) { |
416 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
417 | WriteInt64NoTag(value, output); |
418 | } |
419 | void WireFormatLite::WriteUInt32(int field_number, uint32_t value, |
420 | io::CodedOutputStream* output) { |
421 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
422 | WriteUInt32NoTag(value, output); |
423 | } |
424 | void WireFormatLite::WriteUInt64(int field_number, uint64_t value, |
425 | io::CodedOutputStream* output) { |
426 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
427 | WriteUInt64NoTag(value, output); |
428 | } |
429 | void WireFormatLite::WriteSInt32(int field_number, int32_t value, |
430 | io::CodedOutputStream* output) { |
431 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
432 | WriteSInt32NoTag(value, output); |
433 | } |
434 | void WireFormatLite::WriteSInt64(int field_number, int64_t value, |
435 | io::CodedOutputStream* output) { |
436 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
437 | WriteSInt64NoTag(value, output); |
438 | } |
439 | void WireFormatLite::WriteFixed32(int field_number, uint32_t value, |
440 | io::CodedOutputStream* output) { |
441 | WriteTag(field_number, type: WIRETYPE_FIXED32, output); |
442 | WriteFixed32NoTag(value, output); |
443 | } |
444 | void WireFormatLite::WriteFixed64(int field_number, uint64_t value, |
445 | io::CodedOutputStream* output) { |
446 | WriteTag(field_number, type: WIRETYPE_FIXED64, output); |
447 | WriteFixed64NoTag(value, output); |
448 | } |
449 | void WireFormatLite::WriteSFixed32(int field_number, int32_t value, |
450 | io::CodedOutputStream* output) { |
451 | WriteTag(field_number, type: WIRETYPE_FIXED32, output); |
452 | WriteSFixed32NoTag(value, output); |
453 | } |
454 | void WireFormatLite::WriteSFixed64(int field_number, int64_t value, |
455 | io::CodedOutputStream* output) { |
456 | WriteTag(field_number, type: WIRETYPE_FIXED64, output); |
457 | WriteSFixed64NoTag(value, output); |
458 | } |
459 | void WireFormatLite::WriteFloat(int field_number, float value, |
460 | io::CodedOutputStream* output) { |
461 | WriteTag(field_number, type: WIRETYPE_FIXED32, output); |
462 | WriteFloatNoTag(value, output); |
463 | } |
464 | void WireFormatLite::WriteDouble(int field_number, double value, |
465 | io::CodedOutputStream* output) { |
466 | WriteTag(field_number, type: WIRETYPE_FIXED64, output); |
467 | WriteDoubleNoTag(value, output); |
468 | } |
469 | void WireFormatLite::WriteBool(int field_number, bool value, |
470 | io::CodedOutputStream* output) { |
471 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
472 | WriteBoolNoTag(value, output); |
473 | } |
474 | void WireFormatLite::WriteEnum(int field_number, int value, |
475 | io::CodedOutputStream* output) { |
476 | WriteTag(field_number, type: WIRETYPE_VARINT, output); |
477 | WriteEnumNoTag(value, output); |
478 | } |
479 | |
480 | constexpr size_t kInt32MaxSize = std::numeric_limits<int32_t>::max(); |
481 | |
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, type: WIRETYPE_LENGTH_DELIMITED, output); |
486 | GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); |
487 | output->WriteVarint32(value: value.size()); |
488 | output->WriteString(str: value); |
489 | } |
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, type: WIRETYPE_LENGTH_DELIMITED, output); |
495 | GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); |
496 | output->WriteVarint32(value: value.size()); |
497 | output->WriteRawMaybeAliased(data: value.data(), size: value.size()); |
498 | } |
499 | void WireFormatLite::WriteBytes(int field_number, const std::string& value, |
500 | io::CodedOutputStream* output) { |
501 | WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output); |
502 | GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); |
503 | output->WriteVarint32(value: value.size()); |
504 | output->WriteString(str: value); |
505 | } |
506 | void WireFormatLite::WriteBytesMaybeAliased(int field_number, |
507 | const std::string& value, |
508 | io::CodedOutputStream* output) { |
509 | WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output); |
510 | GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); |
511 | output->WriteVarint32(value: value.size()); |
512 | output->WriteRawMaybeAliased(data: value.data(), size: value.size()); |
513 | } |
514 | |
515 | |
516 | void WireFormatLite::WriteGroup(int field_number, const MessageLite& value, |
517 | io::CodedOutputStream* output) { |
518 | WriteTag(field_number, type: WIRETYPE_START_GROUP, output); |
519 | value.SerializeWithCachedSizes(output); |
520 | WriteTag(field_number, type: WIRETYPE_END_GROUP, output); |
521 | } |
522 | |
523 | void WireFormatLite::WriteMessage(int field_number, const MessageLite& value, |
524 | io::CodedOutputStream* output) { |
525 | WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output); |
526 | const int size = value.GetCachedSize(); |
527 | output->WriteVarint32(value: size); |
528 | value.SerializeWithCachedSizes(output); |
529 | } |
530 | |
531 | uint8_t* WireFormatLite::InternalWriteGroup(int field_number, |
532 | const MessageLite& value, |
533 | uint8_t* target, |
534 | io::EpsCopyOutputStream* stream) { |
535 | target = stream->EnsureSpace(ptr: target); |
536 | target = WriteTagToArray(field_number, type: WIRETYPE_START_GROUP, target); |
537 | target = value._InternalSerialize(ptr: target, stream); |
538 | target = stream->EnsureSpace(ptr: target); |
539 | return WriteTagToArray(field_number, type: WIRETYPE_END_GROUP, target); |
540 | } |
541 | |
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(ptr: target); |
547 | target = WriteTagToArray(field_number, type: WIRETYPE_LENGTH_DELIMITED, target); |
548 | target = io::CodedOutputStream::WriteVarint32ToArray( |
549 | value: static_cast<uint32_t>(cached_size), target); |
550 | return value._InternalSerialize(ptr: target, stream); |
551 | } |
552 | |
553 | void WireFormatLite::WriteSubMessageMaybeToArray( |
554 | int /*size*/, const MessageLite& value, io::CodedOutputStream* output) { |
555 | output->SetCur(value._InternalSerialize(ptr: output->Cur(), stream: output->EpsCopy())); |
556 | } |
557 | |
558 | void WireFormatLite::WriteGroupMaybeToArray(int field_number, |
559 | const MessageLite& value, |
560 | io::CodedOutputStream* output) { |
561 | WriteTag(field_number, type: WIRETYPE_START_GROUP, output); |
562 | const int size = value.GetCachedSize(); |
563 | WriteSubMessageMaybeToArray(size, value, output); |
564 | WriteTag(field_number, type: WIRETYPE_END_GROUP, output); |
565 | } |
566 | |
567 | void WireFormatLite::WriteMessageMaybeToArray(int field_number, |
568 | const MessageLite& value, |
569 | io::CodedOutputStream* output) { |
570 | WriteTag(field_number, type: WIRETYPE_LENGTH_DELIMITED, output); |
571 | const int size = value.GetCachedSize(); |
572 | output->WriteVarint32(value: size); |
573 | WriteSubMessageMaybeToArray(size, value, output); |
574 | } |
575 | |
576 | PROTOBUF_NDEBUG_INLINE static bool ReadBytesToString( |
577 | 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(value: &length) && input->ReadString(buffer: value, size: length); |
582 | } |
583 | |
584 | bool WireFormatLite::ReadBytes(io::CodedInputStream* input, |
585 | std::string* value) { |
586 | return ReadBytesToString(input, value); |
587 | } |
588 | |
589 | bool WireFormatLite::ReadBytes(io::CodedInputStream* input, std::string** p) { |
590 | if (*p == &GetEmptyStringAlreadyInited()) { |
591 | *p = new std::string(); |
592 | } |
593 | return ReadBytesToString(input, value: *p); |
594 | } |
595 | |
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(a: " '" , b: message_name, c: "." , d: field_name, e: "'" ); |
606 | } else { |
607 | quoted_field_name = StrCat(a: " '" , b: field_name, c: "'" ); |
608 | } |
609 | } |
610 | std::string error_message = |
611 | StrCat(a: "String field" , b: quoted_field_name, |
612 | c: " contains invalid UTF-8 data " |
613 | "when " , |
614 | d: operation_str, |
615 | e: " a protocol buffer. Use the 'bytes' type if you intend to " |
616 | "send raw bytes. " , |
617 | f: stacktrace); |
618 | GOOGLE_LOG(ERROR) << error_message; |
619 | } |
620 | |
621 | bool WireFormatLite::VerifyUtf8String(const char* data, int size, Operation op, |
622 | const char* field_name) { |
623 | if (!IsStructurallyValidUTF8(buf: data, len: size)) { |
624 | const char* operation_str = nullptr; |
625 | switch (op) { |
626 | case PARSE: |
627 | operation_str = "parsing" ; |
628 | break; |
629 | case SERIALIZE: |
630 | operation_str = "serializing" ; |
631 | break; |
632 | // no default case: have the compiler warn if a case is not covered. |
633 | } |
634 | PrintUTF8ErrorLog(message_name: "" , field_name, operation_str, emit_stacktrace: false); |
635 | return false; |
636 | } |
637 | return true; |
638 | } |
639 | |
640 | // this code is deliberately written such that clang makes it into really |
641 | // efficient SSE code. |
642 | template <bool ZigZag, bool SignExtended, typename T> |
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(n: x); |
661 | } else if (SignExtended) { |
662 | msb_sum += x >> 31; |
663 | } |
664 | // clang is so smart that it produces optimal SSE sequence unrolling |
665 | // the loop 8 ints at a time. With a sequence of 4 |
666 | // cmpres = cmpgt x, sizeclass ( -1 or 0) |
667 | // sum = sum - cmpres |
668 | if (x > 0x7F) sum++; |
669 | if (x > 0x3FFF) sum++; |
670 | if (x > 0x1FFFFF) sum++; |
671 | if (x > 0xFFFFFFF) sum++; |
672 | } |
673 | if (SignExtended) sum += msb_sum * 5; |
674 | return sum; |
675 | } |
676 | |
677 | template <bool ZigZag, typename T> |
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(n: x); |
688 | } |
689 | // First step is a binary search, we can't branch in sse so we use the |
690 | // result of the compare to adjust sum and appropriately. This code is |
691 | // written to make clang recognize the vectorization. |
692 | uint64_t tmp = x >= (static_cast<uint64_t>(1) << 35) ? -1 : 0; |
693 | sum += 5 & tmp; |
694 | x >>= 35 & tmp; |
695 | if (x > 0x7F) sum++; |
696 | if (x > 0x3FFF) sum++; |
697 | if (x > 0x1FFFFF) sum++; |
698 | if (x > 0xFFFFFFF) sum++; |
699 | } |
700 | return sum; |
701 | } |
702 | |
703 | // GCC does not recognize the vectorization opportunity |
704 | // and other platforms are untested, in those cases using the optimized |
705 | // varint size routine for each element is faster. |
706 | // Hence we enable it only for clang |
707 | #if defined(__SSE__) && defined(__clang__) |
708 | size_t WireFormatLite::Int32Size(const RepeatedField<int32_t>& value) { |
709 | return VarintSize<false, true>(value.data(), value.size()); |
710 | } |
711 | |
712 | size_t WireFormatLite::UInt32Size(const RepeatedField<uint32_t>& value) { |
713 | return VarintSize<false, false>(value.data(), value.size()); |
714 | } |
715 | |
716 | size_t WireFormatLite::SInt32Size(const RepeatedField<int32_t>& value) { |
717 | return VarintSize<true, false>(value.data(), value.size()); |
718 | } |
719 | |
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 | |
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: value.Get(index: i)); |
732 | } |
733 | return out; |
734 | } |
735 | |
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: value.Get(index: i)); |
741 | } |
742 | return out; |
743 | } |
744 | |
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: value.Get(index: i)); |
750 | } |
751 | return out; |
752 | } |
753 | |
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: value.Get(index: i)); |
759 | } |
760 | return out; |
761 | } |
762 | |
763 | #endif |
764 | |
765 | // Micro benchmarks show that the SSE improved loop only starts beating |
766 | // the normal loop on Haswell platforms and then only for >32 ints. We |
767 | // disable this for now. Some specialized users might find it worthwhile to |
768 | // enable this. |
769 | #define USE_SSE_FOR_64_BIT_INTEGER_ARRAYS 0 |
770 | #if USE_SSE_FOR_64_BIT_INTEGER_ARRAYS |
771 | size_t WireFormatLite::Int64Size(const RepeatedField<int64_t>& value) { |
772 | return VarintSize64<false>(value.data(), value.size()); |
773 | } |
774 | |
775 | size_t WireFormatLite::UInt64Size(const RepeatedField<uint64_t>& value) { |
776 | return VarintSize64<false>(value.data(), value.size()); |
777 | } |
778 | |
779 | size_t WireFormatLite::SInt64Size(const RepeatedField<int64_t>& value) { |
780 | return VarintSize64<true>(value.data(), value.size()); |
781 | } |
782 | |
783 | #else |
784 | |
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: value.Get(index: i)); |
790 | } |
791 | return out; |
792 | } |
793 | |
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: value.Get(index: i)); |
799 | } |
800 | return out; |
801 | } |
802 | |
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: value.Get(index: i)); |
808 | } |
809 | return out; |
810 | } |
811 | |
812 | #endif |
813 | |
814 | } // namespace internal |
815 | } // namespace protobuf |
816 | } // namespace google |
817 | |
818 | #include <google/protobuf/port_undef.inc> |
819 | |