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