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_inl.h>
36
37 #include <stack>
38 #include <string>
39 #include <vector>
40 #include <google/protobuf/stubs/logging.h>
41 #include <google/protobuf/stubs/common.h>
42 #include <google/protobuf/stubs/stringprintf.h>
43 #include <google/protobuf/io/coded_stream_inl.h>
44 #include <google/protobuf/io/zero_copy_stream.h>
45 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
46
47
48 namespace google {
49 namespace protobuf {
50 namespace internal {
51
52
53 #if !defined(_MSC_VER) || _MSC_VER >= 1900
54 // Old version of MSVC doesn't like definitions of inline constants, GCC
55 // requires them.
56 const int WireFormatLite::kMessageSetItemStartTag;
57 const int WireFormatLite::kMessageSetItemEndTag;
58 const int WireFormatLite::kMessageSetTypeIdTag;
59 const int WireFormatLite::kMessageSetMessageTag;
60
61 #endif
62
63 // IBM xlC requires prefixing constants with WireFormatLite::
64 const int WireFormatLite::kMessageSetItemTagsSize =
65 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;
73
74 const WireFormatLite::CppType
75 WireFormatLite::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
98 const WireFormatLite::WireType
99 WireFormatLite::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
SkipField(io::CodedInputStream * input,uint32 tag)121 bool 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
SkipField(io::CodedInputStream * input,uint32 tag,io::CodedOutputStream * output)166 bool 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
SkipMessage(io::CodedInputStream * input)223 bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
224 while (true) {
225 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
SkipMessage(io::CodedInputStream * input,io::CodedOutputStream * output)242 bool 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
SkipField(io::CodedInputStream * input,uint32 tag)263 bool FieldSkipper::SkipField(
264 io::CodedInputStream* input, uint32 tag) {
265 return WireFormatLite::SkipField(input, tag);
266 }
267
SkipMessage(io::CodedInputStream * input)268 bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
269 return WireFormatLite::SkipMessage(input);
270 }
271
SkipUnknownEnum(int,int)272 void FieldSkipper::SkipUnknownEnum(
273 int /* field_number */, int /* value */) {
274 // Nothing.
275 }
276
SkipField(io::CodedInputStream * input,uint32 tag)277 bool CodedOutputStreamFieldSkipper::SkipField(
278 io::CodedInputStream* input, uint32 tag) {
279 return WireFormatLite::SkipField(input, tag, unknown_fields_);
280 }
281
SkipMessage(io::CodedInputStream * input)282 bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) {
283 return WireFormatLite::SkipMessage(input, unknown_fields_);
284 }
285
SkipUnknownEnum(int field_number,int value)286 void CodedOutputStreamFieldSkipper::SkipUnknownEnum(
287 int field_number, int value) {
288 unknown_fields_->WriteVarint32(field_number);
289 unknown_fields_->WriteVarint64(value);
290 }
291
ReadPackedEnumNoInline(io::CodedInputStream * input,bool (* is_valid)(int),RepeatedField<int> * values)292 bool 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 }
304 if (is_valid == NULL || is_valid(value)) {
305 values->Add(value);
306 }
307 }
308 input->PopLimit(limit);
309 return true;
310 }
311
ReadPackedEnumPreserveUnknowns(io::CodedInputStream * input,int field_number,bool (* is_valid)(int),io::CodedOutputStream * unknown_fields_stream,RepeatedField<int> * values)312 bool 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
WriteInt32(int field_number,int32 value,io::CodedOutputStream * output)340 void WireFormatLite::WriteInt32(int field_number, int32 value,
341 io::CodedOutputStream* output) {
342 WriteTag(field_number, WIRETYPE_VARINT, output);
343 WriteInt32NoTag(value, output);
344 }
WriteInt64(int field_number,int64 value,io::CodedOutputStream * output)345 void WireFormatLite::WriteInt64(int field_number, int64 value,
346 io::CodedOutputStream* output) {
347 WriteTag(field_number, WIRETYPE_VARINT, output);
348 WriteInt64NoTag(value, output);
349 }
WriteUInt32(int field_number,uint32 value,io::CodedOutputStream * output)350 void WireFormatLite::WriteUInt32(int field_number, uint32 value,
351 io::CodedOutputStream* output) {
352 WriteTag(field_number, WIRETYPE_VARINT, output);
353 WriteUInt32NoTag(value, output);
354 }
WriteUInt64(int field_number,uint64 value,io::CodedOutputStream * output)355 void WireFormatLite::WriteUInt64(int field_number, uint64 value,
356 io::CodedOutputStream* output) {
357 WriteTag(field_number, WIRETYPE_VARINT, output);
358 WriteUInt64NoTag(value, output);
359 }
WriteSInt32(int field_number,int32 value,io::CodedOutputStream * output)360 void WireFormatLite::WriteSInt32(int field_number, int32 value,
361 io::CodedOutputStream* output) {
362 WriteTag(field_number, WIRETYPE_VARINT, output);
363 WriteSInt32NoTag(value, output);
364 }
WriteSInt64(int field_number,int64 value,io::CodedOutputStream * output)365 void WireFormatLite::WriteSInt64(int field_number, int64 value,
366 io::CodedOutputStream* output) {
367 WriteTag(field_number, WIRETYPE_VARINT, output);
368 WriteSInt64NoTag(value, output);
369 }
WriteFixed32(int field_number,uint32 value,io::CodedOutputStream * output)370 void WireFormatLite::WriteFixed32(int field_number, uint32 value,
371 io::CodedOutputStream* output) {
372 WriteTag(field_number, WIRETYPE_FIXED32, output);
373 WriteFixed32NoTag(value, output);
374 }
WriteFixed64(int field_number,uint64 value,io::CodedOutputStream * output)375 void WireFormatLite::WriteFixed64(int field_number, uint64 value,
376 io::CodedOutputStream* output) {
377 WriteTag(field_number, WIRETYPE_FIXED64, output);
378 WriteFixed64NoTag(value, output);
379 }
WriteSFixed32(int field_number,int32 value,io::CodedOutputStream * output)380 void WireFormatLite::WriteSFixed32(int field_number, int32 value,
381 io::CodedOutputStream* output) {
382 WriteTag(field_number, WIRETYPE_FIXED32, output);
383 WriteSFixed32NoTag(value, output);
384 }
WriteSFixed64(int field_number,int64 value,io::CodedOutputStream * output)385 void WireFormatLite::WriteSFixed64(int field_number, int64 value,
386 io::CodedOutputStream* output) {
387 WriteTag(field_number, WIRETYPE_FIXED64, output);
388 WriteSFixed64NoTag(value, output);
389 }
WriteFloat(int field_number,float value,io::CodedOutputStream * output)390 void WireFormatLite::WriteFloat(int field_number, float value,
391 io::CodedOutputStream* output) {
392 WriteTag(field_number, WIRETYPE_FIXED32, output);
393 WriteFloatNoTag(value, output);
394 }
WriteDouble(int field_number,double value,io::CodedOutputStream * output)395 void WireFormatLite::WriteDouble(int field_number, double value,
396 io::CodedOutputStream* output) {
397 WriteTag(field_number, WIRETYPE_FIXED64, output);
398 WriteDoubleNoTag(value, output);
399 }
WriteBool(int field_number,bool value,io::CodedOutputStream * output)400 void WireFormatLite::WriteBool(int field_number, bool value,
401 io::CodedOutputStream* output) {
402 WriteTag(field_number, WIRETYPE_VARINT, output);
403 WriteBoolNoTag(value, output);
404 }
WriteEnum(int field_number,int value,io::CodedOutputStream * output)405 void WireFormatLite::WriteEnum(int field_number, int value,
406 io::CodedOutputStream* output) {
407 WriteTag(field_number, WIRETYPE_VARINT, output);
408 WriteEnumNoTag(value, output);
409 }
410
WriteString(int field_number,const string & value,io::CodedOutputStream * output)411 void 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);
415 GOOGLE_CHECK_LE(value.size(), kint32max);
416 output->WriteVarint32(value.size());
417 output->WriteString(value);
418 }
WriteStringMaybeAliased(int field_number,const string & value,io::CodedOutputStream * output)419 void 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);
424 GOOGLE_CHECK_LE(value.size(), kint32max);
425 output->WriteVarint32(value.size());
426 output->WriteRawMaybeAliased(value.data(), value.size());
427 }
WriteBytes(int field_number,const string & value,io::CodedOutputStream * output)428 void WireFormatLite::WriteBytes(int field_number, const string& value,
429 io::CodedOutputStream* output) {
430 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
431 GOOGLE_CHECK_LE(value.size(), kint32max);
432 output->WriteVarint32(value.size());
433 output->WriteString(value);
434 }
WriteBytesMaybeAliased(int field_number,const string & value,io::CodedOutputStream * output)435 void WireFormatLite::WriteBytesMaybeAliased(
436 int field_number, const string& value,
437 io::CodedOutputStream* output) {
438 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
439 GOOGLE_CHECK_LE(value.size(), kint32max);
440 output->WriteVarint32(value.size());
441 output->WriteRawMaybeAliased(value.data(), value.size());
442 }
443
444
WriteGroup(int field_number,const MessageLite & value,io::CodedOutputStream * output)445 void 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
WriteMessage(int field_number,const MessageLite & value,io::CodedOutputStream * output)453 void 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
WriteGroupMaybeToArray(int field_number,const MessageLite & value,io::CodedOutputStream * output)462 void 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.InternalSerializeWithCachedSizesToArray(
470 output->IsSerializationDeterminstic(), target);
471 GOOGLE_DCHECK_EQ(end - target, size);
472 } else {
473 value.SerializeWithCachedSizes(output);
474 }
475 WriteTag(field_number, WIRETYPE_END_GROUP, output);
476 }
477
WriteMessageMaybeToArray(int field_number,const MessageLite & value,io::CodedOutputStream * output)478 void WireFormatLite::WriteMessageMaybeToArray(int field_number,
479 const MessageLite& value,
480 io::CodedOutputStream* output) {
481 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
482 const int size = value.GetCachedSize();
483 output->WriteVarint32(size);
484 uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
485 if (target != NULL) {
486 uint8* end = value.InternalSerializeWithCachedSizesToArray(
487 output->IsSerializationDeterminstic(), target);
488 GOOGLE_DCHECK_EQ(end - target, size);
489 } else {
490 value.SerializeWithCachedSizes(output);
491 }
492 }
493
494 GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString(
495 io::CodedInputStream* input, string* value);
ReadBytesToString(io::CodedInputStream * input,string * value)496 inline static bool ReadBytesToString(io::CodedInputStream* input,
497 string* value) {
498 uint32 length;
499 return input->ReadVarint32(&length) &&
500 input->InternalReadStringInline(value, length);
501 }
502
ReadBytes(io::CodedInputStream * input,string * value)503 bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string* value) {
504 return ReadBytesToString(input, value);
505 }
506
ReadBytes(io::CodedInputStream * input,string ** p)507 bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string** p) {
508 if (*p == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
509 *p = new ::std::string();
510 }
511 return ReadBytesToString(input, *p);
512 }
513
VerifyUtf8String(const char * data,int size,Operation op,const char * field_name)514 bool WireFormatLite::VerifyUtf8String(const char* data,
515 int size,
516 Operation op,
517 const char* field_name) {
518 if (!IsStructurallyValidUTF8(data, size)) {
519 const char* operation_str = NULL;
520 switch (op) {
521 case PARSE:
522 operation_str = "parsing";
523 break;
524 case SERIALIZE:
525 operation_str = "serializing";
526 break;
527 // no default case: have the compiler warn if a case is not covered.
528 }
529 string quoted_field_name = "";
530 if (field_name != NULL) {
531 quoted_field_name = StringPrintf(" '%s'", field_name);
532 }
533 // no space below to avoid double space when the field name is missing.
534 GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
535 << "UTF-8 data when " << operation_str << " a protocol "
536 << "buffer. Use the 'bytes' type if you intend to send raw "
537 << "bytes. ";
538 return false;
539 }
540 return true;
541 }
542
543 } // namespace internal
544 } // namespace protobuf
545 } // namespace google
546