This source file includes following definitions.
- GetEnumNumber
- ParseAndMergePartial
- ParseAndMergeField
- ParseAndMergeMessageSetItem
- SerializeWithCachedSizes
- SerializeFieldWithCachedSizes
- SerializeMessageSetItemWithCachedSizes
- ByteSize
- FieldByteSize
- FieldDataOnlyByteSize
- MessageSetItemByteSize
- VerifyUTF8StringFallback
#include <stack>
#include <string>
#include <vector>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/unknown_field_set.h>
namespace google {
namespace protobuf {
namespace internal {
namespace {
inline int GetEnumNumber(const EnumValueDescriptor* descriptor) {
return descriptor->number();
}
}
bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input,
Message* message) {
const Descriptor* descriptor = message->GetDescriptor();
const Reflection* message_reflection = message->GetReflection();
while(true) {
uint32 tag = input->ReadTag();
if (tag == 0) {
return true;
}
if (WireFormatLite::GetTagWireType(tag) ==
WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
const FieldDescriptor* field = NULL;
if (descriptor != NULL) {
int field_number = WireFormatLite::GetTagFieldNumber(tag);
field = descriptor->FindFieldByNumber(field_number);
if (field == NULL && descriptor->IsExtensionNumber(field_number)) {
if (input->GetExtensionPool() == NULL) {
field = message_reflection->FindKnownExtensionByNumber(field_number);
} else {
field = input->GetExtensionPool()
->FindExtensionByNumber(descriptor, field_number);
}
}
if (field == NULL &&
descriptor->options().message_set_wire_format() &&
tag == WireFormatLite::kMessageSetItemStartTag) {
if (!ParseAndMergeMessageSetItem(input, message)) {
return false;
}
continue;
}
}
if (!ParseAndMergeField(tag, field, message, input)) {
return false;
}
}
}
bool WireFormat::ParseAndMergeField(
uint32 tag,
const FieldDescriptor* field,
Message* message,
io::CodedInputStream* input) {
const Reflection* message_reflection = message->GetReflection();
enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
if (field == NULL) {
value_format = UNKNOWN;
} else if (WireFormatLite::GetTagWireType(tag) ==
WireTypeForFieldType(field->type())) {
value_format = NORMAL_FORMAT;
} else if (field->is_packable() &&
WireFormatLite::GetTagWireType(tag) ==
WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
value_format = PACKED_FORMAT;
} else {
value_format = UNKNOWN;
}
if (value_format == UNKNOWN) {
return WireFormatLite::SkipField(
input, tag, message_reflection->MutableUnknownFields(message));
} else if (value_format == PACKED_FORMAT) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(length);
switch (field->type()) {
#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
while (input->BytesUntilLimit() > 0) { \
CPPTYPE value; \
if (!WireFormatLite::ReadPrimitive< \
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
return false; \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
HANDLE_PACKED_TYPE( INT32, int32, Int32)
HANDLE_PACKED_TYPE( INT64, int64, Int64)
HANDLE_PACKED_TYPE(SINT32, int32, Int32)
HANDLE_PACKED_TYPE(SINT64, int64, Int64)
HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32)
HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64)
HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
HANDLE_PACKED_TYPE(FLOAT , float , Float )
HANDLE_PACKED_TYPE(DOUBLE, double, Double)
HANDLE_PACKED_TYPE(BOOL, bool, Bool)
#undef HANDLE_PACKED_TYPE
case FieldDescriptor::TYPE_ENUM: {
while (input->BytesUntilLimit() > 0) {
int value;
if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
input, &value)) return false;
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
message_reflection->AddEnum(message, field, enum_value);
}
}
break;
}
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_BYTES:
return false;
break;
}
input->PopLimit(limit);
} else {
switch (field->type()) {
#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
CPPTYPE value; \
if (!WireFormatLite::ReadPrimitive< \
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
return false; \
if (field->is_repeated()) { \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} else { \
message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
HANDLE_TYPE( INT32, int32, Int32)
HANDLE_TYPE( INT64, int64, Int64)
HANDLE_TYPE(SINT32, int32, Int32)
HANDLE_TYPE(SINT64, int64, Int64)
HANDLE_TYPE(UINT32, uint32, UInt32)
HANDLE_TYPE(UINT64, uint64, UInt64)
HANDLE_TYPE( FIXED32, uint32, UInt32)
HANDLE_TYPE( FIXED64, uint64, UInt64)
HANDLE_TYPE(SFIXED32, int32, Int32)
HANDLE_TYPE(SFIXED64, int64, Int64)
HANDLE_TYPE(FLOAT , float , Float )
HANDLE_TYPE(DOUBLE, double, Double)
HANDLE_TYPE(BOOL, bool, Bool)
#undef HANDLE_TYPE
case FieldDescriptor::TYPE_ENUM: {
int value;
if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
input, &value)) return false;
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
if (field->is_repeated()) {
message_reflection->AddEnum(message, field, enum_value);
} else {
message_reflection->SetEnum(message, field, enum_value);
}
} else {
int64 sign_extended_value = static_cast<int64>(value);
message_reflection->MutableUnknownFields(message)
->AddVarint(WireFormatLite::GetTagFieldNumber(tag),
sign_extended_value);
}
break;
}
case FieldDescriptor::TYPE_STRING: {
string value;
if (!WireFormatLite::ReadString(input, &value)) return false;
VerifyUTF8String(value.data(), value.length(), PARSE);
if (field->is_repeated()) {
message_reflection->AddString(message, field, value);
} else {
message_reflection->SetString(message, field, value);
}
break;
}
case FieldDescriptor::TYPE_BYTES: {
string value;
if (!WireFormatLite::ReadBytes(input, &value)) return false;
if (field->is_repeated()) {
message_reflection->AddString(message, field, value);
} else {
message_reflection->SetString(message, field, value);
}
break;
}
case FieldDescriptor::TYPE_GROUP: {
Message* sub_message;
if (field->is_repeated()) {
sub_message = message_reflection->AddMessage(
message, field, input->GetExtensionFactory());
} else {
sub_message = message_reflection->MutableMessage(
message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
input, sub_message))
return false;
break;
}
case FieldDescriptor::TYPE_MESSAGE: {
Message* sub_message;
if (field->is_repeated()) {
sub_message = message_reflection->AddMessage(
message, field, input->GetExtensionFactory());
} else {
sub_message = message_reflection->MutableMessage(
message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
break;
}
}
}
return true;
}
bool WireFormat::ParseAndMergeMessageSetItem(
io::CodedInputStream* input,
Message* message) {
const Reflection* message_reflection = message->GetReflection();
uint32 fake_tag = 0;
const FieldDescriptor* field = NULL;
string message_data;
while (true) {
uint32 tag = input->ReadTag();
if (tag == 0) return false;
switch (tag) {
case WireFormatLite::kMessageSetTypeIdTag: {
uint32 type_id;
if (!input->ReadVarint32(&type_id)) return false;
fake_tag = WireFormatLite::MakeTag(
type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
field = message_reflection->FindKnownExtensionByNumber(type_id);
if (!message_data.empty()) {
io::ArrayInputStream raw_input(message_data.data(),
message_data.size());
io::CodedInputStream sub_input(&raw_input);
if (!ParseAndMergeField(fake_tag, field, message,
&sub_input)) {
return false;
}
message_data.clear();
}
break;
}
case WireFormatLite::kMessageSetMessageTag: {
if (fake_tag == 0) {
string temp;
uint32 length;
if (!input->ReadVarint32(&length)) return false;
if (!input->ReadString(&temp, length)) return false;
io::StringOutputStream output_stream(&message_data);
io::CodedOutputStream coded_output(&output_stream);
coded_output.WriteVarint32(length);
coded_output.WriteString(temp);
} else {
if (!ParseAndMergeField(fake_tag, field, message, input)) {
return false;
}
}
break;
}
case WireFormatLite::kMessageSetItemEndTag: {
return true;
}
default: {
if (!WireFormatLite::SkipField(input, tag, NULL)) return false;
}
}
}
}
void WireFormat::SerializeWithCachedSizes(
const Message& message,
int size, io::CodedOutputStream* output) {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* message_reflection = message.GetReflection();
int expected_endpoint = output->ByteCount() + size;
vector<const FieldDescriptor*> fields;
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
SerializeFieldWithCachedSizes(fields[i], message, output);
}
if (descriptor->options().message_set_wire_format()) {
WireFormatLite::SerializeUnknownMessageSetItems(
message_reflection->GetUnknownFields(message), output);
} else {
WireFormatLite::SerializeUnknownFields(
message_reflection->GetUnknownFields(message), output);
}
GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint)
<< ": Protocol message serialized to a size different from what was "
"originally expected. Perhaps it was modified by another thread "
"during serialization?";
}
void WireFormat::SerializeFieldWithCachedSizes(
const FieldDescriptor* field,
const Message& message,
io::CodedOutputStream* output) {
const Reflection* message_reflection = message.GetReflection();
if (field->is_extension() &&
field->containing_type()->options().message_set_wire_format() &&
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
!field->is_repeated()) {
SerializeMessageSetItemWithCachedSizes(field, message, output);
return;
}
int count = 0;
if (field->is_repeated()) {
count = message_reflection->FieldSize(message, field);
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
const bool is_packed = field->options().packed();
if (is_packed && count > 0) {
WireFormatLite::WriteTag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
const int data_size = FieldDataOnlyByteSize(field, message);
output->WriteVarint32(data_size);
}
for (int j = 0; j < count; j++) {
switch (field->type()) {
#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
const CPPTYPE value = field->is_repeated() ? \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j) : \
message_reflection->Get##CPPTYPE_METHOD( \
message, field); \
if (is_packed) { \
WireFormatLite::Write##TYPE_METHOD##NoTag(value, output); \
} else { \
WireFormatLite::Write##TYPE_METHOD(field->number(), value, output); \
} \
break; \
}
HANDLE_PRIMITIVE_TYPE( INT32, int32, Int32, Int32)
HANDLE_PRIMITIVE_TYPE( INT64, int64, Int64, Int64)
HANDLE_PRIMITIVE_TYPE(SINT32, int32, SInt32, Int32)
HANDLE_PRIMITIVE_TYPE(SINT64, int64, SInt64, Int64)
HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32)
HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64)
HANDLE_PRIMITIVE_TYPE( FIXED32, uint32, Fixed32, UInt32)
HANDLE_PRIMITIVE_TYPE( FIXED64, uint64, Fixed64, UInt64)
HANDLE_PRIMITIVE_TYPE(SFIXED32, int32, SFixed32, Int32)
HANDLE_PRIMITIVE_TYPE(SFIXED64, int64, SFixed64, Int64)
HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float )
HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double)
HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool)
#undef HANDLE_PRIMITIVE_TYPE
#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
WireFormatLite::Write##TYPE_METHOD( \
field->number(), \
field->is_repeated() ? \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j) : \
message_reflection->Get##CPPTYPE_METHOD(message, field), \
output); \
break;
HANDLE_TYPE(GROUP , Group , Message)
HANDLE_TYPE(MESSAGE, Message, Message)
#undef HANDLE_TYPE
case FieldDescriptor::TYPE_ENUM: {
const EnumValueDescriptor* value = field->is_repeated() ?
message_reflection->GetRepeatedEnum(message, field, j) :
message_reflection->GetEnum(message, field);
if (is_packed) {
WireFormatLite::WriteEnumNoTag(value->number(), output);
} else {
WireFormatLite::WriteEnum(field->number(), value->number(), output);
}
break;
}
case FieldDescriptor::TYPE_STRING: {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
VerifyUTF8String(value.data(), value.length(), SERIALIZE);
WireFormatLite::WriteString(field->number(), value, output);
break;
}
case FieldDescriptor::TYPE_BYTES: {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
WireFormatLite::WriteBytes(field->number(), value, output);
break;
}
}
}
}
void WireFormat::SerializeMessageSetItemWithCachedSizes(
const FieldDescriptor* field,
const Message& message,
io::CodedOutputStream* output) {
const Reflection* message_reflection = message.GetReflection();
output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
output->WriteVarint32(field->number());
output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
const Message& sub_message = message_reflection->GetMessage(message, field);
output->WriteVarint32(sub_message.GetCachedSize());
sub_message.SerializeWithCachedSizes(output);
output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
}
int WireFormat::ByteSize(const Message& message) {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* message_reflection = message.GetReflection();
int our_size = 0;
vector<const FieldDescriptor*> fields;
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
our_size += FieldByteSize(fields[i], message);
}
if (descriptor->options().message_set_wire_format()) {
our_size += WireFormatLite::ComputeUnknownMessageSetItemsSize(
message_reflection->GetUnknownFields(message));
} else {
our_size += WireFormatLite::ComputeUnknownFieldsSize(
message_reflection->GetUnknownFields(message));
}
return our_size;
}
int WireFormat::FieldByteSize(
const FieldDescriptor* field,
const Message& message) {
const Reflection* message_reflection = message.GetReflection();
if (field->is_extension() &&
field->containing_type()->options().message_set_wire_format() &&
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
!field->is_repeated()) {
return MessageSetItemByteSize(field, message);
}
int count = 0;
if (field->is_repeated()) {
count = message_reflection->FieldSize(message, field);
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
const int data_size = FieldDataOnlyByteSize(field, message);
int our_size = data_size;
if (field->options().packed()) {
if (data_size > 0) {
our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING);
our_size += io::CodedOutputStream::VarintSize32(data_size);
}
} else {
our_size += count * TagSize(field->number(), field->type());
}
return our_size;
}
int WireFormat::FieldDataOnlyByteSize(
const FieldDescriptor* field,
const Message& message) {
const Reflection* message_reflection = message.GetReflection();
int count = 0;
if (field->is_repeated()) {
count = message_reflection->FieldSize(message, field);
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
int data_size = 0;
switch (field->type()) {
#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
if (field->is_repeated()) { \
for (int j = 0; j < count; j++) { \
data_size += WireFormatLite::TYPE_METHOD##Size( \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j)); \
} \
} else { \
data_size += WireFormatLite::TYPE_METHOD##Size( \
message_reflection->Get##CPPTYPE_METHOD(message, field)); \
} \
break;
#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
data_size += count * WireFormatLite::k##TYPE_METHOD##Size; \
break;
HANDLE_TYPE( INT32, Int32, Int32)
HANDLE_TYPE( INT64, Int64, Int64)
HANDLE_TYPE(SINT32, SInt32, Int32)
HANDLE_TYPE(SINT64, SInt64, Int64)
HANDLE_TYPE(UINT32, UInt32, UInt32)
HANDLE_TYPE(UINT64, UInt64, UInt64)
HANDLE_FIXED_TYPE( FIXED32, Fixed32)
HANDLE_FIXED_TYPE( FIXED64, Fixed64)
HANDLE_FIXED_TYPE(SFIXED32, SFixed32)
HANDLE_FIXED_TYPE(SFIXED64, SFixed64)
HANDLE_FIXED_TYPE(FLOAT , Float )
HANDLE_FIXED_TYPE(DOUBLE, Double)
HANDLE_FIXED_TYPE(BOOL, Bool)
HANDLE_TYPE(GROUP , Group , Message)
HANDLE_TYPE(MESSAGE, Message, Message)
#undef HANDLE_TYPE
#undef HANDLE_FIXED_TYPE
case FieldDescriptor::TYPE_ENUM: {
if (field->is_repeated()) {
for (int j = 0; j < count; j++) {
data_size += WireFormatLite::EnumSize(
message_reflection->GetRepeatedEnum(message, field, j)->number());
}
} else {
data_size += WireFormatLite::EnumSize(
message_reflection->GetEnum(message, field)->number());
}
break;
}
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES: {
for (int j = 0; j < count; j++) {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
data_size += WireFormatLite::StringSize(value);
}
break;
}
}
return data_size;
}
int WireFormat::MessageSetItemByteSize(
const FieldDescriptor* field,
const Message& message) {
const Reflection* message_reflection = message.GetReflection();
int our_size = WireFormatLite::kMessageSetItemTagsSize;
our_size += io::CodedOutputStream::VarintSize32(field->number());
const Message& sub_message = message_reflection->GetMessage(message, field);
int message_size = sub_message.ByteSize();
our_size += io::CodedOutputStream::VarintSize32(message_size);
our_size += message_size;
return our_size;
}
void WireFormat::VerifyUTF8StringFallback(const char* data,
int size,
Operation op) {
if (!IsStructurallyValidUTF8(data, size)) {
const char* operation_str = NULL;
switch (op) {
case PARSE:
operation_str = "parsing";
break;
case SERIALIZE:
operation_str = "serializing";
break;
}
GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when "
<< operation_str
<< " a protocol buffer. Use the 'bytes' type if you intend to "
"send raw bytes.";
}
}
}
}
}