1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
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.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::VarintSize32(kMessageSetItemStartTag) +
60 io::CodedOutputStream::VarintSize32(kMessageSetItemEndTag) +
61 io::CodedOutputStream::VarintSize32(kMessageSetTypeIdTag) +
62 io::CodedOutputStream::VarintSize32(kMessageSetMessageTag);
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
SkipMessage(io::CodedInputStream * input)156 bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
157 while(true) {
158 uint32 tag = input->ReadTag();
159 if (tag == 0) {
160 // End of input. This is a valid place to end, so return true.
161 return true;
162 }
163
164 WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
165
166 if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
167 // Must be the end of the message.
168 return true;
169 }
170
171 if (!SkipField(input, tag)) return false;
172 }
173 }
174
SkipField(io::CodedInputStream * input,uint32 tag)175 bool FieldSkipper::SkipField(
176 io::CodedInputStream* input, uint32 tag) {
177 return WireFormatLite::SkipField(input, tag);
178 }
179
SkipMessage(io::CodedInputStream * input)180 bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
181 return WireFormatLite::SkipMessage(input);
182 }
183
SkipUnknownEnum(int field_number,int value)184 void FieldSkipper::SkipUnknownEnum(
185 int field_number, int value) {
186 // Nothing.
187 }
188
ReadPackedEnumNoInline(io::CodedInputStream * input,bool (* is_valid)(int),RepeatedField<int> * values)189 bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
190 bool (*is_valid)(int),
191 RepeatedField<int>* values) {
192 uint32 length;
193 if (!input->ReadVarint32(&length)) return false;
194 io::CodedInputStream::Limit limit = input->PushLimit(length);
195 while (input->BytesUntilLimit() > 0) {
196 int value;
197 if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
198 int, WireFormatLite::TYPE_ENUM>(input, &value)) {
199 return false;
200 }
201 if (is_valid(value)) {
202 values->Add(value);
203 }
204 }
205 input->PopLimit(limit);
206 return true;
207 }
208
WriteInt32(int field_number,int32 value,io::CodedOutputStream * output)209 void WireFormatLite::WriteInt32(int field_number, int32 value,
210 io::CodedOutputStream* output) {
211 WriteTag(field_number, WIRETYPE_VARINT, output);
212 WriteInt32NoTag(value, output);
213 }
WriteInt64(int field_number,int64 value,io::CodedOutputStream * output)214 void WireFormatLite::WriteInt64(int field_number, int64 value,
215 io::CodedOutputStream* output) {
216 WriteTag(field_number, WIRETYPE_VARINT, output);
217 WriteInt64NoTag(value, output);
218 }
WriteUInt32(int field_number,uint32 value,io::CodedOutputStream * output)219 void WireFormatLite::WriteUInt32(int field_number, uint32 value,
220 io::CodedOutputStream* output) {
221 WriteTag(field_number, WIRETYPE_VARINT, output);
222 WriteUInt32NoTag(value, output);
223 }
WriteUInt64(int field_number,uint64 value,io::CodedOutputStream * output)224 void WireFormatLite::WriteUInt64(int field_number, uint64 value,
225 io::CodedOutputStream* output) {
226 WriteTag(field_number, WIRETYPE_VARINT, output);
227 WriteUInt64NoTag(value, output);
228 }
WriteSInt32(int field_number,int32 value,io::CodedOutputStream * output)229 void WireFormatLite::WriteSInt32(int field_number, int32 value,
230 io::CodedOutputStream* output) {
231 WriteTag(field_number, WIRETYPE_VARINT, output);
232 WriteSInt32NoTag(value, output);
233 }
WriteSInt64(int field_number,int64 value,io::CodedOutputStream * output)234 void WireFormatLite::WriteSInt64(int field_number, int64 value,
235 io::CodedOutputStream* output) {
236 WriteTag(field_number, WIRETYPE_VARINT, output);
237 WriteSInt64NoTag(value, output);
238 }
WriteFixed32(int field_number,uint32 value,io::CodedOutputStream * output)239 void WireFormatLite::WriteFixed32(int field_number, uint32 value,
240 io::CodedOutputStream* output) {
241 WriteTag(field_number, WIRETYPE_FIXED32, output);
242 WriteFixed32NoTag(value, output);
243 }
WriteFixed64(int field_number,uint64 value,io::CodedOutputStream * output)244 void WireFormatLite::WriteFixed64(int field_number, uint64 value,
245 io::CodedOutputStream* output) {
246 WriteTag(field_number, WIRETYPE_FIXED64, output);
247 WriteFixed64NoTag(value, output);
248 }
WriteSFixed32(int field_number,int32 value,io::CodedOutputStream * output)249 void WireFormatLite::WriteSFixed32(int field_number, int32 value,
250 io::CodedOutputStream* output) {
251 WriteTag(field_number, WIRETYPE_FIXED32, output);
252 WriteSFixed32NoTag(value, output);
253 }
WriteSFixed64(int field_number,int64 value,io::CodedOutputStream * output)254 void WireFormatLite::WriteSFixed64(int field_number, int64 value,
255 io::CodedOutputStream* output) {
256 WriteTag(field_number, WIRETYPE_FIXED64, output);
257 WriteSFixed64NoTag(value, output);
258 }
WriteFloat(int field_number,float value,io::CodedOutputStream * output)259 void WireFormatLite::WriteFloat(int field_number, float value,
260 io::CodedOutputStream* output) {
261 WriteTag(field_number, WIRETYPE_FIXED32, output);
262 WriteFloatNoTag(value, output);
263 }
WriteDouble(int field_number,double value,io::CodedOutputStream * output)264 void WireFormatLite::WriteDouble(int field_number, double value,
265 io::CodedOutputStream* output) {
266 WriteTag(field_number, WIRETYPE_FIXED64, output);
267 WriteDoubleNoTag(value, output);
268 }
WriteBool(int field_number,bool value,io::CodedOutputStream * output)269 void WireFormatLite::WriteBool(int field_number, bool value,
270 io::CodedOutputStream* output) {
271 WriteTag(field_number, WIRETYPE_VARINT, output);
272 WriteBoolNoTag(value, output);
273 }
WriteEnum(int field_number,int value,io::CodedOutputStream * output)274 void WireFormatLite::WriteEnum(int field_number, int value,
275 io::CodedOutputStream* output) {
276 WriteTag(field_number, WIRETYPE_VARINT, output);
277 WriteEnumNoTag(value, output);
278 }
279
WriteString(int field_number,const string & value,io::CodedOutputStream * output)280 void WireFormatLite::WriteString(int field_number, const string& value,
281 io::CodedOutputStream* output) {
282 // String is for UTF-8 text only
283 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
284 output->WriteVarint32(value.size());
285 output->WriteString(value);
286 }
WriteBytes(int field_number,const string & value,io::CodedOutputStream * output)287 void WireFormatLite::WriteBytes(int field_number, const string& value,
288 io::CodedOutputStream* output) {
289 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
290 output->WriteVarint32(value.size());
291 output->WriteString(value);
292 }
293
294
WriteGroup(int field_number,const MessageLite & value,io::CodedOutputStream * output)295 void WireFormatLite::WriteGroup(int field_number,
296 const MessageLite& value,
297 io::CodedOutputStream* output) {
298 WriteTag(field_number, WIRETYPE_START_GROUP, output);
299 value.SerializeWithCachedSizes(output);
300 WriteTag(field_number, WIRETYPE_END_GROUP, output);
301 }
302
WriteMessage(int field_number,const MessageLite & value,io::CodedOutputStream * output)303 void WireFormatLite::WriteMessage(int field_number,
304 const MessageLite& value,
305 io::CodedOutputStream* output) {
306 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
307 const int size = value.GetCachedSize();
308 output->WriteVarint32(size);
309 value.SerializeWithCachedSizes(output);
310 }
311
WriteGroupMaybeToArray(int field_number,const MessageLite & value,io::CodedOutputStream * output)312 void WireFormatLite::WriteGroupMaybeToArray(int field_number,
313 const MessageLite& value,
314 io::CodedOutputStream* output) {
315 WriteTag(field_number, WIRETYPE_START_GROUP, output);
316 const int size = value.GetCachedSize();
317 uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
318 if (target != NULL) {
319 uint8* end = value.SerializeWithCachedSizesToArray(target);
320 GOOGLE_DCHECK_EQ(end - target, size);
321 } else {
322 value.SerializeWithCachedSizes(output);
323 }
324 WriteTag(field_number, WIRETYPE_END_GROUP, output);
325 }
326
WriteMessageMaybeToArray(int field_number,const MessageLite & value,io::CodedOutputStream * output)327 void WireFormatLite::WriteMessageMaybeToArray(int field_number,
328 const MessageLite& value,
329 io::CodedOutputStream* output) {
330 WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
331 const int size = value.GetCachedSize();
332 output->WriteVarint32(size);
333 uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
334 if (target != NULL) {
335 uint8* end = value.SerializeWithCachedSizesToArray(target);
336 GOOGLE_DCHECK_EQ(end - target, size);
337 } else {
338 value.SerializeWithCachedSizes(output);
339 }
340 }
341
ReadString(io::CodedInputStream * input,string * value)342 bool WireFormatLite::ReadString(io::CodedInputStream* input,
343 string* value) {
344 // String is for UTF-8 text only
345 uint32 length;
346 if (!input->ReadVarint32(&length)) return false;
347 if (!input->InternalReadStringInline(value, length)) return false;
348 return true;
349 }
ReadBytes(io::CodedInputStream * input,string * value)350 bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
351 string* value) {
352 uint32 length;
353 if (!input->ReadVarint32(&length)) return false;
354 return input->InternalReadStringInline(value, length);
355 }
356
357 } // namespace internal
358 } // namespace protobuf
359 } // namespace google
360