blob: c5bbbf2ed9f965dfdecd98ff6457a688cdaf1bc5 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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 <stack>
36#include <string>
37#include <vector>
38
kenton@google.com80b1d622009-07-29 01:13:20 +000039#include <google/protobuf/wire_format.h>
temporal40ee5512008-07-10 02:12:20 +000040
41#include <google/protobuf/stubs/common.h>
jieluo@google.com4de8f552014-07-18 00:47:59 +000042#include <google/protobuf/stubs/stringprintf.h>
temporal40ee5512008-07-10 02:12:20 +000043#include <google/protobuf/descriptor.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000044#include <google/protobuf/wire_format_lite_inl.h>
temporal40ee5512008-07-10 02:12:20 +000045#include <google/protobuf/descriptor.pb.h>
46#include <google/protobuf/io/coded_stream.h>
47#include <google/protobuf/io/zero_copy_stream.h>
48#include <google/protobuf/io/zero_copy_stream_impl.h>
49#include <google/protobuf/unknown_field_set.h>
50
kenton@google.com80b1d622009-07-29 01:13:20 +000051
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000052
temporal40ee5512008-07-10 02:12:20 +000053namespace google {
54namespace protobuf {
55namespace internal {
56
57namespace {
58
59// This function turns out to be convenient when using some macros later.
60inline int GetEnumNumber(const EnumValueDescriptor* descriptor) {
61 return descriptor->number();
62}
63
temporal40ee5512008-07-10 02:12:20 +000064} // anonymous namespace
65
temporal40ee5512008-07-10 02:12:20 +000066// ===================================================================
67
kenton@google.com80b1d622009-07-29 01:13:20 +000068bool UnknownFieldSetFieldSkipper::SkipField(
69 io::CodedInputStream* input, uint32 tag) {
70 return WireFormat::SkipField(input, tag, unknown_fields_);
71}
72
73bool UnknownFieldSetFieldSkipper::SkipMessage(io::CodedInputStream* input) {
74 return WireFormat::SkipMessage(input, unknown_fields_);
75}
76
77void UnknownFieldSetFieldSkipper::SkipUnknownEnum(
78 int field_number, int value) {
79 unknown_fields_->AddVarint(field_number, value);
80}
81
temporal40ee5512008-07-10 02:12:20 +000082bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
83 UnknownFieldSet* unknown_fields) {
kenton@google.com80b1d622009-07-29 01:13:20 +000084 int number = WireFormatLite::GetTagFieldNumber(tag);
temporal40ee5512008-07-10 02:12:20 +000085
kenton@google.com80b1d622009-07-29 01:13:20 +000086 switch (WireFormatLite::GetTagWireType(tag)) {
87 case WireFormatLite::WIRETYPE_VARINT: {
temporal40ee5512008-07-10 02:12:20 +000088 uint64 value;
89 if (!input->ReadVarint64(&value)) return false;
kenton@google.comd37d46d2009-04-25 02:53:47 +000090 if (unknown_fields != NULL) unknown_fields->AddVarint(number, value);
temporal40ee5512008-07-10 02:12:20 +000091 return true;
92 }
kenton@google.com80b1d622009-07-29 01:13:20 +000093 case WireFormatLite::WIRETYPE_FIXED64: {
temporal40ee5512008-07-10 02:12:20 +000094 uint64 value;
95 if (!input->ReadLittleEndian64(&value)) return false;
kenton@google.comd37d46d2009-04-25 02:53:47 +000096 if (unknown_fields != NULL) unknown_fields->AddFixed64(number, value);
temporal40ee5512008-07-10 02:12:20 +000097 return true;
98 }
kenton@google.com80b1d622009-07-29 01:13:20 +000099 case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
temporal40ee5512008-07-10 02:12:20 +0000100 uint32 length;
101 if (!input->ReadVarint32(&length)) return false;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000102 if (unknown_fields == NULL) {
temporal40ee5512008-07-10 02:12:20 +0000103 if (!input->Skip(length)) return false;
104 } else {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000105 if (!input->ReadString(unknown_fields->AddLengthDelimited(number),
106 length)) {
temporal779f61c2008-08-13 03:15:00 +0000107 return false;
108 }
temporal40ee5512008-07-10 02:12:20 +0000109 }
110 return true;
111 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000112 case WireFormatLite::WIRETYPE_START_GROUP: {
temporal40ee5512008-07-10 02:12:20 +0000113 if (!input->IncrementRecursionDepth()) return false;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000114 if (!SkipMessage(input, (unknown_fields == NULL) ?
115 NULL : unknown_fields->AddGroup(number))) {
temporal40ee5512008-07-10 02:12:20 +0000116 return false;
117 }
118 input->DecrementRecursionDepth();
119 // Check that the ending tag matched the starting tag.
kenton@google.com80b1d622009-07-29 01:13:20 +0000120 if (!input->LastTagWas(WireFormatLite::MakeTag(
121 WireFormatLite::GetTagFieldNumber(tag),
122 WireFormatLite::WIRETYPE_END_GROUP))) {
temporal40ee5512008-07-10 02:12:20 +0000123 return false;
124 }
125 return true;
126 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000127 case WireFormatLite::WIRETYPE_END_GROUP: {
temporal40ee5512008-07-10 02:12:20 +0000128 return false;
129 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000130 case WireFormatLite::WIRETYPE_FIXED32: {
temporal40ee5512008-07-10 02:12:20 +0000131 uint32 value;
132 if (!input->ReadLittleEndian32(&value)) return false;
kenton@google.comd37d46d2009-04-25 02:53:47 +0000133 if (unknown_fields != NULL) unknown_fields->AddFixed32(number, value);
temporal40ee5512008-07-10 02:12:20 +0000134 return true;
135 }
136 default: {
137 return false;
138 }
139 }
140}
141
142bool WireFormat::SkipMessage(io::CodedInputStream* input,
143 UnknownFieldSet* unknown_fields) {
Jisi Liu885b6122015-02-28 14:51:22 -0800144 while (true) {
temporal40ee5512008-07-10 02:12:20 +0000145 uint32 tag = input->ReadTag();
146 if (tag == 0) {
147 // End of input. This is a valid place to end, so return true.
148 return true;
149 }
150
kenton@google.com80b1d622009-07-29 01:13:20 +0000151 WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
temporal40ee5512008-07-10 02:12:20 +0000152
kenton@google.com80b1d622009-07-29 01:13:20 +0000153 if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
temporal40ee5512008-07-10 02:12:20 +0000154 // Must be the end of the message.
155 return true;
156 }
157
158 if (!SkipField(input, tag, unknown_fields)) return false;
159 }
160}
161
Jisi Liu885b6122015-02-28 14:51:22 -0800162bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
163 uint32 field_number,
164 bool (*is_valid)(int),
165 UnknownFieldSet* unknown_fields,
166 RepeatedField<int>* values) {
167 uint32 length;
168 if (!input->ReadVarint32(&length)) return false;
169 io::CodedInputStream::Limit limit = input->PushLimit(length);
170 while (input->BytesUntilLimit() > 0) {
171 int value;
172 if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
173 int, WireFormatLite::TYPE_ENUM>(input, &value)) {
174 return false;
175 }
176 if (is_valid == NULL || is_valid(value)) {
177 values->Add(value);
178 } else {
179 unknown_fields->AddVarint(field_number, value);
180 }
181 }
182 input->PopLimit(limit);
183 return true;
184}
185
186
kenton@google.comd37d46d2009-04-25 02:53:47 +0000187void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
temporal40ee5512008-07-10 02:12:20 +0000188 io::CodedOutputStream* output) {
189 for (int i = 0; i < unknown_fields.field_count(); i++) {
190 const UnknownField& field = unknown_fields.field(i);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000191 switch (field.type()) {
192 case UnknownField::TYPE_VARINT:
kenton@google.com80b1d622009-07-29 01:13:20 +0000193 output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
194 WireFormatLite::WIRETYPE_VARINT));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000195 output->WriteVarint64(field.varint());
196 break;
197 case UnknownField::TYPE_FIXED32:
kenton@google.com80b1d622009-07-29 01:13:20 +0000198 output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
199 WireFormatLite::WIRETYPE_FIXED32));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000200 output->WriteLittleEndian32(field.fixed32());
201 break;
202 case UnknownField::TYPE_FIXED64:
kenton@google.com80b1d622009-07-29 01:13:20 +0000203 output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
204 WireFormatLite::WIRETYPE_FIXED64));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000205 output->WriteLittleEndian64(field.fixed64());
206 break;
207 case UnknownField::TYPE_LENGTH_DELIMITED:
kenton@google.com80b1d622009-07-29 01:13:20 +0000208 output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
209 WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000210 output->WriteVarint32(field.length_delimited().size());
jieluo@google.com4de8f552014-07-18 00:47:59 +0000211 output->WriteRawMaybeAliased(field.length_delimited().data(),
212 field.length_delimited().size());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000213 break;
214 case UnknownField::TYPE_GROUP:
kenton@google.com80b1d622009-07-29 01:13:20 +0000215 output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
216 WireFormatLite::WIRETYPE_START_GROUP));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000217 SerializeUnknownFields(field.group(), output);
kenton@google.com80b1d622009-07-29 01:13:20 +0000218 output->WriteVarint32(WireFormatLite::MakeTag(field.number(),
219 WireFormatLite::WIRETYPE_END_GROUP));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000220 break;
temporal40ee5512008-07-10 02:12:20 +0000221 }
temporal40ee5512008-07-10 02:12:20 +0000222 }
temporal40ee5512008-07-10 02:12:20 +0000223}
224
kenton@google.comd37d46d2009-04-25 02:53:47 +0000225uint8* WireFormat::SerializeUnknownFieldsToArray(
226 const UnknownFieldSet& unknown_fields,
227 uint8* target) {
228 for (int i = 0; i < unknown_fields.field_count(); i++) {
229 const UnknownField& field = unknown_fields.field(i);
230
231 switch (field.type()) {
232 case UnknownField::TYPE_VARINT:
kenton@google.com80b1d622009-07-29 01:13:20 +0000233 target = WireFormatLite::WriteInt64ToArray(
234 field.number(), field.varint(), target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000235 break;
236 case UnknownField::TYPE_FIXED32:
kenton@google.com80b1d622009-07-29 01:13:20 +0000237 target = WireFormatLite::WriteFixed32ToArray(
238 field.number(), field.fixed32(), target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000239 break;
240 case UnknownField::TYPE_FIXED64:
kenton@google.com80b1d622009-07-29 01:13:20 +0000241 target = WireFormatLite::WriteFixed64ToArray(
242 field.number(), field.fixed64(), target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000243 break;
244 case UnknownField::TYPE_LENGTH_DELIMITED:
kenton@google.com80b1d622009-07-29 01:13:20 +0000245 target = WireFormatLite::WriteBytesToArray(
246 field.number(), field.length_delimited(), target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000247 break;
248 case UnknownField::TYPE_GROUP:
kenton@google.com80b1d622009-07-29 01:13:20 +0000249 target = WireFormatLite::WriteTagToArray(
250 field.number(), WireFormatLite::WIRETYPE_START_GROUP, target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000251 target = SerializeUnknownFieldsToArray(field.group(), target);
kenton@google.com80b1d622009-07-29 01:13:20 +0000252 target = WireFormatLite::WriteTagToArray(
253 field.number(), WireFormatLite::WIRETYPE_END_GROUP, target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000254 break;
255 }
256 }
257 return target;
258}
259
260void WireFormat::SerializeUnknownMessageSetItems(
temporal40ee5512008-07-10 02:12:20 +0000261 const UnknownFieldSet& unknown_fields,
262 io::CodedOutputStream* output) {
263 for (int i = 0; i < unknown_fields.field_count(); i++) {
264 const UnknownField& field = unknown_fields.field(i);
temporal40ee5512008-07-10 02:12:20 +0000265 // The only unknown fields that are allowed to exist in a MessageSet are
266 // messages, which are length-delimited.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000267 if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
temporal40ee5512008-07-10 02:12:20 +0000268 // Start group.
kenton@google.com80b1d622009-07-29 01:13:20 +0000269 output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
temporal40ee5512008-07-10 02:12:20 +0000270
271 // Write type ID.
kenton@google.com80b1d622009-07-29 01:13:20 +0000272 output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000273 output->WriteVarint32(field.number());
temporal40ee5512008-07-10 02:12:20 +0000274
275 // Write message.
kenton@google.com80b1d622009-07-29 01:13:20 +0000276 output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000277 field.SerializeLengthDelimitedNoTag(output);
temporal40ee5512008-07-10 02:12:20 +0000278
279 // End group.
kenton@google.com80b1d622009-07-29 01:13:20 +0000280 output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
temporal40ee5512008-07-10 02:12:20 +0000281 }
kenton@google.comd37d46d2009-04-25 02:53:47 +0000282 }
283}
284
285uint8* WireFormat::SerializeUnknownMessageSetItemsToArray(
286 const UnknownFieldSet& unknown_fields,
287 uint8* target) {
288 for (int i = 0; i < unknown_fields.field_count(); i++) {
289 const UnknownField& field = unknown_fields.field(i);
290
291 // The only unknown fields that are allowed to exist in a MessageSet are
292 // messages, which are length-delimited.
293 if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000294 // Start group.
kenton@google.com80b1d622009-07-29 01:13:20 +0000295 target = io::CodedOutputStream::WriteTagToArray(
296 WireFormatLite::kMessageSetItemStartTag, target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000297
298 // Write type ID.
kenton@google.com80b1d622009-07-29 01:13:20 +0000299 target = io::CodedOutputStream::WriteTagToArray(
300 WireFormatLite::kMessageSetTypeIdTag, target);
301 target = io::CodedOutputStream::WriteVarint32ToArray(
302 field.number(), target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000303
304 // Write message.
kenton@google.com80b1d622009-07-29 01:13:20 +0000305 target = io::CodedOutputStream::WriteTagToArray(
306 WireFormatLite::kMessageSetMessageTag, target);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000307 target = field.SerializeLengthDelimitedNoTagToArray(target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000308
309 // End group.
kenton@google.com80b1d622009-07-29 01:13:20 +0000310 target = io::CodedOutputStream::WriteTagToArray(
311 WireFormatLite::kMessageSetItemEndTag, target);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000312 }
temporal40ee5512008-07-10 02:12:20 +0000313 }
314
kenton@google.comd37d46d2009-04-25 02:53:47 +0000315 return target;
temporal40ee5512008-07-10 02:12:20 +0000316}
317
318int WireFormat::ComputeUnknownFieldsSize(
319 const UnknownFieldSet& unknown_fields) {
320 int size = 0;
321 for (int i = 0; i < unknown_fields.field_count(); i++) {
322 const UnknownField& field = unknown_fields.field(i);
323
kenton@google.comd37d46d2009-04-25 02:53:47 +0000324 switch (field.type()) {
325 case UnknownField::TYPE_VARINT:
326 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000327 WireFormatLite::MakeTag(field.number(),
328 WireFormatLite::WIRETYPE_VARINT));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000329 size += io::CodedOutputStream::VarintSize64(field.varint());
330 break;
331 case UnknownField::TYPE_FIXED32:
332 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000333 WireFormatLite::MakeTag(field.number(),
334 WireFormatLite::WIRETYPE_FIXED32));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000335 size += sizeof(int32);
336 break;
337 case UnknownField::TYPE_FIXED64:
338 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000339 WireFormatLite::MakeTag(field.number(),
340 WireFormatLite::WIRETYPE_FIXED64));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000341 size += sizeof(int64);
342 break;
343 case UnknownField::TYPE_LENGTH_DELIMITED:
344 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000345 WireFormatLite::MakeTag(field.number(),
346 WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000347 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000348 field.length_delimited().size());
kenton@google.comd37d46d2009-04-25 02:53:47 +0000349 size += field.length_delimited().size();
350 break;
351 case UnknownField::TYPE_GROUP:
352 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000353 WireFormatLite::MakeTag(field.number(),
354 WireFormatLite::WIRETYPE_START_GROUP));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000355 size += ComputeUnknownFieldsSize(field.group());
356 size += io::CodedOutputStream::VarintSize32(
kenton@google.com80b1d622009-07-29 01:13:20 +0000357 WireFormatLite::MakeTag(field.number(),
358 WireFormatLite::WIRETYPE_END_GROUP));
kenton@google.comd37d46d2009-04-25 02:53:47 +0000359 break;
temporal40ee5512008-07-10 02:12:20 +0000360 }
361 }
362
363 return size;
364}
365
366int WireFormat::ComputeUnknownMessageSetItemsSize(
367 const UnknownFieldSet& unknown_fields) {
368 int size = 0;
369 for (int i = 0; i < unknown_fields.field_count(); i++) {
370 const UnknownField& field = unknown_fields.field(i);
371
372 // The only unknown fields that are allowed to exist in a MessageSet are
373 // messages, which are length-delimited.
kenton@google.comd37d46d2009-04-25 02:53:47 +0000374 if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000375 size += WireFormatLite::kMessageSetItemTagsSize;
temporal40ee5512008-07-10 02:12:20 +0000376 size += io::CodedOutputStream::VarintSize32(field.number());
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000377
378 int field_size = field.GetLengthDelimitedSize();
379 size += io::CodedOutputStream::VarintSize32(field_size);
380 size += field_size;
temporal40ee5512008-07-10 02:12:20 +0000381 }
382 }
383
384 return size;
385}
386
387// ===================================================================
388
temporal779f61c2008-08-13 03:15:00 +0000389bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input,
390 Message* message) {
391 const Descriptor* descriptor = message->GetDescriptor();
392 const Reflection* message_reflection = message->GetReflection();
393
temporal40ee5512008-07-10 02:12:20 +0000394 while(true) {
395 uint32 tag = input->ReadTag();
396 if (tag == 0) {
397 // End of input. This is a valid place to end, so return true.
398 return true;
399 }
400
kenton@google.com80b1d622009-07-29 01:13:20 +0000401 if (WireFormatLite::GetTagWireType(tag) ==
402 WireFormatLite::WIRETYPE_END_GROUP) {
temporal40ee5512008-07-10 02:12:20 +0000403 // Must be the end of the message.
404 return true;
405 }
406
407 const FieldDescriptor* field = NULL;
408
409 if (descriptor != NULL) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000410 int field_number = WireFormatLite::GetTagFieldNumber(tag);
temporal40ee5512008-07-10 02:12:20 +0000411 field = descriptor->FindFieldByNumber(field_number);
412
413 // If that failed, check if the field is an extension.
414 if (field == NULL && descriptor->IsExtensionNumber(field_number)) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000415 if (input->GetExtensionPool() == NULL) {
416 field = message_reflection->FindKnownExtensionByNumber(field_number);
417 } else {
418 field = input->GetExtensionPool()
419 ->FindExtensionByNumber(descriptor, field_number);
420 }
temporal40ee5512008-07-10 02:12:20 +0000421 }
422
423 // If that failed, but we're a MessageSet, and this is the tag for a
424 // MessageSet item, then parse that.
425 if (field == NULL &&
426 descriptor->options().message_set_wire_format() &&
kenton@google.com80b1d622009-07-29 01:13:20 +0000427 tag == WireFormatLite::kMessageSetItemStartTag) {
temporal779f61c2008-08-13 03:15:00 +0000428 if (!ParseAndMergeMessageSetItem(input, message)) {
temporal40ee5512008-07-10 02:12:20 +0000429 return false;
430 }
431 continue; // Skip ParseAndMergeField(); already taken care of.
432 }
433 }
434
temporal779f61c2008-08-13 03:15:00 +0000435 if (!ParseAndMergeField(tag, field, message, input)) {
temporal40ee5512008-07-10 02:12:20 +0000436 return false;
437 }
438 }
439}
440
jieluo@google.com4de8f552014-07-18 00:47:59 +0000441bool WireFormat::SkipMessageSetField(io::CodedInputStream* input,
442 uint32 field_number,
443 UnknownFieldSet* unknown_fields) {
444 uint32 length;
445 if (!input->ReadVarint32(&length)) return false;
446 return input->ReadString(
447 unknown_fields->AddLengthDelimited(field_number), length);
448}
449
450bool WireFormat::ParseAndMergeMessageSetField(uint32 field_number,
451 const FieldDescriptor* field,
452 Message* message,
453 io::CodedInputStream* input) {
454 const Reflection* message_reflection = message->GetReflection();
455 if (field == NULL) {
456 // We store unknown MessageSet extensions as groups.
457 return SkipMessageSetField(
458 input, field_number, message_reflection->MutableUnknownFields(message));
459 } else if (field->is_repeated() ||
460 field->type() != FieldDescriptor::TYPE_MESSAGE) {
461 // This shouldn't happen as we only allow optional message extensions to
462 // MessageSet.
463 GOOGLE_LOG(ERROR) << "Extensions of MessageSets must be optional messages.";
464 return false;
465 } else {
466 Message* sub_message = message_reflection->MutableMessage(
467 message, field, input->GetExtensionFactory());
468 return WireFormatLite::ReadMessage(input, sub_message);
469 }
470}
471
temporal40ee5512008-07-10 02:12:20 +0000472bool WireFormat::ParseAndMergeField(
473 uint32 tag,
474 const FieldDescriptor* field, // May be NULL for unknown
temporal779f61c2008-08-13 03:15:00 +0000475 Message* message,
temporal40ee5512008-07-10 02:12:20 +0000476 io::CodedInputStream* input) {
temporal779f61c2008-08-13 03:15:00 +0000477 const Reflection* message_reflection = message->GetReflection();
478
kenton@google.comfccb1462009-12-18 02:11:36 +0000479 enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
480
481 if (field == NULL) {
482 value_format = UNKNOWN;
483 } else if (WireFormatLite::GetTagWireType(tag) ==
484 WireTypeForFieldType(field->type())) {
485 value_format = NORMAL_FORMAT;
486 } else if (field->is_packable() &&
487 WireFormatLite::GetTagWireType(tag) ==
488 WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
489 value_format = PACKED_FORMAT;
490 } else {
491 // We don't recognize this field. Either the field number is unknown
492 // or the wire type doesn't match. Put it in our unknown field set.
493 value_format = UNKNOWN;
temporal40ee5512008-07-10 02:12:20 +0000494 }
495
kenton@google.comfccb1462009-12-18 02:11:36 +0000496 if (value_format == UNKNOWN) {
497 return SkipField(input, tag,
498 message_reflection->MutableUnknownFields(message));
499 } else if (value_format == PACKED_FORMAT) {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000500 uint32 length;
501 if (!input->ReadVarint32(&length)) return false;
502 io::CodedInputStream::Limit limit = input->PushLimit(length);
503
504 switch (field->type()) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000505#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
kenton@google.com80b1d622009-07-29 01:13:20 +0000506 case FieldDescriptor::TYPE_##TYPE: { \
507 while (input->BytesUntilLimit() > 0) { \
508 CPPTYPE value; \
kenton@google.comfccb1462009-12-18 02:11:36 +0000509 if (!WireFormatLite::ReadPrimitive< \
510 CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
511 return false; \
kenton@google.com80b1d622009-07-29 01:13:20 +0000512 message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
513 } \
514 break; \
kenton@google.com2d6daa72009-01-22 01:27:00 +0000515 }
516
kenton@google.comfccb1462009-12-18 02:11:36 +0000517 HANDLE_PACKED_TYPE( INT32, int32, Int32)
518 HANDLE_PACKED_TYPE( INT64, int64, Int64)
519 HANDLE_PACKED_TYPE(SINT32, int32, Int32)
520 HANDLE_PACKED_TYPE(SINT64, int64, Int64)
521 HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
522 HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
kenton@google.com2d6daa72009-01-22 01:27:00 +0000523
kenton@google.comfccb1462009-12-18 02:11:36 +0000524 HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32)
525 HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64)
526 HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
527 HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
kenton@google.com2d6daa72009-01-22 01:27:00 +0000528
kenton@google.comfccb1462009-12-18 02:11:36 +0000529 HANDLE_PACKED_TYPE(FLOAT , float , Float )
530 HANDLE_PACKED_TYPE(DOUBLE, double, Double)
kenton@google.com2d6daa72009-01-22 01:27:00 +0000531
kenton@google.comfccb1462009-12-18 02:11:36 +0000532 HANDLE_PACKED_TYPE(BOOL, bool, Bool)
kenton@google.com2d6daa72009-01-22 01:27:00 +0000533#undef HANDLE_PACKED_TYPE
534
535 case FieldDescriptor::TYPE_ENUM: {
536 while (input->BytesUntilLimit() > 0) {
537 int value;
kenton@google.comfccb1462009-12-18 02:11:36 +0000538 if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
539 input, &value)) return false;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800540 if (message->GetDescriptor()->file()->syntax() ==
541 FileDescriptor::SYNTAX_PROTO3) {
542 message_reflection->AddEnumValue(message, field, value);
543 } else {
544 const EnumValueDescriptor* enum_value =
545 field->enum_type()->FindValueByNumber(value);
546 if (enum_value != NULL) {
547 message_reflection->AddEnum(message, field, enum_value);
Jisi Liu885b6122015-02-28 14:51:22 -0800548 } else {
549 // The enum value is not one of the known values. Add it to the
550 // UnknownFieldSet.
551 int64 sign_extended_value = static_cast<int64>(value);
552 message_reflection->MutableUnknownFields(message)
553 ->AddVarint(
554 WireFormatLite::GetTagFieldNumber(tag),
555 sign_extended_value);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800556 }
kenton@google.com2d6daa72009-01-22 01:27:00 +0000557 }
558 }
559
560 break;
561 }
562
563 case FieldDescriptor::TYPE_STRING:
564 case FieldDescriptor::TYPE_GROUP:
565 case FieldDescriptor::TYPE_MESSAGE:
566 case FieldDescriptor::TYPE_BYTES:
567 // Can't have packed fields of these types: these should be caught by
568 // the protocol compiler.
569 return false;
570 break;
temporal40ee5512008-07-10 02:12:20 +0000571 }
572
kenton@google.com2d6daa72009-01-22 01:27:00 +0000573 input->PopLimit(limit);
574 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000575 // Non-packed value (value_format == NORMAL_FORMAT)
kenton@google.com2d6daa72009-01-22 01:27:00 +0000576 switch (field->type()) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000577#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
kenton@google.com80b1d622009-07-29 01:13:20 +0000578 case FieldDescriptor::TYPE_##TYPE: { \
579 CPPTYPE value; \
kenton@google.comfccb1462009-12-18 02:11:36 +0000580 if (!WireFormatLite::ReadPrimitive< \
581 CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
582 return false; \
kenton@google.com80b1d622009-07-29 01:13:20 +0000583 if (field->is_repeated()) { \
584 message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
585 } else { \
586 message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
587 } \
588 break; \
kenton@google.com2d6daa72009-01-22 01:27:00 +0000589 }
temporal40ee5512008-07-10 02:12:20 +0000590
kenton@google.comfccb1462009-12-18 02:11:36 +0000591 HANDLE_TYPE( INT32, int32, Int32)
592 HANDLE_TYPE( INT64, int64, Int64)
593 HANDLE_TYPE(SINT32, int32, Int32)
594 HANDLE_TYPE(SINT64, int64, Int64)
595 HANDLE_TYPE(UINT32, uint32, UInt32)
596 HANDLE_TYPE(UINT64, uint64, UInt64)
temporal40ee5512008-07-10 02:12:20 +0000597
kenton@google.comfccb1462009-12-18 02:11:36 +0000598 HANDLE_TYPE( FIXED32, uint32, UInt32)
599 HANDLE_TYPE( FIXED64, uint64, UInt64)
600 HANDLE_TYPE(SFIXED32, int32, Int32)
601 HANDLE_TYPE(SFIXED64, int64, Int64)
temporal40ee5512008-07-10 02:12:20 +0000602
kenton@google.comfccb1462009-12-18 02:11:36 +0000603 HANDLE_TYPE(FLOAT , float , Float )
604 HANDLE_TYPE(DOUBLE, double, Double)
temporal40ee5512008-07-10 02:12:20 +0000605
kenton@google.comfccb1462009-12-18 02:11:36 +0000606 HANDLE_TYPE(BOOL, bool, Bool)
temporal40ee5512008-07-10 02:12:20 +0000607#undef HANDLE_TYPE
608
kenton@google.com2d6daa72009-01-22 01:27:00 +0000609 case FieldDescriptor::TYPE_ENUM: {
610 int value;
kenton@google.comfccb1462009-12-18 02:11:36 +0000611 if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
612 input, &value)) return false;
Feng Xiao6ef984a2014-11-10 17:34:54 -0800613 if (message->GetDescriptor()->file()->syntax() ==
614 FileDescriptor::SYNTAX_PROTO3) {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000615 if (field->is_repeated()) {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800616 message_reflection->AddEnumValue(message, field, value);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000617 } else {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800618 message_reflection->SetEnumValue(message, field, value);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000619 }
temporal40ee5512008-07-10 02:12:20 +0000620 } else {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800621 const EnumValueDescriptor* enum_value =
622 field->enum_type()->FindValueByNumber(value);
623 if (enum_value != NULL) {
624 if (field->is_repeated()) {
625 message_reflection->AddEnum(message, field, enum_value);
626 } else {
627 message_reflection->SetEnum(message, field, enum_value);
628 }
629 } else {
630 // The enum value is not one of the known values. Add it to the
631 // UnknownFieldSet.
632 int64 sign_extended_value = static_cast<int64>(value);
633 message_reflection->MutableUnknownFields(message)
634 ->AddVarint(
635 WireFormatLite::GetTagFieldNumber(tag),
636 sign_extended_value);
637 }
temporal40ee5512008-07-10 02:12:20 +0000638 }
kenton@google.com2d6daa72009-01-22 01:27:00 +0000639 break;
temporal40ee5512008-07-10 02:12:20 +0000640 }
641
kenton@google.comfccb1462009-12-18 02:11:36 +0000642 // Handle strings separately so that we can optimize the ctype=CORD case.
643 case FieldDescriptor::TYPE_STRING: {
644 string value;
645 if (!WireFormatLite::ReadString(input, &value)) return false;
jieluo@google.com4de8f552014-07-18 00:47:59 +0000646 VerifyUTF8StringNamedField(value.data(), value.length(), PARSE,
647 field->name().c_str());
kenton@google.comfccb1462009-12-18 02:11:36 +0000648 if (field->is_repeated()) {
649 message_reflection->AddString(message, field, value);
650 } else {
651 message_reflection->SetString(message, field, value);
652 }
653 break;
654 }
655
656 case FieldDescriptor::TYPE_BYTES: {
657 string value;
658 if (!WireFormatLite::ReadBytes(input, &value)) return false;
659 if (field->is_repeated()) {
660 message_reflection->AddString(message, field, value);
661 } else {
662 message_reflection->SetString(message, field, value);
663 }
664 break;
665 }
temporal40ee5512008-07-10 02:12:20 +0000666
kenton@google.com2d6daa72009-01-22 01:27:00 +0000667 case FieldDescriptor::TYPE_GROUP: {
668 Message* sub_message;
669 if (field->is_repeated()) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000670 sub_message = message_reflection->AddMessage(
671 message, field, input->GetExtensionFactory());
kenton@google.com2d6daa72009-01-22 01:27:00 +0000672 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000673 sub_message = message_reflection->MutableMessage(
674 message, field, input->GetExtensionFactory());
kenton@google.com2d6daa72009-01-22 01:27:00 +0000675 }
676
kenton@google.com80b1d622009-07-29 01:13:20 +0000677 if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
678 input, sub_message))
kenton@google.com2d6daa72009-01-22 01:27:00 +0000679 return false;
680 break;
temporal40ee5512008-07-10 02:12:20 +0000681 }
682
kenton@google.com2d6daa72009-01-22 01:27:00 +0000683 case FieldDescriptor::TYPE_MESSAGE: {
684 Message* sub_message;
685 if (field->is_repeated()) {
kenton@google.comfccb1462009-12-18 02:11:36 +0000686 sub_message = message_reflection->AddMessage(
687 message, field, input->GetExtensionFactory());
kenton@google.com2d6daa72009-01-22 01:27:00 +0000688 } else {
kenton@google.comfccb1462009-12-18 02:11:36 +0000689 sub_message = message_reflection->MutableMessage(
690 message, field, input->GetExtensionFactory());
kenton@google.com2d6daa72009-01-22 01:27:00 +0000691 }
692
kenton@google.com80b1d622009-07-29 01:13:20 +0000693 if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
kenton@google.com2d6daa72009-01-22 01:27:00 +0000694 break;
695 }
temporal40ee5512008-07-10 02:12:20 +0000696 }
697 }
698
699 return true;
700}
701
702bool WireFormat::ParseAndMergeMessageSetItem(
703 io::CodedInputStream* input,
temporal779f61c2008-08-13 03:15:00 +0000704 Message* message) {
705 const Reflection* message_reflection = message->GetReflection();
706
temporal40ee5512008-07-10 02:12:20 +0000707 // This method parses a group which should contain two fields:
708 // required int32 type_id = 2;
709 // required data message = 3;
710
jieluo@google.com4de8f552014-07-18 00:47:59 +0000711 uint32 last_type_id = 0;
temporal40ee5512008-07-10 02:12:20 +0000712
713 // Once we see a type_id, we'll look up the FieldDescriptor for the
714 // extension.
715 const FieldDescriptor* field = NULL;
716
717 // If we see message data before the type_id, we'll append it to this so
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000718 // we can parse it later.
temporal40ee5512008-07-10 02:12:20 +0000719 string message_data;
720
721 while (true) {
722 uint32 tag = input->ReadTag();
723 if (tag == 0) return false;
724
725 switch (tag) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000726 case WireFormatLite::kMessageSetTypeIdTag: {
temporal40ee5512008-07-10 02:12:20 +0000727 uint32 type_id;
728 if (!input->ReadVarint32(&type_id)) return false;
jieluo@google.com4de8f552014-07-18 00:47:59 +0000729 last_type_id = type_id;
temporal40ee5512008-07-10 02:12:20 +0000730 field = message_reflection->FindKnownExtensionByNumber(type_id);
731
732 if (!message_data.empty()) {
733 // We saw some message data before the type_id. Have to parse it
734 // now.
735 io::ArrayInputStream raw_input(message_data.data(),
736 message_data.size());
737 io::CodedInputStream sub_input(&raw_input);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000738 if (!ParseAndMergeMessageSetField(last_type_id, field, message,
739 &sub_input)) {
temporal40ee5512008-07-10 02:12:20 +0000740 return false;
741 }
742 message_data.clear();
743 }
744
745 break;
746 }
747
kenton@google.com80b1d622009-07-29 01:13:20 +0000748 case WireFormatLite::kMessageSetMessageTag: {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000749 if (last_type_id == 0) {
temporal40ee5512008-07-10 02:12:20 +0000750 // We haven't seen a type_id yet. Append this data to message_data.
751 string temp;
752 uint32 length;
753 if (!input->ReadVarint32(&length)) return false;
754 if (!input->ReadString(&temp, length)) return false;
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000755 io::StringOutputStream output_stream(&message_data);
756 io::CodedOutputStream coded_output(&output_stream);
757 coded_output.WriteVarint32(length);
758 coded_output.WriteString(temp);
temporal40ee5512008-07-10 02:12:20 +0000759 } else {
760 // Already saw type_id, so we can parse this directly.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000761 if (!ParseAndMergeMessageSetField(last_type_id, field, message,
762 input)) {
temporal40ee5512008-07-10 02:12:20 +0000763 return false;
764 }
765 }
766
767 break;
768 }
769
kenton@google.com80b1d622009-07-29 01:13:20 +0000770 case WireFormatLite::kMessageSetItemEndTag: {
temporal40ee5512008-07-10 02:12:20 +0000771 return true;
772 }
773
774 default: {
775 if (!SkipField(input, tag, NULL)) return false;
776 }
777 }
778 }
779}
780
781// ===================================================================
782
kenton@google.comd37d46d2009-04-25 02:53:47 +0000783void WireFormat::SerializeWithCachedSizes(
temporal779f61c2008-08-13 03:15:00 +0000784 const Message& message,
temporal40ee5512008-07-10 02:12:20 +0000785 int size, io::CodedOutputStream* output) {
temporal779f61c2008-08-13 03:15:00 +0000786 const Descriptor* descriptor = message.GetDescriptor();
787 const Reflection* message_reflection = message.GetReflection();
temporal40ee5512008-07-10 02:12:20 +0000788 int expected_endpoint = output->ByteCount() + size;
789
790 vector<const FieldDescriptor*> fields;
temporal779f61c2008-08-13 03:15:00 +0000791 message_reflection->ListFields(message, &fields);
temporal40ee5512008-07-10 02:12:20 +0000792 for (int i = 0; i < fields.size(); i++) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000793 SerializeFieldWithCachedSizes(fields[i], message, output);
temporal40ee5512008-07-10 02:12:20 +0000794 }
795
796 if (descriptor->options().message_set_wire_format()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000797 SerializeUnknownMessageSetItems(
798 message_reflection->GetUnknownFields(message), output);
temporal40ee5512008-07-10 02:12:20 +0000799 } else {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000800 SerializeUnknownFields(
801 message_reflection->GetUnknownFields(message), output);
temporal40ee5512008-07-10 02:12:20 +0000802 }
803
804 GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint)
805 << ": Protocol message serialized to a size different from what was "
806 "originally expected. Perhaps it was modified by another thread "
807 "during serialization?";
temporal40ee5512008-07-10 02:12:20 +0000808}
809
kenton@google.comd37d46d2009-04-25 02:53:47 +0000810void WireFormat::SerializeFieldWithCachedSizes(
temporal40ee5512008-07-10 02:12:20 +0000811 const FieldDescriptor* field,
temporal779f61c2008-08-13 03:15:00 +0000812 const Message& message,
temporal40ee5512008-07-10 02:12:20 +0000813 io::CodedOutputStream* output) {
temporal779f61c2008-08-13 03:15:00 +0000814 const Reflection* message_reflection = message.GetReflection();
815
temporal40ee5512008-07-10 02:12:20 +0000816 if (field->is_extension() &&
817 field->containing_type()->options().message_set_wire_format() &&
818 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
819 !field->is_repeated()) {
kenton@google.comd37d46d2009-04-25 02:53:47 +0000820 SerializeMessageSetItemWithCachedSizes(field, message, output);
821 return;
temporal40ee5512008-07-10 02:12:20 +0000822 }
823
824 int count = 0;
825
826 if (field->is_repeated()) {
temporal779f61c2008-08-13 03:15:00 +0000827 count = message_reflection->FieldSize(message, field);
828 } else if (message_reflection->HasField(message, field)) {
temporal40ee5512008-07-10 02:12:20 +0000829 count = 1;
830 }
831
kenton@google.com2d6daa72009-01-22 01:27:00 +0000832 const bool is_packed = field->options().packed();
833 if (is_packed && count > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000834 WireFormatLite::WriteTag(field->number(),
835 WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000836 const int data_size = FieldDataOnlyByteSize(field, message);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000837 output->WriteVarint32(data_size);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000838 }
839
temporal40ee5512008-07-10 02:12:20 +0000840 for (int j = 0; j < count; j++) {
841 switch (field->type()) {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000842#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \
843 case FieldDescriptor::TYPE_##TYPE: { \
844 const CPPTYPE value = field->is_repeated() ? \
845 message_reflection->GetRepeated##CPPTYPE_METHOD( \
846 message, field, j) : \
847 message_reflection->Get##CPPTYPE_METHOD( \
848 message, field); \
849 if (is_packed) { \
kenton@google.com80b1d622009-07-29 01:13:20 +0000850 WireFormatLite::Write##TYPE_METHOD##NoTag(value, output); \
kenton@google.com2d6daa72009-01-22 01:27:00 +0000851 } else { \
kenton@google.com80b1d622009-07-29 01:13:20 +0000852 WireFormatLite::Write##TYPE_METHOD(field->number(), value, output); \
kenton@google.com2d6daa72009-01-22 01:27:00 +0000853 } \
854 break; \
855 }
856
857 HANDLE_PRIMITIVE_TYPE( INT32, int32, Int32, Int32)
858 HANDLE_PRIMITIVE_TYPE( INT64, int64, Int64, Int64)
859 HANDLE_PRIMITIVE_TYPE(SINT32, int32, SInt32, Int32)
860 HANDLE_PRIMITIVE_TYPE(SINT64, int64, SInt64, Int64)
861 HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32)
862 HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64)
863
864 HANDLE_PRIMITIVE_TYPE( FIXED32, uint32, Fixed32, UInt32)
865 HANDLE_PRIMITIVE_TYPE( FIXED64, uint64, Fixed64, UInt64)
866 HANDLE_PRIMITIVE_TYPE(SFIXED32, int32, SFixed32, Int32)
867 HANDLE_PRIMITIVE_TYPE(SFIXED64, int64, SFixed64, Int64)
868
869 HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float )
870 HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double)
871
872 HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool)
873#undef HANDLE_PRIMITIVE_TYPE
874
temporal40ee5512008-07-10 02:12:20 +0000875#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
876 case FieldDescriptor::TYPE_##TYPE: \
kenton@google.com80b1d622009-07-29 01:13:20 +0000877 WireFormatLite::Write##TYPE_METHOD( \
temporal40ee5512008-07-10 02:12:20 +0000878 field->number(), \
879 field->is_repeated() ? \
temporal779f61c2008-08-13 03:15:00 +0000880 message_reflection->GetRepeated##CPPTYPE_METHOD( \
881 message, field, j) : \
882 message_reflection->Get##CPPTYPE_METHOD(message, field), \
kenton@google.comd37d46d2009-04-25 02:53:47 +0000883 output); \
temporal40ee5512008-07-10 02:12:20 +0000884 break;
885
temporal40ee5512008-07-10 02:12:20 +0000886 HANDLE_TYPE(GROUP , Group , Message)
887 HANDLE_TYPE(MESSAGE, Message, Message)
888#undef HANDLE_TYPE
889
890 case FieldDescriptor::TYPE_ENUM: {
891 const EnumValueDescriptor* value = field->is_repeated() ?
temporal779f61c2008-08-13 03:15:00 +0000892 message_reflection->GetRepeatedEnum(message, field, j) :
893 message_reflection->GetEnum(message, field);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000894 if (is_packed) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000895 WireFormatLite::WriteEnumNoTag(value->number(), output);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000896 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000897 WireFormatLite::WriteEnum(field->number(), value->number(), output);
kenton@google.com2d6daa72009-01-22 01:27:00 +0000898 }
temporal40ee5512008-07-10 02:12:20 +0000899 break;
900 }
901
902 // Handle strings separately so that we can get string references
903 // instead of copying.
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000904 case FieldDescriptor::TYPE_STRING: {
kenton@google.comfccb1462009-12-18 02:11:36 +0000905 string scratch;
906 const string& value = field->is_repeated() ?
907 message_reflection->GetRepeatedStringReference(
908 message, field, j, &scratch) :
909 message_reflection->GetStringReference(message, field, &scratch);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000910 VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE,
911 field->name().c_str());
kenton@google.comfccb1462009-12-18 02:11:36 +0000912 WireFormatLite::WriteString(field->number(), value, output);
temporal40ee5512008-07-10 02:12:20 +0000913 break;
914 }
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000915
916 case FieldDescriptor::TYPE_BYTES: {
kenton@google.comfccb1462009-12-18 02:11:36 +0000917 string scratch;
918 const string& value = field->is_repeated() ?
919 message_reflection->GetRepeatedStringReference(
920 message, field, j, &scratch) :
921 message_reflection->GetStringReference(message, field, &scratch);
922 WireFormatLite::WriteBytes(field->number(), value, output);
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000923 break;
924 }
temporal40ee5512008-07-10 02:12:20 +0000925 }
926 }
temporal40ee5512008-07-10 02:12:20 +0000927}
928
kenton@google.comd37d46d2009-04-25 02:53:47 +0000929void WireFormat::SerializeMessageSetItemWithCachedSizes(
temporal40ee5512008-07-10 02:12:20 +0000930 const FieldDescriptor* field,
temporal779f61c2008-08-13 03:15:00 +0000931 const Message& message,
temporal40ee5512008-07-10 02:12:20 +0000932 io::CodedOutputStream* output) {
temporal779f61c2008-08-13 03:15:00 +0000933 const Reflection* message_reflection = message.GetReflection();
934
temporal40ee5512008-07-10 02:12:20 +0000935 // Start group.
kenton@google.com80b1d622009-07-29 01:13:20 +0000936 output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
temporal40ee5512008-07-10 02:12:20 +0000937
938 // Write type ID.
kenton@google.com80b1d622009-07-29 01:13:20 +0000939 output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000940 output->WriteVarint32(field->number());
temporal40ee5512008-07-10 02:12:20 +0000941
942 // Write message.
kenton@google.com80b1d622009-07-29 01:13:20 +0000943 output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
temporal40ee5512008-07-10 02:12:20 +0000944
temporal779f61c2008-08-13 03:15:00 +0000945 const Message& sub_message = message_reflection->GetMessage(message, field);
kenton@google.comd37d46d2009-04-25 02:53:47 +0000946 output->WriteVarint32(sub_message.GetCachedSize());
947 sub_message.SerializeWithCachedSizes(output);
temporal40ee5512008-07-10 02:12:20 +0000948
949 // End group.
kenton@google.com80b1d622009-07-29 01:13:20 +0000950 output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
temporal40ee5512008-07-10 02:12:20 +0000951}
952
953// ===================================================================
954
temporal779f61c2008-08-13 03:15:00 +0000955int WireFormat::ByteSize(const Message& message) {
956 const Descriptor* descriptor = message.GetDescriptor();
957 const Reflection* message_reflection = message.GetReflection();
958
temporal40ee5512008-07-10 02:12:20 +0000959 int our_size = 0;
960
961 vector<const FieldDescriptor*> fields;
temporal779f61c2008-08-13 03:15:00 +0000962 message_reflection->ListFields(message, &fields);
temporal40ee5512008-07-10 02:12:20 +0000963 for (int i = 0; i < fields.size(); i++) {
temporal779f61c2008-08-13 03:15:00 +0000964 our_size += FieldByteSize(fields[i], message);
temporal40ee5512008-07-10 02:12:20 +0000965 }
966
967 if (descriptor->options().message_set_wire_format()) {
968 our_size += ComputeUnknownMessageSetItemsSize(
temporal779f61c2008-08-13 03:15:00 +0000969 message_reflection->GetUnknownFields(message));
temporal40ee5512008-07-10 02:12:20 +0000970 } else {
971 our_size += ComputeUnknownFieldsSize(
temporal779f61c2008-08-13 03:15:00 +0000972 message_reflection->GetUnknownFields(message));
temporal40ee5512008-07-10 02:12:20 +0000973 }
974
975 return our_size;
976}
977
978int WireFormat::FieldByteSize(
979 const FieldDescriptor* field,
temporal779f61c2008-08-13 03:15:00 +0000980 const Message& message) {
981 const Reflection* message_reflection = message.GetReflection();
982
temporal40ee5512008-07-10 02:12:20 +0000983 if (field->is_extension() &&
984 field->containing_type()->options().message_set_wire_format() &&
985 field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
986 !field->is_repeated()) {
temporal779f61c2008-08-13 03:15:00 +0000987 return MessageSetItemByteSize(field, message);
temporal40ee5512008-07-10 02:12:20 +0000988 }
989
temporal40ee5512008-07-10 02:12:20 +0000990 int count = 0;
temporal40ee5512008-07-10 02:12:20 +0000991 if (field->is_repeated()) {
temporal779f61c2008-08-13 03:15:00 +0000992 count = message_reflection->FieldSize(message, field);
993 } else if (message_reflection->HasField(message, field)) {
temporal40ee5512008-07-10 02:12:20 +0000994 count = 1;
995 }
996
kenton@google.com2d6daa72009-01-22 01:27:00 +0000997 const int data_size = FieldDataOnlyByteSize(field, message);
998 int our_size = data_size;
999 if (field->options().packed()) {
1000 if (data_size > 0) {
1001 // Packed fields get serialized like a string, not their native type.
1002 // Technically this doesn't really matter; the size only changes if it's
1003 // a GROUP
1004 our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING);
1005 our_size += io::CodedOutputStream::VarintSize32(data_size);
1006 }
1007 } else {
1008 our_size += count * TagSize(field->number(), field->type());
1009 }
1010 return our_size;
1011}
temporal40ee5512008-07-10 02:12:20 +00001012
kenton@google.com2d6daa72009-01-22 01:27:00 +00001013int WireFormat::FieldDataOnlyByteSize(
1014 const FieldDescriptor* field,
1015 const Message& message) {
1016 const Reflection* message_reflection = message.GetReflection();
1017
1018 int count = 0;
1019 if (field->is_repeated()) {
1020 count = message_reflection->FieldSize(message, field);
1021 } else if (message_reflection->HasField(message, field)) {
1022 count = 1;
1023 }
1024
1025 int data_size = 0;
temporal40ee5512008-07-10 02:12:20 +00001026 switch (field->type()) {
1027#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
1028 case FieldDescriptor::TYPE_##TYPE: \
1029 if (field->is_repeated()) { \
1030 for (int j = 0; j < count; j++) { \
kenton@google.com80b1d622009-07-29 01:13:20 +00001031 data_size += WireFormatLite::TYPE_METHOD##Size( \
temporal779f61c2008-08-13 03:15:00 +00001032 message_reflection->GetRepeated##CPPTYPE_METHOD( \
1033 message, field, j)); \
temporal40ee5512008-07-10 02:12:20 +00001034 } \
1035 } else { \
kenton@google.com80b1d622009-07-29 01:13:20 +00001036 data_size += WireFormatLite::TYPE_METHOD##Size( \
temporal779f61c2008-08-13 03:15:00 +00001037 message_reflection->Get##CPPTYPE_METHOD(message, field)); \
temporal40ee5512008-07-10 02:12:20 +00001038 } \
1039 break;
1040
1041#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \
1042 case FieldDescriptor::TYPE_##TYPE: \
kenton@google.com80b1d622009-07-29 01:13:20 +00001043 data_size += count * WireFormatLite::k##TYPE_METHOD##Size; \
temporal40ee5512008-07-10 02:12:20 +00001044 break;
1045
1046 HANDLE_TYPE( INT32, Int32, Int32)
1047 HANDLE_TYPE( INT64, Int64, Int64)
1048 HANDLE_TYPE(SINT32, SInt32, Int32)
1049 HANDLE_TYPE(SINT64, SInt64, Int64)
1050 HANDLE_TYPE(UINT32, UInt32, UInt32)
1051 HANDLE_TYPE(UINT64, UInt64, UInt64)
1052
1053 HANDLE_FIXED_TYPE( FIXED32, Fixed32)
1054 HANDLE_FIXED_TYPE( FIXED64, Fixed64)
1055 HANDLE_FIXED_TYPE(SFIXED32, SFixed32)
1056 HANDLE_FIXED_TYPE(SFIXED64, SFixed64)
1057
1058 HANDLE_FIXED_TYPE(FLOAT , Float )
1059 HANDLE_FIXED_TYPE(DOUBLE, Double)
1060
1061 HANDLE_FIXED_TYPE(BOOL, Bool)
1062
1063 HANDLE_TYPE(GROUP , Group , Message)
1064 HANDLE_TYPE(MESSAGE, Message, Message)
1065#undef HANDLE_TYPE
1066#undef HANDLE_FIXED_TYPE
1067
1068 case FieldDescriptor::TYPE_ENUM: {
1069 if (field->is_repeated()) {
1070 for (int j = 0; j < count; j++) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001071 data_size += WireFormatLite::EnumSize(
temporal779f61c2008-08-13 03:15:00 +00001072 message_reflection->GetRepeatedEnum(message, field, j)->number());
temporal40ee5512008-07-10 02:12:20 +00001073 }
1074 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +00001075 data_size += WireFormatLite::EnumSize(
temporal779f61c2008-08-13 03:15:00 +00001076 message_reflection->GetEnum(message, field)->number());
temporal40ee5512008-07-10 02:12:20 +00001077 }
1078 break;
1079 }
1080
1081 // Handle strings separately so that we can get string references
1082 // instead of copying.
1083 case FieldDescriptor::TYPE_STRING:
1084 case FieldDescriptor::TYPE_BYTES: {
kenton@google.comfccb1462009-12-18 02:11:36 +00001085 for (int j = 0; j < count; j++) {
1086 string scratch;
1087 const string& value = field->is_repeated() ?
1088 message_reflection->GetRepeatedStringReference(
1089 message, field, j, &scratch) :
1090 message_reflection->GetStringReference(message, field, &scratch);
1091 data_size += WireFormatLite::StringSize(value);
1092 }
temporal40ee5512008-07-10 02:12:20 +00001093 break;
1094 }
1095 }
kenton@google.com2d6daa72009-01-22 01:27:00 +00001096 return data_size;
temporal40ee5512008-07-10 02:12:20 +00001097}
1098
1099int WireFormat::MessageSetItemByteSize(
1100 const FieldDescriptor* field,
temporal779f61c2008-08-13 03:15:00 +00001101 const Message& message) {
1102 const Reflection* message_reflection = message.GetReflection();
1103
kenton@google.com80b1d622009-07-29 01:13:20 +00001104 int our_size = WireFormatLite::kMessageSetItemTagsSize;
temporal40ee5512008-07-10 02:12:20 +00001105
1106 // type_id
1107 our_size += io::CodedOutputStream::VarintSize32(field->number());
1108
1109 // message
temporal779f61c2008-08-13 03:15:00 +00001110 const Message& sub_message = message_reflection->GetMessage(message, field);
temporal40ee5512008-07-10 02:12:20 +00001111 int message_size = sub_message.ByteSize();
1112
1113 our_size += io::CodedOutputStream::VarintSize32(message_size);
1114 our_size += message_size;
1115
1116 return our_size;
1117}
1118
kenton@google.com80b1d622009-07-29 01:13:20 +00001119void WireFormat::VerifyUTF8StringFallback(const char* data,
1120 int size,
jieluo@google.com4de8f552014-07-18 00:47:59 +00001121 Operation op,
1122 const char* field_name) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001123 if (!IsStructurallyValidUTF8(data, size)) {
1124 const char* operation_str = NULL;
1125 switch (op) {
1126 case PARSE:
1127 operation_str = "parsing";
1128 break;
1129 case SERIALIZE:
1130 operation_str = "serializing";
1131 break;
1132 // no default case: have the compiler warn if a case is not covered.
1133 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00001134 string quoted_field_name = "";
1135 if (field_name != NULL) {
1136 quoted_field_name = StringPrintf(" '%s'", field_name);
1137 }
1138 // no space below to avoid double space when the field name is missing.
1139 GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "
1140 << "UTF-8 data when " << operation_str << " a protocol "
1141 << "buffer. Use the 'bytes' type if you intend to send raw "
1142 << "bytes. ";
kenton@google.com80b1d622009-07-29 01:13:20 +00001143 }
1144}
1145
1146
temporal40ee5512008-07-10 02:12:20 +00001147} // namespace internal
1148} // namespace protobuf
1149} // namespace google