• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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