blob: f2517074696e9958a15e9443e585a625627acab5 [file] [log] [blame]
kenton@google.com80b1d622009-07-29 01:13:20 +00001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
kenton@google.com80b1d622009-07-29 01:13:20 +00004//
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
kenton@google.comfccb1462009-12-18 02:11:36 +000035#include <google/protobuf/wire_format_lite_inl.h>
36
kenton@google.com80b1d622009-07-29 01:13:20 +000037#include <stack>
38#include <string>
39#include <vector>
Feng Xiaoeee38b02015-08-22 18:25:48 -070040#include <google/protobuf/stubs/logging.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000041#include <google/protobuf/stubs/common.h>
Feng Xiaob17ec3c2015-08-23 17:50:38 -070042#include <google/protobuf/stubs/stringprintf.h>
kenton@google.comfccb1462009-12-18 02:11:36 +000043#include <google/protobuf/io/coded_stream_inl.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000044#include <google/protobuf/io/zero_copy_stream.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000045#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000046
Feng Xiaob17ec3c2015-08-23 17:50:38 -070047
kenton@google.com80b1d622009-07-29 01:13:20 +000048namespace google {
49namespace protobuf {
50namespace internal {
51
Bruce Dawson86ba70e2015-10-29 12:41:29 -070052
53#if !defined(_MSC_VER) || _MSC_VER >= 1900
54// Old version of MSVC doesn't like definitions of inline constants, GCC
55// requires them.
kenton@google.com80b1d622009-07-29 01:13:20 +000056const int WireFormatLite::kMessageSetItemStartTag;
57const int WireFormatLite::kMessageSetItemEndTag;
58const int WireFormatLite::kMessageSetTypeIdTag;
59const int WireFormatLite::kMessageSetMessageTag;
60
61#endif
62
Andrew Paprocki4eaa16f2014-10-31 15:46:39 -040063// IBM xlC requires prefixing constants with WireFormatLite::
kenton@google.com80b1d622009-07-29 01:13:20 +000064const int WireFormatLite::kMessageSetItemTagsSize =
Feng Xiao99aa0f92014-11-20 16:18:53 -080065 io::CodedOutputStream::StaticVarintSize32<
66 WireFormatLite::kMessageSetItemStartTag>::value +
67 io::CodedOutputStream::StaticVarintSize32<
68 WireFormatLite::kMessageSetItemEndTag>::value +
69 io::CodedOutputStream::StaticVarintSize32<
70 WireFormatLite::kMessageSetTypeIdTag>::value +
71 io::CodedOutputStream::StaticVarintSize32<
72 WireFormatLite::kMessageSetMessageTag>::value;
kenton@google.com80b1d622009-07-29 01:13:20 +000073
74const WireFormatLite::CppType
75WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
76 static_cast<CppType>(0), // 0 is reserved for errors
77
78 CPPTYPE_DOUBLE, // TYPE_DOUBLE
79 CPPTYPE_FLOAT, // TYPE_FLOAT
80 CPPTYPE_INT64, // TYPE_INT64
81 CPPTYPE_UINT64, // TYPE_UINT64
82 CPPTYPE_INT32, // TYPE_INT32
83 CPPTYPE_UINT64, // TYPE_FIXED64
84 CPPTYPE_UINT32, // TYPE_FIXED32
85 CPPTYPE_BOOL, // TYPE_BOOL
86 CPPTYPE_STRING, // TYPE_STRING
87 CPPTYPE_MESSAGE, // TYPE_GROUP
88 CPPTYPE_MESSAGE, // TYPE_MESSAGE
89 CPPTYPE_STRING, // TYPE_BYTES
90 CPPTYPE_UINT32, // TYPE_UINT32
91 CPPTYPE_ENUM, // TYPE_ENUM
92 CPPTYPE_INT32, // TYPE_SFIXED32
93 CPPTYPE_INT64, // TYPE_SFIXED64
94 CPPTYPE_INT32, // TYPE_SINT32
95 CPPTYPE_INT64, // TYPE_SINT64
96};
97
98const WireFormatLite::WireType
99WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
100 static_cast<WireFormatLite::WireType>(-1), // invalid
101 WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE
102 WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT
103 WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64
104 WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64
105 WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32
106 WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64
107 WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32
108 WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL
109 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING
110 WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP
111 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE
112 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES
113 WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32
114 WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM
115 WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32
116 WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64
117 WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32
118 WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64
119};
120
121bool WireFormatLite::SkipField(
122 io::CodedInputStream* input, uint32 tag) {
123 switch (WireFormatLite::GetTagWireType(tag)) {
124 case WireFormatLite::WIRETYPE_VARINT: {
125 uint64 value;
126 if (!input->ReadVarint64(&value)) return false;
127 return true;
128 }
129 case WireFormatLite::WIRETYPE_FIXED64: {
130 uint64 value;
131 if (!input->ReadLittleEndian64(&value)) return false;
132 return true;
133 }
134 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
135 uint32 length;
136 if (!input->ReadVarint32(&length)) return false;
137 if (!input->Skip(length)) return false;
138 return true;
139 }
140 case WireFormatLite::WIRETYPE_START_GROUP: {
141 if (!input->IncrementRecursionDepth()) return false;
142 if (!SkipMessage(input)) return false;
143 input->DecrementRecursionDepth();
144 // Check that the ending tag matched the starting tag.
145 if (!input->LastTagWas(WireFormatLite::MakeTag(
146 WireFormatLite::GetTagFieldNumber(tag),
147 WireFormatLite::WIRETYPE_END_GROUP))) {
148 return false;
149 }
150 return true;
151 }
152 case WireFormatLite::WIRETYPE_END_GROUP: {
153 return false;
154 }
155 case WireFormatLite::WIRETYPE_FIXED32: {
156 uint32 value;
157 if (!input->ReadLittleEndian32(&value)) return false;
158 return true;
159 }
160 default: {
161 return false;
162 }
163 }
164}
165
jieluo@google.com4de8f552014-07-18 00:47:59 +0000166bool WireFormatLite::SkipField(
167 io::CodedInputStream* input, uint32 tag, io::CodedOutputStream* output) {
168 switch (WireFormatLite::GetTagWireType(tag)) {
169 case WireFormatLite::WIRETYPE_VARINT: {
170 uint64 value;
171 if (!input->ReadVarint64(&value)) return false;
172 output->WriteVarint32(tag);
173 output->WriteVarint64(value);
174 return true;
175 }
176 case WireFormatLite::WIRETYPE_FIXED64: {
177 uint64 value;
178 if (!input->ReadLittleEndian64(&value)) return false;
179 output->WriteVarint32(tag);
180 output->WriteLittleEndian64(value);
181 return true;
182 }
183 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
184 uint32 length;
185 if (!input->ReadVarint32(&length)) return false;
186 output->WriteVarint32(tag);
187 output->WriteVarint32(length);
188 // TODO(mkilavuz): Provide API to prevent extra string copying.
189 string temp;
190 if (!input->ReadString(&temp, length)) return false;
191 output->WriteString(temp);
192 return true;
193 }
194 case WireFormatLite::WIRETYPE_START_GROUP: {
195 output->WriteVarint32(tag);
196 if (!input->IncrementRecursionDepth()) return false;
197 if (!SkipMessage(input, output)) return false;
198 input->DecrementRecursionDepth();
199 // Check that the ending tag matched the starting tag.
200 if (!input->LastTagWas(WireFormatLite::MakeTag(
201 WireFormatLite::GetTagFieldNumber(tag),
202 WireFormatLite::WIRETYPE_END_GROUP))) {
203 return false;
204 }
205 return true;
206 }
207 case WireFormatLite::WIRETYPE_END_GROUP: {
208 return false;
209 }
210 case WireFormatLite::WIRETYPE_FIXED32: {
211 uint32 value;
212 if (!input->ReadLittleEndian32(&value)) return false;
213 output->WriteVarint32(tag);
214 output->WriteLittleEndian32(value);
215 return true;
216 }
217 default: {
218 return false;
219 }
220 }
221}
222
kenton@google.com80b1d622009-07-29 01:13:20 +0000223bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000224 while (true) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000225 uint32 tag = input->ReadTag();
226 if (tag == 0) {
227 // End of input. This is a valid place to end, so return true.
228 return true;
229 }
230
231 WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
232
233 if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
234 // Must be the end of the message.
235 return true;
236 }
237
238 if (!SkipField(input, tag)) return false;
239 }
240}
241
jieluo@google.com4de8f552014-07-18 00:47:59 +0000242bool WireFormatLite::SkipMessage(io::CodedInputStream* input,
243 io::CodedOutputStream* output) {
244 while (true) {
245 uint32 tag = input->ReadTag();
246 if (tag == 0) {
247 // End of input. This is a valid place to end, so return true.
248 return true;
249 }
250
251 WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
252
253 if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
254 output->WriteVarint32(tag);
255 // Must be the end of the message.
256 return true;
257 }
258
259 if (!SkipField(input, tag, output)) return false;
260 }
261}
262
kenton@google.com80b1d622009-07-29 01:13:20 +0000263bool FieldSkipper::SkipField(
264 io::CodedInputStream* input, uint32 tag) {
265 return WireFormatLite::SkipField(input, tag);
266}
267
268bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
269 return WireFormatLite::SkipMessage(input);
270}
271
272void FieldSkipper::SkipUnknownEnum(
liujisi@google.comc5553a32014-05-28 21:48:28 +0000273 int /* field_number */, int /* value */) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000274 // Nothing.
275}
276
jieluo@google.com4de8f552014-07-18 00:47:59 +0000277bool CodedOutputStreamFieldSkipper::SkipField(
278 io::CodedInputStream* input, uint32 tag) {
279 return WireFormatLite::SkipField(input, tag, unknown_fields_);
280}
281
282bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) {
283 return WireFormatLite::SkipMessage(input, unknown_fields_);
284}
285
286void CodedOutputStreamFieldSkipper::SkipUnknownEnum(
287 int field_number, int value) {
288 unknown_fields_->WriteVarint32(field_number);
289 unknown_fields_->WriteVarint64(value);
290}
291
kenton@google.comfccb1462009-12-18 02:11:36 +0000292bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
293 bool (*is_valid)(int),
294 RepeatedField<int>* values) {
295 uint32 length;
296 if (!input->ReadVarint32(&length)) return false;
297 io::CodedInputStream::Limit limit = input->PushLimit(length);
298 while (input->BytesUntilLimit() > 0) {
299 int value;
300 if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
301 int, WireFormatLite::TYPE_ENUM>(input, &value)) {
302 return false;
303 }
Feng Xiao6ef984a2014-11-10 17:34:54 -0800304 if (is_valid == NULL || is_valid(value)) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000305 values->Add(value);
306 }
307 }
308 input->PopLimit(limit);
309 return true;
310}
311
Jisi Liu885b6122015-02-28 14:51:22 -0800312bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
313 io::CodedInputStream* input,
314 int field_number,
315 bool (*is_valid)(int),
316 io::CodedOutputStream* unknown_fields_stream,
317 RepeatedField<int>* values) {
318 uint32 length;
319 if (!input->ReadVarint32(&length)) return false;
320 io::CodedInputStream::Limit limit = input->PushLimit(length);
321 while (input->BytesUntilLimit() > 0) {
322 int value;
323 if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
324 int, WireFormatLite::TYPE_ENUM>(input, &value)) {
325 return false;
326 }
327 if (is_valid == NULL || is_valid(value)) {
328 values->Add(value);
329 } else {
330 uint32 tag = WireFormatLite::MakeTag(field_number,
331 WireFormatLite::WIRETYPE_VARINT);
332 unknown_fields_stream->WriteVarint32(tag);
333 unknown_fields_stream->WriteVarint32(value);
334 }
335 }
336 input->PopLimit(limit);
337 return true;
338}
339
kenton@google.comfccb1462009-12-18 02:11:36 +0000340void WireFormatLite::WriteInt32(int field_number, int32 value,
341 io::CodedOutputStream* output) {
342 WriteTag(field_number, WIRETYPE_VARINT, output);
343 WriteInt32NoTag(value, output);
344}
345void WireFormatLite::WriteInt64(int field_number, int64 value,
346 io::CodedOutputStream* output) {
347 WriteTag(field_number, WIRETYPE_VARINT, output);
348 WriteInt64NoTag(value, output);
349}
350void WireFormatLite::WriteUInt32(int field_number, uint32 value,
351 io::CodedOutputStream* output) {
352 WriteTag(field_number, WIRETYPE_VARINT, output);
353 WriteUInt32NoTag(value, output);
354}
355void WireFormatLite::WriteUInt64(int field_number, uint64 value,
356 io::CodedOutputStream* output) {
357 WriteTag(field_number, WIRETYPE_VARINT, output);
358 WriteUInt64NoTag(value, output);
359}
360void WireFormatLite::WriteSInt32(int field_number, int32 value,
361 io::CodedOutputStream* output) {
362 WriteTag(field_number, WIRETYPE_VARINT, output);
363 WriteSInt32NoTag(value, output);
364}
365void WireFormatLite::WriteSInt64(int field_number, int64 value,
366 io::CodedOutputStream* output) {
367 WriteTag(field_number, WIRETYPE_VARINT, output);
368 WriteSInt64NoTag(value, output);
369}
370void WireFormatLite::WriteFixed32(int field_number, uint32 value,
371 io::CodedOutputStream* output) {
372 WriteTag(field_number, WIRETYPE_FIXED32, output);
373 WriteFixed32NoTag(value, output);
374}
375void WireFormatLite::WriteFixed64(int field_number, uint64 value,
376 io::CodedOutputStream* output) {
377 WriteTag(field_number, WIRETYPE_FIXED64, output);
378 WriteFixed64NoTag(value, output);
379}
380void WireFormatLite::WriteSFixed32(int field_number, int32 value,
381 io::CodedOutputStream* output) {
382 WriteTag(field_number, WIRETYPE_FIXED32, output);
383 WriteSFixed32NoTag(value, output);
384}
385void WireFormatLite::WriteSFixed64(int field_number, int64 value,
386 io::CodedOutputStream* output) {
387 WriteTag(field_number, WIRETYPE_FIXED64, output);
388 WriteSFixed64NoTag(value, output);
389}
390void WireFormatLite::WriteFloat(int field_number, float value,
391 io::CodedOutputStream* output) {
392 WriteTag(field_number, WIRETYPE_FIXED32, output);
393 WriteFloatNoTag(value, output);
394}
395void WireFormatLite::WriteDouble(int field_number, double value,
396 io::CodedOutputStream* output) {
397 WriteTag(field_number, WIRETYPE_FIXED64, output);
398 WriteDoubleNoTag(value, output);
399}
400void WireFormatLite::WriteBool(int field_number, bool value,
401 io::CodedOutputStream* output) {
402 WriteTag(field_number, WIRETYPE_VARINT, output);
403 WriteBoolNoTag(value, output);
404}
405void WireFormatLite::WriteEnum(int field_number, int value,
406 io::CodedOutputStream* output) {
407 WriteTag(field_number, WIRETYPE_VARINT, output);
408 WriteEnumNoTag(value, output);
409}
410
411void WireFormatLite::WriteString(int field_number, const string& value,
412 io::CodedOutputStream* output) {
413 // String is for UTF-8 text only
414 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700415 GOOGLE_CHECK_LE(value.size(), kint32max);
kenton@google.comfccb1462009-12-18 02:11:36 +0000416 output->WriteVarint32(value.size());
417 output->WriteString(value);
418}
jieluo@google.com4de8f552014-07-18 00:47:59 +0000419void WireFormatLite::WriteStringMaybeAliased(
420 int field_number, const string& value,
421 io::CodedOutputStream* output) {
422 // String is for UTF-8 text only
423 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700424 GOOGLE_CHECK_LE(value.size(), kint32max);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000425 output->WriteVarint32(value.size());
426 output->WriteRawMaybeAliased(value.data(), value.size());
427}
kenton@google.comfccb1462009-12-18 02:11:36 +0000428void WireFormatLite::WriteBytes(int field_number, const string& value,
429 io::CodedOutputStream* output) {
430 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700431 GOOGLE_CHECK_LE(value.size(), kint32max);
kenton@google.comfccb1462009-12-18 02:11:36 +0000432 output->WriteVarint32(value.size());
433 output->WriteString(value);
434}
jieluo@google.com4de8f552014-07-18 00:47:59 +0000435void WireFormatLite::WriteBytesMaybeAliased(
436 int field_number, const string& value,
437 io::CodedOutputStream* output) {
438 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700439 GOOGLE_CHECK_LE(value.size(), kint32max);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000440 output->WriteVarint32(value.size());
441 output->WriteRawMaybeAliased(value.data(), value.size());
442}
kenton@google.comfccb1462009-12-18 02:11:36 +0000443
444
445void WireFormatLite::WriteGroup(int field_number,
446 const MessageLite& value,
447 io::CodedOutputStream* output) {
448 WriteTag(field_number, WIRETYPE_START_GROUP, output);
449 value.SerializeWithCachedSizes(output);
450 WriteTag(field_number, WIRETYPE_END_GROUP, output);
451}
452
453void WireFormatLite::WriteMessage(int field_number,
454 const MessageLite& value,
455 io::CodedOutputStream* output) {
456 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
457 const int size = value.GetCachedSize();
458 output->WriteVarint32(size);
459 value.SerializeWithCachedSizes(output);
460}
461
462void WireFormatLite::WriteGroupMaybeToArray(int field_number,
463 const MessageLite& value,
464 io::CodedOutputStream* output) {
465 WriteTag(field_number, WIRETYPE_START_GROUP, output);
466 const int size = value.GetCachedSize();
467 uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
468 if (target != NULL) {
469 uint8* end = value.SerializeWithCachedSizesToArray(target);
470 GOOGLE_DCHECK_EQ(end - target, size);
471 } else {
472 value.SerializeWithCachedSizes(output);
473 }
474 WriteTag(field_number, WIRETYPE_END_GROUP, output);
475}
476
477void WireFormatLite::WriteMessageMaybeToArray(int field_number,
478 const MessageLite& value,
479 io::CodedOutputStream* output) {
480 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
481 const int size = value.GetCachedSize();
482 output->WriteVarint32(size);
483 uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
484 if (target != NULL) {
485 uint8* end = value.SerializeWithCachedSizesToArray(target);
486 GOOGLE_DCHECK_EQ(end - target, size);
487 } else {
488 value.SerializeWithCachedSizes(output);
489 }
490}
491
Feng Xiaoeee38b02015-08-22 18:25:48 -0700492GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString(
493 io::CodedInputStream* input, string* value);
494inline static bool ReadBytesToString(io::CodedInputStream* input,
Feng Xiao6ef984a2014-11-10 17:34:54 -0800495 string* value) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000496 uint32 length;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800497 return input->ReadVarint32(&length) &&
498 input->InternalReadStringInline(value, length);
kenton@google.comfccb1462009-12-18 02:11:36 +0000499}
Feng Xiao6ef984a2014-11-10 17:34:54 -0800500
501bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string* value) {
502 return ReadBytesToString(input, value);
503}
504
505bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string** p) {
506 if (*p == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
507 *p = new ::std::string();
508 }
509 return ReadBytesToString(input, *p);
kenton@google.comfccb1462009-12-18 02:11:36 +0000510}
511
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700512bool WireFormatLite::VerifyUtf8String(const char* data,
513 int size,
514 Operation op,
515 const char* field_name) {
516 if (!IsStructurallyValidUTF8(data, size)) {
517 const char* operation_str = NULL;
518 switch (op) {
519 case PARSE:
520 operation_str = "parsing";
521 break;
522 case SERIALIZE:
523 operation_str = "serializing";
524 break;
525 // no default case: have the compiler warn if a case is not covered.
526 }
527 string quoted_field_name = "";
528 if (field_name != NULL) {
529 quoted_field_name = StringPrintf(" '%s'", field_name);
530 }
531 // no space below to avoid double space when the field name is missing.
532 GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
533 << "UTF-8 data when " << operation_str << " a protocol "
534 << "buffer. Use the 'bytes' type if you intend to send raw "
535 << "bytes. ";
536 return false;
537 }
538 return true;
539}
540
kenton@google.com80b1d622009-07-29 01:13:20 +0000541} // namespace internal
542} // namespace protobuf
543} // namespace google