Line data Source code
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 : #ifndef _MSC_VER // MSVC doesn't like definitions of inline constants, GCC
53 : // requires them.
54 : const int WireFormatLite::kMessageSetItemStartTag;
55 : const int WireFormatLite::kMessageSetItemEndTag;
56 : const int WireFormatLite::kMessageSetTypeIdTag;
57 : const int WireFormatLite::kMessageSetMessageTag;
58 :
59 : #endif
60 :
61 : // IBM xlC requires prefixing constants with WireFormatLite::
62 : const int WireFormatLite::kMessageSetItemTagsSize =
63 : io::CodedOutputStream::StaticVarintSize32<
64 : WireFormatLite::kMessageSetItemStartTag>::value +
65 : io::CodedOutputStream::StaticVarintSize32<
66 : WireFormatLite::kMessageSetItemEndTag>::value +
67 : io::CodedOutputStream::StaticVarintSize32<
68 : WireFormatLite::kMessageSetTypeIdTag>::value +
69 : io::CodedOutputStream::StaticVarintSize32<
70 : WireFormatLite::kMessageSetMessageTag>::value;
71 :
72 : const WireFormatLite::CppType
73 : WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
74 : static_cast<CppType>(0), // 0 is reserved for errors
75 :
76 : CPPTYPE_DOUBLE, // TYPE_DOUBLE
77 : CPPTYPE_FLOAT, // TYPE_FLOAT
78 : CPPTYPE_INT64, // TYPE_INT64
79 : CPPTYPE_UINT64, // TYPE_UINT64
80 : CPPTYPE_INT32, // TYPE_INT32
81 : CPPTYPE_UINT64, // TYPE_FIXED64
82 : CPPTYPE_UINT32, // TYPE_FIXED32
83 : CPPTYPE_BOOL, // TYPE_BOOL
84 : CPPTYPE_STRING, // TYPE_STRING
85 : CPPTYPE_MESSAGE, // TYPE_GROUP
86 : CPPTYPE_MESSAGE, // TYPE_MESSAGE
87 : CPPTYPE_STRING, // TYPE_BYTES
88 : CPPTYPE_UINT32, // TYPE_UINT32
89 : CPPTYPE_ENUM, // TYPE_ENUM
90 : CPPTYPE_INT32, // TYPE_SFIXED32
91 : CPPTYPE_INT64, // TYPE_SFIXED64
92 : CPPTYPE_INT32, // TYPE_SINT32
93 : CPPTYPE_INT64, // TYPE_SINT64
94 : };
95 :
96 : const WireFormatLite::WireType
97 : WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
98 : static_cast<WireFormatLite::WireType>(-1), // invalid
99 : WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE
100 : WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT
101 : WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64
102 : WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64
103 : WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32
104 : WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64
105 : WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32
106 : WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL
107 : WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING
108 : WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP
109 : WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE
110 : WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES
111 : WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32
112 : WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM
113 : WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32
114 : WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64
115 : WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32
116 : WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64
117 : };
118 :
119 0 : bool WireFormatLite::SkipField(
120 0 : io::CodedInputStream* input, uint32 tag) {
121 0 : switch (WireFormatLite::GetTagWireType(tag)) {
122 : case WireFormatLite::WIRETYPE_VARINT: {
123 : uint64 value;
124 0 : if (!input->ReadVarint64(&value)) return false;
125 0 : return true;
126 : }
127 : case WireFormatLite::WIRETYPE_FIXED64: {
128 : uint64 value;
129 0 : if (!input->ReadLittleEndian64(&value)) return false;
130 0 : return true;
131 : }
132 : case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
133 : uint32 length;
134 0 : if (!input->ReadVarint32(&length)) return false;
135 0 : if (!input->Skip(length)) return false;
136 0 : return true;
137 : }
138 : case WireFormatLite::WIRETYPE_START_GROUP: {
139 0 : if (!input->IncrementRecursionDepth()) return false;
140 0 : if (!SkipMessage(input)) return false;
141 0 : input->DecrementRecursionDepth();
142 : // Check that the ending tag matched the starting tag.
143 0 : if (!input->LastTagWas(WireFormatLite::MakeTag(
144 : WireFormatLite::GetTagFieldNumber(tag),
145 0 : WireFormatLite::WIRETYPE_END_GROUP))) {
146 : return false;
147 : }
148 0 : return true;
149 : }
150 : case WireFormatLite::WIRETYPE_END_GROUP: {
151 : return false;
152 : }
153 : case WireFormatLite::WIRETYPE_FIXED32: {
154 : uint32 value;
155 0 : if (!input->ReadLittleEndian32(&value)) return false;
156 0 : return true;
157 : }
158 : default: {
159 : return false;
160 : }
161 : }
162 : }
163 :
164 0 : bool WireFormatLite::SkipField(
165 0 : io::CodedInputStream* input, uint32 tag, io::CodedOutputStream* output) {
166 0 : switch (WireFormatLite::GetTagWireType(tag)) {
167 : case WireFormatLite::WIRETYPE_VARINT: {
168 : uint64 value;
169 0 : if (!input->ReadVarint64(&value)) return false;
170 0 : output->WriteVarint32(tag);
171 0 : output->WriteVarint64(value);
172 : return true;
173 : }
174 : case WireFormatLite::WIRETYPE_FIXED64: {
175 : uint64 value;
176 0 : if (!input->ReadLittleEndian64(&value)) return false;
177 0 : output->WriteVarint32(tag);
178 0 : output->WriteLittleEndian64(value);
179 : return true;
180 : }
181 : case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
182 : uint32 length;
183 0 : if (!input->ReadVarint32(&length)) return false;
184 0 : output->WriteVarint32(tag);
185 0 : output->WriteVarint32(length);
186 : // TODO(mkilavuz): Provide API to prevent extra string copying.
187 : string temp;
188 0 : if (!input->ReadString(&temp, length)) return false;
189 : output->WriteString(temp);
190 : return true;
191 : }
192 : case WireFormatLite::WIRETYPE_START_GROUP: {
193 0 : output->WriteVarint32(tag);
194 0 : if (!input->IncrementRecursionDepth()) return false;
195 0 : if (!SkipMessage(input, output)) return false;
196 0 : input->DecrementRecursionDepth();
197 : // Check that the ending tag matched the starting tag.
198 0 : if (!input->LastTagWas(WireFormatLite::MakeTag(
199 : WireFormatLite::GetTagFieldNumber(tag),
200 0 : WireFormatLite::WIRETYPE_END_GROUP))) {
201 : return false;
202 : }
203 0 : return true;
204 : }
205 : case WireFormatLite::WIRETYPE_END_GROUP: {
206 : return false;
207 : }
208 : case WireFormatLite::WIRETYPE_FIXED32: {
209 : uint32 value;
210 0 : if (!input->ReadLittleEndian32(&value)) return false;
211 0 : output->WriteVarint32(tag);
212 0 : output->WriteLittleEndian32(value);
213 : return true;
214 : }
215 : default: {
216 : return false;
217 : }
218 : }
219 : }
220 :
221 0 : bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
222 : while (true) {
223 0 : uint32 tag = input->ReadTag();
224 0 : if (tag == 0) {
225 : // End of input. This is a valid place to end, so return true.
226 : return true;
227 : }
228 :
229 0 : WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
230 :
231 0 : if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
232 : // Must be the end of the message.
233 : return true;
234 : }
235 :
236 0 : if (!SkipField(input, tag)) return false;
237 : }
238 : }
239 :
240 0 : bool WireFormatLite::SkipMessage(io::CodedInputStream* input,
241 : io::CodedOutputStream* output) {
242 : while (true) {
243 0 : uint32 tag = input->ReadTag();
244 0 : if (tag == 0) {
245 : // End of input. This is a valid place to end, so return true.
246 : return true;
247 : }
248 :
249 0 : WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
250 :
251 0 : if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
252 0 : output->WriteVarint32(tag);
253 : // Must be the end of the message.
254 0 : return true;
255 : }
256 :
257 0 : if (!SkipField(input, tag, output)) return false;
258 : }
259 : }
260 :
261 0 : bool FieldSkipper::SkipField(
262 : io::CodedInputStream* input, uint32 tag) {
263 0 : return WireFormatLite::SkipField(input, tag);
264 : }
265 :
266 0 : bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
267 0 : return WireFormatLite::SkipMessage(input);
268 : }
269 :
270 0 : void FieldSkipper::SkipUnknownEnum(
271 : int /* field_number */, int /* value */) {
272 : // Nothing.
273 0 : }
274 :
275 0 : bool CodedOutputStreamFieldSkipper::SkipField(
276 : io::CodedInputStream* input, uint32 tag) {
277 0 : return WireFormatLite::SkipField(input, tag, unknown_fields_);
278 : }
279 :
280 0 : bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) {
281 0 : return WireFormatLite::SkipMessage(input, unknown_fields_);
282 : }
283 :
284 0 : void CodedOutputStreamFieldSkipper::SkipUnknownEnum(
285 : int field_number, int value) {
286 0 : unknown_fields_->WriteVarint32(field_number);
287 0 : unknown_fields_->WriteVarint64(value);
288 0 : }
289 :
290 0 : bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
291 : bool (*is_valid)(int),
292 : RepeatedField<int>* values) {
293 : uint32 length;
294 0 : if (!input->ReadVarint32(&length)) return false;
295 0 : io::CodedInputStream::Limit limit = input->PushLimit(length);
296 0 : while (input->BytesUntilLimit() > 0) {
297 : int value;
298 0 : if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
299 : int, WireFormatLite::TYPE_ENUM>(input, &value)) {
300 0 : return false;
301 : }
302 0 : if (is_valid == NULL || is_valid(value)) {
303 0 : values->Add(value);
304 : }
305 : }
306 0 : input->PopLimit(limit);
307 : return true;
308 : }
309 :
310 0 : bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
311 : io::CodedInputStream* input,
312 : int field_number,
313 : bool (*is_valid)(int),
314 : io::CodedOutputStream* unknown_fields_stream,
315 : RepeatedField<int>* values) {
316 : uint32 length;
317 0 : if (!input->ReadVarint32(&length)) return false;
318 0 : io::CodedInputStream::Limit limit = input->PushLimit(length);
319 0 : while (input->BytesUntilLimit() > 0) {
320 : int value;
321 0 : if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
322 : int, WireFormatLite::TYPE_ENUM>(input, &value)) {
323 0 : return false;
324 : }
325 0 : if (is_valid == NULL || is_valid(value)) {
326 0 : values->Add(value);
327 : } else {
328 : uint32 tag = WireFormatLite::MakeTag(field_number,
329 0 : WireFormatLite::WIRETYPE_VARINT);
330 0 : unknown_fields_stream->WriteVarint32(tag);
331 0 : unknown_fields_stream->WriteVarint32(value);
332 : }
333 : }
334 0 : input->PopLimit(limit);
335 : return true;
336 : }
337 :
338 8 : void WireFormatLite::WriteInt32(int field_number, int32 value,
339 : io::CodedOutputStream* output) {
340 : WriteTag(field_number, WIRETYPE_VARINT, output);
341 : WriteInt32NoTag(value, output);
342 8 : }
343 0 : void WireFormatLite::WriteInt64(int field_number, int64 value,
344 : io::CodedOutputStream* output) {
345 : WriteTag(field_number, WIRETYPE_VARINT, output);
346 : WriteInt64NoTag(value, output);
347 0 : }
348 0 : void WireFormatLite::WriteUInt32(int field_number, uint32 value,
349 : io::CodedOutputStream* output) {
350 : WriteTag(field_number, WIRETYPE_VARINT, output);
351 : WriteUInt32NoTag(value, output);
352 0 : }
353 0 : void WireFormatLite::WriteUInt64(int field_number, uint64 value,
354 : io::CodedOutputStream* output) {
355 : WriteTag(field_number, WIRETYPE_VARINT, output);
356 : WriteUInt64NoTag(value, output);
357 0 : }
358 0 : void WireFormatLite::WriteSInt32(int field_number, int32 value,
359 : io::CodedOutputStream* output) {
360 : WriteTag(field_number, WIRETYPE_VARINT, output);
361 : WriteSInt32NoTag(value, output);
362 0 : }
363 0 : void WireFormatLite::WriteSInt64(int field_number, int64 value,
364 : io::CodedOutputStream* output) {
365 : WriteTag(field_number, WIRETYPE_VARINT, output);
366 : WriteSInt64NoTag(value, output);
367 0 : }
368 0 : void WireFormatLite::WriteFixed32(int field_number, uint32 value,
369 : io::CodedOutputStream* output) {
370 : WriteTag(field_number, WIRETYPE_FIXED32, output);
371 : WriteFixed32NoTag(value, output);
372 0 : }
373 0 : void WireFormatLite::WriteFixed64(int field_number, uint64 value,
374 : io::CodedOutputStream* output) {
375 : WriteTag(field_number, WIRETYPE_FIXED64, output);
376 : WriteFixed64NoTag(value, output);
377 0 : }
378 0 : void WireFormatLite::WriteSFixed32(int field_number, int32 value,
379 : io::CodedOutputStream* output) {
380 : WriteTag(field_number, WIRETYPE_FIXED32, output);
381 : WriteSFixed32NoTag(value, output);
382 0 : }
383 0 : void WireFormatLite::WriteSFixed64(int field_number, int64 value,
384 : io::CodedOutputStream* output) {
385 : WriteTag(field_number, WIRETYPE_FIXED64, output);
386 : WriteSFixed64NoTag(value, output);
387 0 : }
388 0 : void WireFormatLite::WriteFloat(int field_number, float value,
389 : io::CodedOutputStream* output) {
390 : WriteTag(field_number, WIRETYPE_FIXED32, output);
391 : WriteFloatNoTag(value, output);
392 0 : }
393 0 : void WireFormatLite::WriteDouble(int field_number, double value,
394 : io::CodedOutputStream* output) {
395 : WriteTag(field_number, WIRETYPE_FIXED64, output);
396 : WriteDoubleNoTag(value, output);
397 0 : }
398 0 : void WireFormatLite::WriteBool(int field_number, bool value,
399 : io::CodedOutputStream* output) {
400 : WriteTag(field_number, WIRETYPE_VARINT, output);
401 : WriteBoolNoTag(value, output);
402 0 : }
403 0 : void WireFormatLite::WriteEnum(int field_number, int value,
404 : io::CodedOutputStream* output) {
405 : WriteTag(field_number, WIRETYPE_VARINT, output);
406 : WriteEnumNoTag(value, output);
407 0 : }
408 :
409 10 : void WireFormatLite::WriteString(int field_number, const string& value,
410 : io::CodedOutputStream* output) {
411 : // String is for UTF-8 text only
412 : WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
413 10 : GOOGLE_CHECK(value.size() <= kint32max);
414 10 : output->WriteVarint32(value.size());
415 : output->WriteString(value);
416 10 : }
417 20 : void WireFormatLite::WriteStringMaybeAliased(
418 : int field_number, const string& value,
419 : io::CodedOutputStream* output) {
420 : // String is for UTF-8 text only
421 : WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
422 20 : GOOGLE_CHECK(value.size() <= kint32max);
423 20 : output->WriteVarint32(value.size());
424 20 : output->WriteRawMaybeAliased(value.data(), value.size());
425 20 : }
426 0 : void WireFormatLite::WriteBytes(int field_number, const string& value,
427 : io::CodedOutputStream* output) {
428 : WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
429 0 : GOOGLE_CHECK(value.size() <= kint32max);
430 0 : output->WriteVarint32(value.size());
431 : output->WriteString(value);
432 0 : }
433 8 : void WireFormatLite::WriteBytesMaybeAliased(
434 : int field_number, const string& value,
435 : io::CodedOutputStream* output) {
436 : WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
437 8 : GOOGLE_CHECK(value.size() <= kint32max);
438 8 : output->WriteVarint32(value.size());
439 8 : output->WriteRawMaybeAliased(value.data(), value.size());
440 8 : }
441 :
442 :
443 0 : void WireFormatLite::WriteGroup(int field_number,
444 : const MessageLite& value,
445 : io::CodedOutputStream* output) {
446 : WriteTag(field_number, WIRETYPE_START_GROUP, output);
447 0 : value.SerializeWithCachedSizes(output);
448 : WriteTag(field_number, WIRETYPE_END_GROUP, output);
449 0 : }
450 :
451 4 : void WireFormatLite::WriteMessage(int field_number,
452 : const MessageLite& value,
453 : io::CodedOutputStream* output) {
454 : WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
455 4 : const int size = value.GetCachedSize();
456 4 : output->WriteVarint32(size);
457 4 : value.SerializeWithCachedSizes(output);
458 4 : }
459 :
460 0 : void WireFormatLite::WriteGroupMaybeToArray(int field_number,
461 : const MessageLite& value,
462 : io::CodedOutputStream* output) {
463 : WriteTag(field_number, WIRETYPE_START_GROUP, output);
464 0 : const int size = value.GetCachedSize();
465 0 : uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
466 0 : if (target != NULL) {
467 0 : uint8* end = value.SerializeWithCachedSizesToArray(target);
468 : GOOGLE_DCHECK_EQ(end - target, size);
469 : } else {
470 0 : value.SerializeWithCachedSizes(output);
471 : }
472 : WriteTag(field_number, WIRETYPE_END_GROUP, output);
473 0 : }
474 :
475 14 : void WireFormatLite::WriteMessageMaybeToArray(int field_number,
476 : const MessageLite& value,
477 : io::CodedOutputStream* output) {
478 : WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
479 14 : const int size = value.GetCachedSize();
480 14 : output->WriteVarint32(size);
481 14 : uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
482 14 : if (target != NULL) {
483 0 : uint8* end = value.SerializeWithCachedSizesToArray(target);
484 : GOOGLE_DCHECK_EQ(end - target, size);
485 : } else {
486 14 : value.SerializeWithCachedSizes(output);
487 : }
488 14 : }
489 :
490 : GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString(
491 : io::CodedInputStream* input, string* value);
492 : inline static bool ReadBytesToString(io::CodedInputStream* input,
493 : string* value) {
494 : uint32 length;
495 3065680 : return input->ReadVarint32(&length) &&
496 1532906 : input->InternalReadStringInline(value, length);
497 : }
498 :
499 1532899 : bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string* value) {
500 1532779 : return ReadBytesToString(input, value);
501 : }
502 :
503 0 : bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string** p) {
504 0 : if (*p == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
505 0 : *p = new ::std::string();
506 : }
507 0 : return ReadBytesToString(input, *p);
508 : }
509 :
510 479229 : bool WireFormatLite::VerifyUtf8String(const char* data,
511 : int size,
512 : Operation op,
513 : const char* field_name) {
514 479229 : if (!IsStructurallyValidUTF8(data, size)) {
515 0 : const char* operation_str = NULL;
516 0 : switch (op) {
517 : case PARSE:
518 0 : operation_str = "parsing";
519 0 : break;
520 : case SERIALIZE:
521 0 : operation_str = "serializing";
522 0 : break;
523 : // no default case: have the compiler warn if a case is not covered.
524 : }
525 0 : string quoted_field_name = "";
526 0 : if (field_name != NULL) {
527 0 : quoted_field_name = StringPrintf(" '%s'", field_name);
528 : }
529 : // no space below to avoid double space when the field name is missing.
530 0 : GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
531 0 : << "UTF-8 data when " << operation_str << " a protocol "
532 0 : << "buffer. Use the 'bytes' type if you intend to send raw "
533 0 : << "bytes. ";
534 0 : return false;
535 : }
536 : return true;
537 : }
538 :
539 : } // namespace internal
540 : } // namespace protobuf
541 : } // namespace google
|