Integrate recent changes from google3.

protoc
- New flags --encode and --decode can be used to convert between protobuf text
  format and binary format from the command-line.
- New flag --descriptor_set_out can be used to write FileDescriptorProtos for
  all parsed files directly into a single output file.  This is particularly
  useful if you wish to parse .proto files from programs written in languages
  other than C++: just run protoc as a background process and have it output
  a FileDescriptorList, then parse that natively.

C++
- Reflection objects are now per-class rather than per-instance.  To make this
  possible, the Reflection interface had to be changed such that all methods
  take the Message instance as a parameter.  This change improves performance
  significantly in memory-bandwidth-limited use cases, since it makes the
  message objects smaller.  Note that source-incompatible interface changes
  like this will not be made again after the library leaves beta.

Python
- MergeFrom(message) and CopyFrom(message) are now implemented.
- SerializeToString() raises an exception if the message is missing required
  fields.
- Code organization improvements.
- Fixed doc comments for RpcController and RpcChannel, which had somehow been
  swapped.
This commit is contained in:
temporal 2008-08-13 03:15:00 +00:00
parent a0f27fcd96
commit 779f61c6a3
44 changed files with 3369 additions and 2067 deletions

View file

@ -6,14 +6,6 @@
# will fail if these files do not match what the protocol compiler would
# generate.
# Note that this will always need to be run once after running
# extract_from_google3.sh. That script initially copies descriptor.pb.{h,cc}
# over from the google3 code and fixes it up to compile outside of google3, but
# it cannot fix the encoded descriptor embedded in descriptor.pb.cc. So, once
# the protocol compiler has been built with the slightly-broken
# descriptor.pb.cc, the files must be regenerated and the compiler must be
# built again.
if test ! -e src/google/protobuf/stubs/common.h; then
cat >&2 << __EOF__
Could not find source code. Make sure you are running this script from the

View file

@ -656,9 +656,172 @@ class RefectionTest(unittest.TestCase):
self.assertRaises(KeyError, extendee_proto.HasExtension,
unittest_pb2.repeated_string_extension)
def testCopyFrom(self):
# TODO(robinson): Implement.
pass
def testMergeFromSingularField(self):
# Test merge with just a singular field.
proto1 = unittest_pb2.TestAllTypes()
proto1.optional_int32 = 1
proto2 = unittest_pb2.TestAllTypes()
# This shouldn't get overwritten.
proto2.optional_string = 'value'
proto2.MergeFrom(proto1)
self.assertEqual(1, proto2.optional_int32)
self.assertEqual('value', proto2.optional_string)
def testMergeFromRepeatedField(self):
# Test merge with just a repeated field.
proto1 = unittest_pb2.TestAllTypes()
proto1.repeated_int32.append(1)
proto1.repeated_int32.append(2)
proto2 = unittest_pb2.TestAllTypes()
proto2.repeated_int32.append(0)
proto2.MergeFrom(proto1)
self.assertEqual(0, proto2.repeated_int32[0])
self.assertEqual(1, proto2.repeated_int32[1])
self.assertEqual(2, proto2.repeated_int32[2])
def testMergeFromOptionalGroup(self):
# Test merge with an optional group.
proto1 = unittest_pb2.TestAllTypes()
proto1.optionalgroup.a = 12
proto2 = unittest_pb2.TestAllTypes()
proto2.MergeFrom(proto1)
self.assertEqual(12, proto2.optionalgroup.a)
def testMergeFromRepeatedNestedMessage(self):
# Test merge with a repeated nested message.
proto1 = unittest_pb2.TestAllTypes()
m = proto1.repeated_nested_message.add()
m.bb = 123
m = proto1.repeated_nested_message.add()
m.bb = 321
proto2 = unittest_pb2.TestAllTypes()
m = proto2.repeated_nested_message.add()
m.bb = 999
proto2.MergeFrom(proto1)
self.assertEqual(999, proto2.repeated_nested_message[0].bb)
self.assertEqual(123, proto2.repeated_nested_message[1].bb)
self.assertEqual(321, proto2.repeated_nested_message[2].bb)
def testMergeFromAllFields(self):
# With all fields set.
proto1 = unittest_pb2.TestAllTypes()
test_util.SetAllFields(proto1)
proto2 = unittest_pb2.TestAllTypes()
proto2.MergeFrom(proto1)
# Messages should be equal.
self.assertEqual(proto2, proto1)
# Serialized string should be equal too.
string1 = proto1.SerializeToString()
string2 = proto2.SerializeToString()
self.assertEqual(string1, string2)
def testMergeFromExtensionsSingular(self):
proto1 = unittest_pb2.TestAllExtensions()
proto1.Extensions[unittest_pb2.optional_int32_extension] = 1
proto2 = unittest_pb2.TestAllExtensions()
proto2.MergeFrom(proto1)
self.assertEqual(
1, proto2.Extensions[unittest_pb2.optional_int32_extension])
def testMergeFromExtensionsRepeated(self):
proto1 = unittest_pb2.TestAllExtensions()
proto1.Extensions[unittest_pb2.repeated_int32_extension].append(1)
proto1.Extensions[unittest_pb2.repeated_int32_extension].append(2)
proto2 = unittest_pb2.TestAllExtensions()
proto2.Extensions[unittest_pb2.repeated_int32_extension].append(0)
proto2.MergeFrom(proto1)
self.assertEqual(
3, len(proto2.Extensions[unittest_pb2.repeated_int32_extension]))
self.assertEqual(
0, proto2.Extensions[unittest_pb2.repeated_int32_extension][0])
self.assertEqual(
1, proto2.Extensions[unittest_pb2.repeated_int32_extension][1])
self.assertEqual(
2, proto2.Extensions[unittest_pb2.repeated_int32_extension][2])
def testMergeFromExtensionsNestedMessage(self):
proto1 = unittest_pb2.TestAllExtensions()
ext1 = proto1.Extensions[
unittest_pb2.repeated_nested_message_extension]
m = ext1.add()
m.bb = 222
m = ext1.add()
m.bb = 333
proto2 = unittest_pb2.TestAllExtensions()
ext2 = proto2.Extensions[
unittest_pb2.repeated_nested_message_extension]
m = ext2.add()
m.bb = 111
proto2.MergeFrom(proto1)
ext2 = proto2.Extensions[
unittest_pb2.repeated_nested_message_extension]
self.assertEqual(3, len(ext2))
self.assertEqual(111, ext2[0].bb)
self.assertEqual(222, ext2[1].bb)
self.assertEqual(333, ext2[2].bb)
def testCopyFromSingularField(self):
# Test copy with just a singular field.
proto1 = unittest_pb2.TestAllTypes()
proto1.optional_int32 = 1
proto1.optional_string = 'important-text'
proto2 = unittest_pb2.TestAllTypes()
proto2.optional_string = 'value'
proto2.CopyFrom(proto1)
self.assertEqual(1, proto2.optional_int32)
self.assertEqual('important-text', proto2.optional_string)
def testCopyFromRepeatedField(self):
# Test copy with a repeated field.
proto1 = unittest_pb2.TestAllTypes()
proto1.repeated_int32.append(1)
proto1.repeated_int32.append(2)
proto2 = unittest_pb2.TestAllTypes()
proto2.repeated_int32.append(0)
proto2.CopyFrom(proto1)
self.assertEqual(1, proto2.repeated_int32[0])
self.assertEqual(2, proto2.repeated_int32[1])
def testCopyFromAllFields(self):
# With all fields set.
proto1 = unittest_pb2.TestAllTypes()
test_util.SetAllFields(proto1)
proto2 = unittest_pb2.TestAllTypes()
proto2.CopyFrom(proto1)
# Messages should be equal.
self.assertEqual(proto2, proto1)
# Serialized string should be equal too.
string1 = proto1.SerializeToString()
string2 = proto2.SerializeToString()
self.assertEqual(string1, string2)
def testCopyFromSelf(self):
proto1 = unittest_pb2.TestAllTypes()
proto1.repeated_int32.append(1)
proto1.optional_int32 = 2
proto1.optional_string = 'important-text'
proto1.CopyFrom(proto1)
self.assertEqual(1, proto1.repeated_int32[0])
self.assertEqual(2, proto1.optional_int32)
self.assertEqual('important-text', proto1.optional_string)
def testClear(self):
proto = unittest_pb2.TestAllTypes()
@ -1256,6 +1419,57 @@ class SerializationTest(unittest.TestCase):
# Parsing this message should succeed.
proto2.MergeFromString(serialized)
def _CheckRaises(self, exc_class, callable_obj, exception):
"""This method checks if the excpetion type and message are as expected."""
try:
callable_obj()
except exc_class, ex:
# Check if the exception message is the right one.
self.assertEqual(exception, str(ex))
return
else:
raise self.failureException('%s not raised' % str(exc_class))
def testSerializeUninitialized(self):
proto = unittest_pb2.TestRequired()
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
'Required field protobuf_unittest.TestRequired.a is not set.')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
proto.a = 1
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
'Required field protobuf_unittest.TestRequired.b is not set.')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
proto.b = 2
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
'Required field protobuf_unittest.TestRequired.c is not set.')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
proto.c = 3
serialized = proto.SerializeToString()
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
proto2 = unittest_pb2.TestRequired()
proto2.MergeFromString(serialized)
self.assertEqual(1, proto2.a)
self.assertEqual(2, proto2.b)
self.assertEqual(3, proto2.c)
proto2.ParseFromString(partial)
self.assertEqual(1, proto2.a)
self.assertEqual(2, proto2.b)
self.assertEqual(3, proto2.c)
class OptionsTest(unittest.TestCase):

View file

@ -65,15 +65,43 @@ class Message(object):
return text_format.MessageToString(self)
def MergeFrom(self, other_msg):
"""Merges the contents of the specified message into current message.
This method merges the contents of the specified message into the current
message. Singular fields that are set in the specified message overwrite
the corresponding fields in the current message. Repeated fields are
appended. Singular sub-messages and groups are recursively merged.
Args:
other_msg: Message to merge into the current message.
"""
raise NotImplementedError
def CopyFrom(self, other_msg):
raise NotImplementedError
"""Copies the content of the specified message into the current message.
The method clears the current message and then merges the specified
message using MergeFrom.
Args:
other_msg: Message to copy into the current one.
"""
if self == other_msg:
return
self.Clear()
self.MergeFrom(other_msg)
def Clear(self):
"""Clears all data that was set in the message."""
raise NotImplementedError
def IsInitialized(self):
"""Checks if the message is initialized.
Returns:
The method returns True if the message is initialized (i.e. all of its
required fields are set).
"""
raise NotImplementedError
# TODO(robinson): MergeFromString() should probably return None and be
@ -118,6 +146,26 @@ class Message(object):
self.MergeFromString(serialized)
def SerializeToString(self):
"""Serializes the protocol message to a binary string.
Returns:
A binary string representation of the message if all of the required
fields in the message are set (i.e. the message is initialized).
Raises:
message.EncodeError if the message isn't initialized.
"""
raise NotImplementedError
def SerializePartialToString(self):
"""Serializes the protocol message to a binary string.
This method is similar to SerializeToString but doesn't check if the
message is initialized.
Returns:
A string representation of the partial message.
"""
raise NotImplementedError
# TODO(robinson): Decide whether we like these better

View file

@ -43,6 +43,7 @@ import weakref
from google.protobuf.internal import decoder
from google.protobuf.internal import encoder
from google.protobuf.internal import message_listener as message_listener_mod
from google.protobuf.internal import type_checkers
from google.protobuf.internal import wire_format
from google.protobuf import descriptor as descriptor_mod
from google.protobuf import message as message_mod
@ -261,8 +262,8 @@ def _DefaultValueForField(message, field):
# been set. (Depends on order in which we initialize the classes).
return _RepeatedCompositeFieldContainer(listener, field.message_type)
else:
return _RepeatedScalarFieldContainer(listener,
_VALUE_CHECKERS[field.cpp_type])
return _RepeatedScalarFieldContainer(
listener, type_checkers.VALUE_CHECKERS[field.cpp_type])
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
assert field.default_value is None
@ -370,7 +371,7 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
python_field_name = _ValueFieldName(proto_field_name)
has_field_name = _HasFieldName(proto_field_name)
property_name = _PropertyName(proto_field_name)
type_checker = _VALUE_CHECKERS[field.cpp_type]
type_checker = type_checkers.VALUE_CHECKERS[field.cpp_type]
def getter(self):
return getattr(self, python_field_name)
@ -614,7 +615,7 @@ def _BytesForNonRepeatedElement(value, field_number, field_type):
within FieldDescriptor.
"""
try:
fn = _TYPE_TO_BYTE_SIZE_FN[field_type]
fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type]
return fn(field_number, value)
except KeyError:
raise message_mod.EncodeError('Unrecognized field type: %d' % field_type)
@ -707,7 +708,7 @@ def _SerializeValueToEncoder(value, field_number, field_descriptor, encoder):
return
try:
method = _TYPE_TO_SERIALIZE_METHOD[field_descriptor.type]
method = type_checkers.TYPE_TO_SERIALIZE_METHOD[field_descriptor.type]
method(encoder, field_number, value)
except KeyError:
raise message_mod.EncodeError('Unrecognized field type: %d' %
@ -748,15 +749,24 @@ def _ImergeSorted(*streams):
def _AddSerializeToStringMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
Encoder = encoder.Encoder
def SerializeToString(self):
# Check if the message has all of its required fields set.
errors = []
if not _InternalIsInitialized(self, errors):
raise message_mod.EncodeError('\n'.join(errors))
return self.SerializePartialToString()
cls.SerializeToString = SerializeToString
def _AddSerializePartialToStringMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
Encoder = encoder.Encoder
def SerializePartialToString(self):
encoder = Encoder()
# We need to serialize all extension and non-extension fields
# together, in sorted order by field number.
# Step 3: Iterate over all extension and non-extension fields, sorted
# in order of tag number, and serialize each one to the wire.
for field_descriptor, field_value in self.ListFields():
if field_descriptor.label == _FieldDescriptor.LABEL_REPEATED:
repeated_value = field_value
@ -766,13 +776,13 @@ def _AddSerializeToStringMethod(message_descriptor, cls):
_SerializeValueToEncoder(element, field_descriptor.number,
field_descriptor, encoder)
return encoder.ToString()
cls.SerializeToString = SerializeToString
cls.SerializePartialToString = SerializePartialToString
def _WireTypeForFieldType(field_type):
"""Given a field type, returns the expected wire type."""
try:
return _FIELD_TYPE_TO_WIRE_TYPE[field_type]
return type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_type]
except KeyError:
raise message_mod.DecodeError('Unknown field type: %d' % field_type)
@ -804,7 +814,7 @@ def _DeserializeScalarFromDecoder(field_type, decoder):
be a scalar (non-group, non-message) FieldDescriptor.FIELD_* constant.
"""
try:
method = _TYPE_TO_DESERIALIZE_METHOD[field_type]
method = type_checkers.TYPE_TO_DESERIALIZE_METHOD[field_type]
return method(decoder)
except KeyError:
raise message_mod.DecodeError('Unrecognized field type: %d' % field_type)
@ -1034,12 +1044,13 @@ def _HasFieldOrExtension(message, field_or_extension):
return message.HasField(field_or_extension.name)
def _IsFieldOrExtensionInitialized(message, field):
def _IsFieldOrExtensionInitialized(message, field, errors=None):
"""Checks if a message field or extension is initialized.
Args:
message: The message which contains the field or extension.
field: Field or extension to check. This must be a FieldDescriptor instance.
errors: Errors will be appended to it, if set to a meaningful value.
Returns:
True if the field/extension can be considered initialized.
@ -1047,6 +1058,8 @@ def _IsFieldOrExtensionInitialized(message, field):
# If the field is required and is not set, it isn't initialized.
if field.label == _FieldDescriptor.LABEL_REQUIRED:
if not _HasFieldOrExtension(message, field):
if errors is not None:
errors.append('Required field %s is not set.' % field.full_name)
return False
# If the field is optional and is not set, or if it
@ -1062,7 +1075,27 @@ def _IsFieldOrExtensionInitialized(message, field):
# If all submessages in this field are initialized, the field is
# considered initialized.
for message in messages:
if not message.IsInitialized():
if not _InternalIsInitialized(message, errors):
return False
return True
def _InternalIsInitialized(message, errors=None):
"""Checks if all required fields of a message are set.
Args:
message: The message to check.
errors: If set, initialization errors will be appended to it.
Returns:
True iff the specified message has all required fields set.
"""
fields_and_extensions = []
fields_and_extensions.extend(message.DESCRIPTOR.fields)
fields_and_extensions.extend(
[extension[0] for extension in message.Extensions._ListSetExtensions()])
for field_or_extension in fields_and_extensions:
if not _IsFieldOrExtensionInitialized(message, field_or_extension, errors):
return False
return True
@ -1082,25 +1115,54 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
cls.MergeFromString = MergeFromString
def _AddIsInitializedMethod(message_descriptor, cls):
def _AddIsInitializedMethod(cls):
"""Adds the IsInitialized method to the protocol message class."""
def IsInitialized(self):
fields_and_extensions = []
fields_and_extensions.extend(message_descriptor.fields)
fields_and_extensions.extend(
self.Extensions._AllExtensionsByNumber().values())
for field_or_extension in fields_and_extensions:
if not _IsFieldOrExtensionInitialized(self, field_or_extension):
return False
return True
cls.IsInitialized = IsInitialized
cls.IsInitialized = _InternalIsInitialized
def _MergeFieldOrExtension(destination_msg, field, value):
"""Merges a specified message field into another message."""
property_name = _PropertyName(field.name)
is_extension = field.is_extension
if not is_extension:
destination = getattr(destination_msg, property_name)
elif (field.label == _FieldDescriptor.LABEL_REPEATED or
field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
destination = destination_msg.Extensions[field]
# Case 1 - a composite field.
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
for v in value:
destination.add().MergeFrom(v)
else:
destination.MergeFrom(value)
return
# Case 2 - a repeated field.
if field.label == _FieldDescriptor.LABEL_REPEATED:
for v in value:
destination.append(v)
return
# Case 3 - a singular field.
if is_extension:
destination_msg.Extensions[field] = value
else:
setattr(destination_msg, property_name, value)
def _AddMergeFromMethod(cls):
def MergeFrom(self, msg):
assert msg is not self
for field in msg.ListFields():
_MergeFieldOrExtension(self, field[0], field[1])
cls.MergeFrom = MergeFrom
def _AddMessageMethods(message_descriptor, cls):
"""Adds implementations of all Message methods to cls."""
# TODO(robinson): Add support for remaining Message methods.
_AddListFieldsMethod(message_descriptor, cls)
_AddHasFieldMethod(cls)
_AddClearFieldMethod(cls)
@ -1111,8 +1173,10 @@ def _AddMessageMethods(message_descriptor, cls):
_AddSetListenerMethod(cls)
_AddByteSizeMethod(message_descriptor, cls)
_AddSerializeToStringMethod(message_descriptor, cls)
_AddSerializePartialToStringMethod(message_descriptor, cls)
_AddMergeFromStringMethod(message_descriptor, cls)
_AddIsInitializedMethod(message_descriptor, cls)
_AddIsInitializedMethod(cls)
_AddMergeFromMethod(cls)
def _AddPrivateHelperMethods(cls):
@ -1440,7 +1504,7 @@ class _ExtensionDict(object):
and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE):
# It's slightly wasteful to lookup the type checker each time,
# but we expect this to be a vanishingly uncommon case anyway.
type_checker = _VALUE_CHECKERS[field.cpp_type]
type_checker = type_checkers.VALUE_CHECKERS[field.cpp_type]
type_checker.CheckValue(value)
self._values[handle_id] = value
self._has_bits[handle_id] = True
@ -1561,174 +1625,3 @@ class _ExtensionDict(object):
# be careful when we move away from having _known_extensions as a
# deep-copied member of this object.
return dict((f.number, f) for f in self._known_extensions.itervalues())
# None of the typecheckers below make any attempt to guard against people
# subclassing builtin types and doing weird things. We're not trying to
# protect against malicious clients here, just people accidentally shooting
# themselves in the foot in obvious ways.
class _TypeChecker(object):
"""Type checker used to catch type errors as early as possible
when the client is setting scalar fields in protocol messages.
"""
def __init__(self, *acceptable_types):
self._acceptable_types = acceptable_types
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, self._acceptable_types):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), self._acceptable_types))
raise TypeError(message)
# _IntValueChecker and its subclasses perform integer type-checks
# and bounds-checks.
class _IntValueChecker(object):
"""Checker used for integer fields. Performs type-check and range check."""
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, (int, long)):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), (int, long)))
raise TypeError(message)
if not self._MIN <= proposed_value <= self._MAX:
raise ValueError('Value out of range: %d' % proposed_value)
class _Int32ValueChecker(_IntValueChecker):
# We're sure to use ints instead of longs here since comparison may be more
# efficient.
_MIN = -2147483648
_MAX = 2147483647
class _Uint32ValueChecker(_IntValueChecker):
_MIN = 0
_MAX = (1 << 32) - 1
class _Int64ValueChecker(_IntValueChecker):
_MIN = -(1 << 63)
_MAX = (1 << 63) - 1
class _Uint64ValueChecker(_IntValueChecker):
_MIN = 0
_MAX = (1 << 64) - 1
# Type-checkers for all scalar CPPTYPEs.
_VALUE_CHECKERS = {
_FieldDescriptor.CPPTYPE_INT32: _Int32ValueChecker(),
_FieldDescriptor.CPPTYPE_INT64: _Int64ValueChecker(),
_FieldDescriptor.CPPTYPE_UINT32: _Uint32ValueChecker(),
_FieldDescriptor.CPPTYPE_UINT64: _Uint64ValueChecker(),
_FieldDescriptor.CPPTYPE_DOUBLE: _TypeChecker(
float, int, long),
_FieldDescriptor.CPPTYPE_FLOAT: _TypeChecker(
float, int, long),
_FieldDescriptor.CPPTYPE_BOOL: _TypeChecker(bool, int),
_FieldDescriptor.CPPTYPE_ENUM: _Int32ValueChecker(),
_FieldDescriptor.CPPTYPE_STRING: _TypeChecker(str),
}
# Map from field type to a function F, such that F(field_num, value)
# gives the total byte size for a value of the given type. This
# byte size includes tag information and any other additional space
# associated with serializing "value".
_TYPE_TO_BYTE_SIZE_FN = {
_FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize,
_FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize,
_FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize,
_FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize,
_FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize,
_FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize,
_FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize,
_FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize,
_FieldDescriptor.TYPE_STRING: wire_format.StringByteSize,
_FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize,
_FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize,
_FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize,
_FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize,
_FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize,
_FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize,
_FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize,
_FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize,
_FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize
}
# Maps from field type to an unbound Encoder method F, such that
# F(encoder, field_number, value) will append the serialization
# of a value of this type to the encoder.
_Encoder = encoder.Encoder
_TYPE_TO_SERIALIZE_METHOD = {
_FieldDescriptor.TYPE_DOUBLE: _Encoder.AppendDouble,
_FieldDescriptor.TYPE_FLOAT: _Encoder.AppendFloat,
_FieldDescriptor.TYPE_INT64: _Encoder.AppendInt64,
_FieldDescriptor.TYPE_UINT64: _Encoder.AppendUInt64,
_FieldDescriptor.TYPE_INT32: _Encoder.AppendInt32,
_FieldDescriptor.TYPE_FIXED64: _Encoder.AppendFixed64,
_FieldDescriptor.TYPE_FIXED32: _Encoder.AppendFixed32,
_FieldDescriptor.TYPE_BOOL: _Encoder.AppendBool,
_FieldDescriptor.TYPE_STRING: _Encoder.AppendString,
_FieldDescriptor.TYPE_GROUP: _Encoder.AppendGroup,
_FieldDescriptor.TYPE_MESSAGE: _Encoder.AppendMessage,
_FieldDescriptor.TYPE_BYTES: _Encoder.AppendBytes,
_FieldDescriptor.TYPE_UINT32: _Encoder.AppendUInt32,
_FieldDescriptor.TYPE_ENUM: _Encoder.AppendEnum,
_FieldDescriptor.TYPE_SFIXED32: _Encoder.AppendSFixed32,
_FieldDescriptor.TYPE_SFIXED64: _Encoder.AppendSFixed64,
_FieldDescriptor.TYPE_SINT32: _Encoder.AppendSInt32,
_FieldDescriptor.TYPE_SINT64: _Encoder.AppendSInt64,
}
# Maps from field type to expected wiretype.
_FIELD_TYPE_TO_WIRE_TYPE = {
_FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64,
_FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32,
_FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64,
_FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32,
_FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_STRING:
wire_format.WIRETYPE_LENGTH_DELIMITED,
_FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP,
_FieldDescriptor.TYPE_MESSAGE:
wire_format.WIRETYPE_LENGTH_DELIMITED,
_FieldDescriptor.TYPE_BYTES:
wire_format.WIRETYPE_LENGTH_DELIMITED,
_FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32,
_FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64,
_FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT,
}
# Maps from field type to an unbound Decoder method F,
# such that F(decoder) will read a field of the requested type.
#
# Note that Message and Group are intentionally missing here.
# They're handled by _RecursivelyMerge().
_Decoder = decoder.Decoder
_TYPE_TO_DESERIALIZE_METHOD = {
_FieldDescriptor.TYPE_DOUBLE: _Decoder.ReadDouble,
_FieldDescriptor.TYPE_FLOAT: _Decoder.ReadFloat,
_FieldDescriptor.TYPE_INT64: _Decoder.ReadInt64,
_FieldDescriptor.TYPE_UINT64: _Decoder.ReadUInt64,
_FieldDescriptor.TYPE_INT32: _Decoder.ReadInt32,
_FieldDescriptor.TYPE_FIXED64: _Decoder.ReadFixed64,
_FieldDescriptor.TYPE_FIXED32: _Decoder.ReadFixed32,
_FieldDescriptor.TYPE_BOOL: _Decoder.ReadBool,
_FieldDescriptor.TYPE_STRING: _Decoder.ReadString,
_FieldDescriptor.TYPE_BYTES: _Decoder.ReadBytes,
_FieldDescriptor.TYPE_UINT32: _Decoder.ReadUInt32,
_FieldDescriptor.TYPE_ENUM: _Decoder.ReadEnum,
_FieldDescriptor.TYPE_SFIXED32: _Decoder.ReadSFixed32,
_FieldDescriptor.TYPE_SFIXED64: _Decoder.ReadSFixed64,
_FieldDescriptor.TYPE_SINT32: _Decoder.ReadSInt32,
_FieldDescriptor.TYPE_SINT64: _Decoder.ReadSInt64,
}

View file

@ -85,18 +85,14 @@ class Service(object):
class RpcController(object):
"""Abstract interface for an RPC channel.
"""An RpcController mediates a single method call.
An RpcChannel represents a communication line to a service which can be used
to call that service's methods. The service may be running on another
machine. Normally, you should not use an RpcChannel directly, but instead
construct a stub {@link Service} wrapping it. Example:
Example:
RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234")
RpcController controller = rpcImpl.Controller()
MyService service = MyService_Stub(channel)
service.MyMethod(controller, request, callback)
The primary purpose of the controller is to provide a way to manipulate
settings specific to the RPC implementation and to find out about RPC-level
errors. The methods provided by the RpcController interface are intended
to be a "least common denominator" set of features which we expect all
implementations to support. Specific implementations may provide more
advanced features (e.g. deadline propagation).
"""
# Client-side methods below
@ -172,14 +168,18 @@ class RpcController(object):
class RpcChannel(object):
"""An RpcController mediates a single method call.
"""Abstract interface for an RPC channel.
The primary purpose of the controller is to provide a way to manipulate
settings specific to the RPC implementation and to find out about RPC-level
errors. The methods provided by the RpcController interface are intended
to be a "least common denominator" set of features which we expect all
implementations to support. Specific implementations may provide more
advanced features (e.g. deadline propagation).
An RpcChannel represents a communication line to a service which can be used
to call that service's methods. The service may be running on another
machine. Normally, you should not use an RpcChannel directly, but instead
construct a stub {@link Service} wrapping it. Example:
Example:
RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234")
RpcController controller = rpcImpl.Controller()
MyService service = MyService_Stub(channel)
service.MyMethod(controller, request, callback)
"""
def CallMethod(self, method_descriptor, rpc_controller,

View file

@ -35,6 +35,8 @@
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
@ -52,6 +54,12 @@ namespace compiler {
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#endif
#ifndef O_BINARY
@ -82,10 +90,31 @@ static bool IsWindowsAbsolutePath(const string& text) {
#endif
}
void SetFdToTextMode(int fd) {
#ifdef _WIN32
if (_setmode(fd, _O_TEXT) == -1) {
// This should never happen, I think.
GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno);
}
#endif
// (Text and binary are the same on non-Windows platforms.)
}
void SetFdToBinaryMode(int fd) {
#ifdef _WIN32
if (_setmode(fd, _O_BINARY) == -1) {
// This should never happen, I think.
GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno);
}
#endif
// (Text and binary are the same on non-Windows platforms.)
}
} // namespace
// A MultiFileErrorCollector that prints errors to stderr.
class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector {
class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
public io::ErrorCollector {
public:
ErrorPrinter() {}
~ErrorPrinter() {}
@ -101,6 +130,11 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector {
}
cerr << ": " << message << endl;
}
// implements io::ErrorCollector -----------------------------------
void AddError(int line, int column, const string& message) {
AddError("input", line, column, message);
}
};
// -------------------------------------------------------------------
@ -243,7 +277,9 @@ CommandLineInterface::ErrorReportingFileOutput::~ErrorReportingFileOutput() {
// ===================================================================
CommandLineInterface::CommandLineInterface()
: disallow_services_(false),
: mode_(MODE_COMPILE),
imports_in_descriptor_set_(false),
disallow_services_(false),
inputs_are_proto_path_relative_(false) {}
CommandLineInterface::~CommandLineInterface() {}
@ -258,7 +294,7 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name,
int CommandLineInterface::Run(int argc, const char* const argv[]) {
Clear();
if (!ParseArguments(argc, argv)) return -1;
if (!ParseArguments(argc, argv)) return 1;
// Set up the source tree.
DiskSourceTree source_tree;
@ -269,32 +305,61 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
// Map input files to virtual paths if necessary.
if (!inputs_are_proto_path_relative_) {
if (!MakeInputsBeProtoPathRelative(&source_tree)) {
return -1;
return 1;
}
}
// Allocate the Importer.
ErrorPrinter error_collector;
DescriptorPool pool;
Importer importer(&source_tree, &error_collector);
vector<const FileDescriptor*> parsed_files;
// Parse each file and generate output.
for (int i = 0; i < input_files_.size(); i++) {
// Import the file.
const FileDescriptor* parsed_file = importer.Import(input_files_[i]);
if (parsed_file == NULL) return -1;
if (parsed_file == NULL) return 1;
parsed_files.push_back(parsed_file);
// Enforce --disallow_services.
if (disallow_services_ && parsed_file->service_count() > 0) {
cerr << parsed_file->name() << ": This file contains services, but "
"--disallow_services was used." << endl;
return -1;
return 1;
}
// Generate output files.
for (int i = 0; i < output_directives_.size(); i++) {
if (!GenerateOutput(parsed_file, output_directives_[i])) {
return -1;
if (mode_ == MODE_COMPILE) {
// Generate output files.
for (int i = 0; i < output_directives_.size(); i++) {
if (!GenerateOutput(parsed_file, output_directives_[i])) {
return 1;
}
}
}
}
if (!descriptor_set_name_.empty()) {
if (!WriteDescriptorSet(parsed_files)) {
return 1;
}
}
if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) {
if (codec_type_.empty()) {
// HACK: Define an EmptyMessage type to use for decoding.
DescriptorPool pool;
FileDescriptorProto file;
file.set_name("empty_message.proto");
file.add_message_type()->set_name("EmptyMessage");
GOOGLE_CHECK(pool.BuildFile(file) != NULL);
codec_type_ = "EmptyMessage";
if (!EncodeOrDecode(&pool)) {
return 1;
}
} else {
if (!EncodeOrDecode(importer.pool())) {
return 1;
}
}
}
@ -303,9 +368,18 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
}
void CommandLineInterface::Clear() {
// Clear all members that are set by Run(). Note that we must not clear
// members which are set by other methods before Run() is called.
executable_name_.clear();
proto_path_.clear();
input_files_.clear();
output_directives_.clear();
codec_type_.clear();
descriptor_set_name_.clear();
mode_ = MODE_COMPILE;
imports_in_descriptor_set_ = false;
disallow_services_ = false;
}
bool CommandLineInterface::MakeInputsBeProtoPathRelative(
@ -351,9 +425,12 @@ bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
string name, value;
if (ParseArgument(argv[i], &name, &value)) {
// Retured true => Use the next argument as the flag value.
// Returned true => Use the next argument as the flag value.
if (i + 1 == argc || argv[i+1][0] == '-') {
cerr << "Missing value for flag: " << name << endl;
if (name == "--decode") {
cerr << "To decode an unknown message, use --decode_raw." << endl;
}
return false;
} else {
++i;
@ -370,14 +447,23 @@ bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
}
// Check some errror cases.
if (input_files_.empty()) {
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
if (decoding_raw && !input_files_.empty()) {
cerr << "When using --decode_raw, no input files should be given." << endl;
return false;
} else if (!decoding_raw && input_files_.empty()) {
cerr << "Missing input file." << endl;
return false;
}
if (output_directives_.empty()) {
if (mode_ == MODE_COMPILE && output_directives_.empty() &&
descriptor_set_name_.empty()) {
cerr << "Missing output directives." << endl;
return false;
}
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
cerr << "--include_imports only makes sense when combined with "
"--descriptor_set_name." << endl;
}
return true;
}
@ -428,7 +514,9 @@ bool CommandLineInterface::ParseArgument(const char* arg,
if (*name == "-h" || *name == "--help" ||
*name == "--disallow_services" ||
*name == "--version") {
*name == "--include_imports" ||
*name == "--version" ||
*name == "--decode_raw") {
// HACK: These are the only flags that don't take a value.
// They probably should not be hard-coded like this but for now it's
// not worth doing better.
@ -487,6 +575,29 @@ bool CommandLineInterface::InterpretArgument(const string& name,
proto_path_.push_back(make_pair(virtual_path, disk_path));
}
} else if (name == "-o" || name == "--descriptor_set_out") {
if (!descriptor_set_name_.empty()) {
cerr << name << " may only be passed once." << endl;
return false;
}
if (value.empty()) {
cerr << name << " requires a non-empty value." << endl;
return false;
}
if (mode_ != MODE_COMPILE) {
cerr << "Cannot use --encode or --decode and generate descriptors at the "
"same time." << endl;
return false;
}
descriptor_set_name_ = value;
} else if (name == "--include_imports") {
if (imports_in_descriptor_set_) {
cerr << name << " may only be passed once." << endl;
return false;
}
imports_in_descriptor_set_ = true;
} else if (name == "-h" || name == "--help") {
PrintHelpText();
return false; // Exit without running compiler.
@ -503,6 +614,33 @@ bool CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--disallow_services") {
disallow_services_ = true;
} else if (name == "--encode" || name == "--decode" ||
name == "--decode_raw") {
if (mode_ != MODE_COMPILE) {
cerr << "Only one of --encode and --decode can be specified." << endl;
return false;
}
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
cerr << "Cannot use " << name
<< " and generate code or descriptors at the same time." << endl;
return false;
}
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
if (value.empty() && name != "--decode_raw") {
cerr << "Type name for " << name << " cannot be blank." << endl;
if (name == "--decode") {
cerr << "To decode an unknown message, use --decode_raw." << endl;
}
return false;
} else if (!value.empty() && name == "--decode_raw") {
cerr << "--decode_raw does not take a parameter." << endl;
return false;
}
codec_type_ = value;
} else {
// Some other flag. Look it up in the generators list.
GeneratorMap::const_iterator iter = generators_.find(name);
@ -512,6 +650,12 @@ bool CommandLineInterface::InterpretArgument(const string& name,
}
// It's an output flag. Add it to the output directives.
if (mode_ != MODE_COMPILE) {
cerr << "Cannot use --encode or --decode and generate code at the "
"same time." << endl;
return false;
}
OutputDirective directive;
directive.name = name;
directive.generator = iter->second.generator;
@ -536,14 +680,33 @@ bool CommandLineInterface::InterpretArgument(const string& name,
void CommandLineInterface::PrintHelpText() {
// Sorry for indentation here; line wrapping would be uglier.
cerr <<
"Usage: " << executable_name_ << " [OPTION] PROTO_FILE\n"
"Parse PROTO_FILE and generate output based on the options given:\n"
"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
"Parse PROTO_FILES and generate output based on the options given:\n"
" -IPATH, --proto_path=PATH Specify the directory in which to search for\n"
" imports. May be specified multiple times;\n"
" directories will be searched in order. If not\n"
" given, the current working directory is used.\n"
" --version Show version info and exit.\n"
" -h, --help Show this text and exit." << endl;
" -h, --help Show this text and exit.\n"
" --encode=MESSAGE_TYPE Read a text-format message of the given type\n"
" from standard input and write it in binary\n"
" to standard output. The message type must\n"
" be defined in PROTO_FILES or their imports.\n"
" --decode=MESSAGE_TYPE Read a binary message of the given type from\n"
" standard input and write it in text format\n"
" to standard output. The message type must\n"
" be defined in PROTO_FILES or their imports.\n"
" --decode_raw Read an arbitrary protocol message from\n"
" standard input and write the raw tag/value\n"
" pairs in text format to standard output. No\n"
" PROTO_FILES should be given when using this\n"
" flag.\n"
" -oFILE, Writes a FileDescriptorSet (a protocol buffer,\n"
" --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n"
" the input files to FILE.\n"
" --include_imports When using --descriptor_set_out, also include\n"
" all dependencies of the input files in the\n"
" set, so that the set is self-contained." << endl;
for (GeneratorMap::iterator iter = generators_.begin();
iter != generators_.end(); ++iter) {
@ -584,6 +747,116 @@ bool CommandLineInterface::GenerateOutput(
return true;
}
bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
// Look up the type.
const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
if (type == NULL) {
cerr << "Type not defined: " << codec_type_ << endl;
return false;
}
DynamicMessageFactory dynamic_factory(pool);
scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New());
if (mode_ == MODE_ENCODE) {
SetFdToTextMode(STDIN_FILENO);
SetFdToBinaryMode(STDOUT_FILENO);
} else {
SetFdToBinaryMode(STDIN_FILENO);
SetFdToTextMode(STDOUT_FILENO);
}
io::FileInputStream in(STDIN_FILENO);
io::FileOutputStream out(STDOUT_FILENO);
if (mode_ == MODE_ENCODE) {
// Input is text.
ErrorPrinter error_collector;
TextFormat::Parser parser;
parser.RecordErrorsTo(&error_collector);
parser.AllowPartialMessage(true);
if (!parser.Parse(&in, message.get())) {
cerr << "Failed to parse input." << endl;
return false;
}
} else {
// Input is binary.
if (!message->ParsePartialFromZeroCopyStream(&in)) {
cerr << "Failed to parse input." << endl;
return false;
}
}
if (!message->IsInitialized()) {
cerr << "warning: Input message is missing required fields: "
<< message->InitializationErrorString() << endl;
}
if (mode_ == MODE_ENCODE) {
// Output is binary.
if (!message->SerializePartialToZeroCopyStream(&out)) {
cerr << "output: I/O error." << endl;
return false;
}
} else {
// Output is text.
if (!TextFormat::Print(*message, &out)) {
cerr << "output: I/O error." << endl;
return false;
}
}
return true;
}
bool CommandLineInterface::WriteDescriptorSet(
const vector<const FileDescriptor*> parsed_files) {
FileDescriptorSet file_set;
set<const FileDescriptor*> already_added;
vector<const FileDescriptor*> to_add(parsed_files);
while (!to_add.empty()) {
const FileDescriptor* file = to_add.back();
to_add.pop_back();
if (already_added.insert(file).second) {
// This file was not already in the set.
file->CopyTo(file_set.add_file());
if (imports_in_descriptor_set_) {
// Add all of this file's dependencies.
for (int i = 0; i < file->dependency_count(); i++) {
to_add.push_back(file->dependency(i));
}
}
}
}
int fd;
do {
fd = open(descriptor_set_name_.c_str(),
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
} while (fd < 0 && errno == EINTR);
if (fd < 0) {
perror(descriptor_set_name_.c_str());
return false;
}
io::FileOutputStream out(fd);
if (!file_set.SerializeToZeroCopyStream(&out)) {
cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
out.Close();
return false;
}
if (!out.Close()) {
cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
return false;
}
return true;
}
} // namespace compiler
} // namespace protobuf

View file

@ -35,6 +35,7 @@ namespace google {
namespace protobuf {
class FileDescriptor; // descriptor.h
class DescriptorPool; // descriptor.h
namespace compiler {
@ -164,6 +165,12 @@ class LIBPROTOC_EXPORT CommandLineInterface {
bool GenerateOutput(const FileDescriptor* proto_file,
const OutputDirective& output_directive);
// Implements --encode and --decode.
bool EncodeOrDecode(const DescriptorPool* pool);
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
// -----------------------------------------------------------------
// The name of the executable as invoked (i.e. argv[0]).
@ -181,6 +188,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
GeneratorMap generators_;
// Stuff parsed from command line.
enum Mode {
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
MODE_ENCODE, // --encode: read text from stdin, write binary to stdout.
MODE_DECODE // --decode: read binary from stdin, write text to stdout.
};
Mode mode_;
vector<pair<string, string> > proto_path_; // Search path for proto files.
vector<string> input_files_; // Names of the input proto files.
@ -194,6 +209,19 @@ class LIBPROTOC_EXPORT CommandLineInterface {
};
vector<OutputDirective> output_directives_;
// When using --encode or --decode, this names the type we are encoding or
// decoding. (Empty string indicates --decode_raw.)
string codec_type_;
// If --descriptor_set_out was given, this is the filename to which the
// FileDescriptorSet should be written. Otherwise, empty.
string descriptor_set_name_;
// True if --include_imports was given, meaning that we should
// write all transitive dependencies to the DescriptorSet. Otherwise, only
// the .proto files listed on the command-line are added.
bool imports_in_descriptor_set_;
// Was the --disallow_services flag used?
bool disallow_services_;

View file

@ -18,13 +18,23 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#endif
#include <vector>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/stubs/strutil.h>
@ -35,6 +45,15 @@ namespace google {
namespace protobuf {
namespace compiler {
#if defined(_WIN32)
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#endif
namespace {
class CommandLineInterfaceTest : public testing::Test {
@ -110,6 +129,9 @@ class CommandLineInterfaceTest : public testing::Test {
const string& message_name,
const string& output_file);
void ReadDescriptorSet(const string& filename,
FileDescriptorSet* descriptor_set);
private:
// The object we are testing.
CommandLineInterface cli_;
@ -333,6 +355,18 @@ void CommandLineInterfaceTest::ExpectGenerated(
<< "Output file did not have expected contents: " + output_file;
}
void CommandLineInterfaceTest::ReadDescriptorSet(
const string& filename, FileDescriptorSet* descriptor_set) {
string path = temp_directory_ + "/" + filename;
string file_contents;
if (!File::ReadFileToString(path, &file_contents)) {
FAIL() << "File not found: " << path;
}
if (!descriptor_set->ParseFromString(file_contents)) {
FAIL() << "Could not parse file contents: " << path;
}
}
// ===================================================================
CommandLineInterfaceTest::MockCodeGenerator::MockCodeGenerator(
@ -665,6 +699,57 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
}
TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
CreateTempFile("bar.proto",
"syntax = \"proto2\";\n"
"import \"foo.proto\";\n"
"message Bar {\n"
" optional Foo foo = 1;\n"
"}\n");
Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
"--proto_path=$tmpdir bar.proto");
ExpectNoErrors();
FileDescriptorSet descriptor_set;
ReadDescriptorSet("descriptor_set", &descriptor_set);
if (HasFatalFailure()) return;
ASSERT_EQ(1, descriptor_set.file_size());
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
}
TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
CreateTempFile("bar.proto",
"syntax = \"proto2\";\n"
"import \"foo.proto\";\n"
"message Bar {\n"
" optional Foo foo = 1;\n"
"}\n");
Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
"--include_imports --proto_path=$tmpdir bar.proto");
ExpectNoErrors();
FileDescriptorSet descriptor_set;
ReadDescriptorSet("descriptor_set", &descriptor_set);
if (HasFatalFailure()) return;
ASSERT_EQ(2, descriptor_set.file_size());
if (descriptor_set.file(0).name() == "bar.proto") {
swap(descriptor_set.mutable_file()->mutable_data()[0],
descriptor_set.mutable_file()->mutable_data()[1]);
}
EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
}
// -------------------------------------------------------------------
TEST_F(CommandLineInterfaceTest, ParseErrors) {
@ -954,14 +1039,14 @@ TEST_F(CommandLineInterfaceTest, HelpText) {
TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
// Test that a single-character flag works.
RegisterGenerator("test_generator", "-o",
RegisterGenerator("test_generator", "-t",
"output.test", "Test output.");
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
Run("protocol_compiler -o$tmpdir "
Run("protocol_compiler -t$tmpdir "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
@ -989,14 +1074,14 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
// Test that separating the flag value with a space works for
// single-character flags.
RegisterGenerator("test_generator", "-o",
RegisterGenerator("test_generator", "-t",
"output.test", "Test output.");
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
Run("protocol_compiler -o $tmpdir "
Run("protocol_compiler -t $tmpdir "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
@ -1026,6 +1111,166 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
ExpectErrorText("Missing value for flag: --test_out\n");
}
// ===================================================================
// Test for --encode and --decode. Note that it would be easier to do this
// test as a shell script, but we'd like to be able to run the test on
// platforms that don't have a Bourne-compatible shell available (especially
// Windows/MSVC).
class EncodeDecodeTest : public testing::Test {
protected:
virtual void SetUp() {
duped_stdin_ = dup(STDIN_FILENO);
}
virtual void TearDown() {
dup2(duped_stdin_, STDIN_FILENO);
close(duped_stdin_);
}
void RedirectStdinFromText(const string& input) {
string filename = TestTempDir() + "/test_stdin";
File::WriteStringToFileOrDie(input, filename);
GOOGLE_CHECK(RedirectStdinFromFile(filename));
}
bool RedirectStdinFromFile(const string& filename) {
int fd = open(filename.c_str(), O_RDONLY);
if (fd < 0) return false;
dup2(fd, STDIN_FILENO);
close(fd);
return true;
}
// Remove '\r' characters from text.
string StripCR(const string& text) {
string result;
for (int i = 0; i < text.size(); i++) {
if (text[i] != '\r') {
result.push_back(text[i]);
}
}
return result;
}
enum Type { TEXT, BINARY };
enum ReturnCode { SUCCESS, ERROR };
bool Run(const string& command) {
vector<string> args;
args.push_back("protoc");
SplitStringUsing(command, " ", &args);
args.push_back("--proto_path=" + TestSourceDir());
scoped_array<const char*> argv(new const char*[args.size()]);
for (int i = 0; i < args.size(); i++) {
argv[i] = args[i].c_str();
}
CommandLineInterface cli;
cli.SetInputsAreProtoPathRelative(true);
CaptureTestStdout();
CaptureTestStderr();
int result = cli.Run(args.size(), argv.get());
captured_stdout_ = GetCapturedTestStdout();
captured_stderr_ = GetCapturedTestStderr();
return result == 0;
}
void ExpectStdoutMatchesBinaryFile(const string& filename) {
string expected_output;
ASSERT_TRUE(File::ReadFileToString(filename, &expected_output));
// Don't use EXPECT_EQ because we don't want to print raw binary data to
// stdout on failure.
EXPECT_TRUE(captured_stdout_ == expected_output);
}
void ExpectStdoutMatchesTextFile(const string& filename) {
string expected_output;
ASSERT_TRUE(File::ReadFileToString(filename, &expected_output));
ExpectStdoutMatchesText(expected_output);
}
void ExpectStdoutMatchesText(const string& expected_text) {
EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_));
}
void ExpectStderrMatchesText(const string& expected_text) {
EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_));
}
private:
int duped_stdin_;
string captured_stdout_;
string captured_stderr_;
};
TEST_F(EncodeDecodeTest, Encode) {
RedirectStdinFromFile(TestSourceDir() +
"/google/protobuf/testdata/text_format_unittest_data.txt");
EXPECT_TRUE(Run("google/protobuf/unittest.proto "
"--encode=protobuf_unittest.TestAllTypes"));
ExpectStdoutMatchesBinaryFile(TestSourceDir() +
"/google/protobuf/testdata/golden_message");
ExpectStderrMatchesText("");
}
TEST_F(EncodeDecodeTest, Decode) {
RedirectStdinFromFile(TestSourceDir() +
"/google/protobuf/testdata/golden_message");
EXPECT_TRUE(Run("google/protobuf/unittest.proto "
"--decode=protobuf_unittest.TestAllTypes"));
ExpectStdoutMatchesTextFile(TestSourceDir() +
"/google/protobuf/testdata/text_format_unittest_data.txt");
ExpectStderrMatchesText("");
}
TEST_F(EncodeDecodeTest, Partial) {
RedirectStdinFromText("");
EXPECT_TRUE(Run("google/protobuf/unittest.proto "
"--encode=protobuf_unittest.TestRequired"));
ExpectStdoutMatchesText("");
ExpectStderrMatchesText(
"warning: Input message is missing required fields: a, b, c\n");
}
TEST_F(EncodeDecodeTest, DecodeRaw) {
protobuf_unittest::TestAllTypes message;
message.set_optional_int32(123);
message.set_optional_string("foo");
string data;
message.SerializeToString(&data);
RedirectStdinFromText(data);
EXPECT_TRUE(Run("--decode_raw"));
ExpectStdoutMatchesText("1: 123\n"
"14: \"foo\"\n");
ExpectStderrMatchesText("");
}
TEST_F(EncodeDecodeTest, UnknownType) {
EXPECT_FALSE(Run("google/protobuf/unittest.proto "
"--encode=NoSuchType"));
ExpectStdoutMatchesText("");
ExpectStderrMatchesText("Type not defined: NoSuchType\n");
}
TEST_F(EncodeDecodeTest, ProtoParseError) {
EXPECT_FALSE(Run("google/protobuf/no_such_file.proto "
"--encode=NoSuchType"));
ExpectStdoutMatchesText("");
ExpectStderrMatchesText(
"google/protobuf/no_such_file.proto: File not found.\n");
}
} // anonymous namespace
} // namespace compiler

View file

@ -128,7 +128,14 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// Open namespace.
GenerateNamespaceOpeners(printer);
printer->Print("\n");
// Forward-declare the BuildDescriptors function, so that we can declare it
// to be a friend of each class.
printer->Print(
"\n"
"// Internal implementation detail -- do not call this.\n"
"void $builddescriptorsname$();\n"
"\n",
"builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
// Generate forward declarations of classes.
for (int i = 0; i < file_->message_type_count(); i++) {
@ -302,6 +309,9 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// time, because every message has a statically-initialized default instance,
// and the constructor for a message class accesses its descriptor. See the
// constructor and the descriptor() method of message classes.
//
// We also construct the reflection object for each class inside
// BuildDescriptors().
printer->Print(
"\n"
"void $builddescriptorsname$() {\n"

View file

@ -188,7 +188,7 @@ string FilenameIdentifier(const string& filename) {
// Return the name of the BuildDescriptors() function for a given file.
string GlobalBuildDescriptorsName(const string& filename) {
return "proto_BuildDescriptors_" + FilenameIdentifier(filename);
return "protobuf_BuildDesc_" + FilenameIdentifier(filename);
}
} // namespace cpp

View file

@ -374,6 +374,8 @@ GenerateClassDefinition(io::Printer* printer) {
} else {
vars["dllexport"] = dllexport_decl_ + " ";
}
vars["builddescriptorsname"] =
GlobalBuildDescriptorsName(descriptor_->file()->name());
printer->Print(vars,
"class $dllexport$$classname$ : public ::google::protobuf::Message {\n"
@ -396,11 +398,11 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n"
"inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
" return _reflection_.unknown_fields();\n"
" return _unknown_fields_;\n"
"}\n"
"\n"
"inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
" return _reflection_.mutable_unknown_fields();\n"
" return &_unknown_fields_;\n"
"}\n"
"\n"
"static const ::google::protobuf::Descriptor* descriptor();\n"
@ -432,8 +434,7 @@ GenerateClassDefinition(io::Printer* printer) {
"public:\n"
"\n"
"const ::google::protobuf::Descriptor* GetDescriptor() const;\n"
"const ::google::protobuf::Message::Reflection* GetReflection() const;\n"
"::google::protobuf::Message::Reflection* GetReflection();\n"
"const ::google::protobuf::Reflection* GetReflection() const;\n"
"\n"
"// nested types ----------------------------------------------------\n"
"\n");
@ -481,7 +482,7 @@ GenerateClassDefinition(io::Printer* printer) {
// TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
printer->Print(
"::google::protobuf::internal::GeneratedMessageReflection _reflection_;\n"
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
"mutable int _cached_size_;\n"
"\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
@ -491,7 +492,7 @@ GenerateClassDefinition(io::Printer* printer) {
// Generate offsets and _has_bits_ boilerplate.
printer->Print(vars,
"\n"
"friend void $builddescriptorsname$();\n"
"static const $classname$ default_instance_;\n");
if (descriptor_->field_count() > 0) {
@ -540,8 +541,11 @@ GenerateInlineMethods(io::Printer* printer) {
void MessageGenerator::
GenerateDescriptorDeclarations(io::Printer* printer) {
printer->Print("const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n",
"name", classname_);
printer->Print(
"const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
"const ::google::protobuf::internal::GeneratedMessageReflection*\n"
" $name$_reflection_ = NULL;\n",
"name", classname_);
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateDescriptorDeclarations(printer);
@ -562,6 +566,7 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
vars["classname"] = classname_;
vars["index"] = SimpleItoa(index);
// Obtain the descriptor from the parent's descriptor.
if (descriptor_->containing_type() == NULL) {
printer->Print(vars,
"$classname$_descriptor_ = file->message_type($index$);\n");
@ -572,6 +577,29 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
"$parent$_descriptor_->nested_type($index$);\n");
}
// Construct the reflection object.
printer->Print(vars,
"$classname$_reflection_ =\n"
" new ::google::protobuf::internal::GeneratedMessageReflection(\n"
" $classname$_descriptor_,\n"
" &$classname$::default_instance(),\n"
" $classname$::_offsets_,\n"
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
"$classname$, _unknown_fields_),\n");
if (descriptor_->extension_range_count() > 0) {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
"$classname$, _extensions_),\n");
} else {
// No extensions.
printer->Print(vars,
" -1,\n");
}
printer->Print(vars,
" ::google::protobuf::DescriptorPool::generated_pool());\n");
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
@ -650,15 +678,13 @@ GenerateClassMethods(io::Printer* printer) {
" return descriptor();\n"
"}\n"
"\n"
"const ::google::protobuf::Message::Reflection*\n"
"$classname$::GetReflection() const {\n"
" return &_reflection_;\n"
"}\n"
"\n"
"::google::protobuf::Message::Reflection* $classname$::GetReflection() {\n"
" return &_reflection_;\n"
"const ::google::protobuf::Reflection* $classname$::GetReflection() const {\n"
" if ($classname$_reflection_ == NULL) $builddescriptorsname$();\n"
" return $classname$_reflection_;\n"
"}\n",
"classname", classname_);
"classname", classname_,
"builddescriptorsname",
GlobalBuildDescriptorsName(descriptor_->file()->name()));
}
void MessageGenerator::
@ -686,20 +712,16 @@ GenerateInitializerList(io::Printer* printer) {
printer->Indent();
printer->Indent();
bool has_extensions = descriptor_->extension_range_count() > 0;
if (has_extensions) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"_extensions_(descriptor(),\n"
"_extensions_(&$classname$_descriptor_,\n"
" ::google::protobuf::DescriptorPool::generated_pool(),\n"
" ::google::protobuf::MessageFactory::generated_factory()),\n");
" ::google::protobuf::MessageFactory::generated_factory()),\n",
"classname", classname_);
}
printer->Print(
"_reflection_(descriptor(),\n"
" this, &default_instance_,\n"
" _offsets_, _has_bits_, $extensions$),\n"
"_cached_size_(0)",
"extensions", has_extensions ? "&_extensions_" : "NULL");
"_cached_size_(0)");
// Write the initializers for each field.
for (int i = 0; i < descriptor_->field_count(); i++) {
@ -904,8 +926,7 @@ GenerateMergeFrom(io::Printer* printer) {
" ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
" &from);\n"
"if (source == NULL) {\n"
" ::google::protobuf::internal::ReflectionOps::Merge(\n"
" descriptor(), *from.GetReflection(), &_reflection_);\n"
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
"} else {\n"
" MergeFrom(*source);\n"
"}\n",
@ -1028,7 +1049,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
"bool $classname$::MergePartialFromCodedStream(\n"
" ::google::protobuf::io::CodedInputStream* input) {\n"
" return ::google::protobuf::internal::WireFormat::ParseAndMergePartial(\n"
" descriptor(), input, &_reflection_);\n"
" input, this);\n"
"}\n",
"classname", classname_);
return;
@ -1157,7 +1178,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
}
printer->Print(") {\n"
" DO_(_extensions_.ParseField(tag, input, &_reflection_));\n"
" DO_(_extensions_.ParseField(tag, input, this));\n"
" continue;\n"
"}\n");
}
@ -1214,7 +1235,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
printer->Print(vars,
"// Extension range [$start$, $end$)\n"
"DO_(_extensions_.SerializeWithCachedSizes(\n"
" $start$, $end$, &_reflection_, output));\n\n");
" $start$, $end$, *this, output));\n\n");
}
void MessageGenerator::
@ -1341,7 +1362,7 @@ GenerateByteSize(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"total_size += _extensions_.ByteSize(&_reflection_);\n"
"total_size += _extensions_.ByteSize(*this);\n"
"\n");
}

View file

@ -268,7 +268,7 @@ TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
TestUtil::ReflectionTester reflection_tester(
unittest::TestAllTypes::descriptor());
reflection_tester.SetAllFieldsViaReflection(message1->GetReflection());
reflection_tester.SetAllFieldsViaReflection(message1.get());
message2.CopyFrom(*message1);

View file

@ -604,7 +604,7 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) {
}
bool Parser::ParseOptionAssignment(Message* options) {
Message::Reflection* reflection = options->GetReflection();
const Reflection* reflection = options->GetReflection();
const Descriptor* descriptor = options->GetDescriptor();
// Parse name.
@ -623,7 +623,7 @@ bool Parser::ParseOptionAssignment(Message* options) {
AddError(line, column, "Not implemented: repeated options.");
return false;
}
if (reflection->HasField(field)) {
if (reflection->HasField(*options, field)) {
AddError(line, column, "Option \"" + name + "\" was already set.");
return false;
}
@ -638,7 +638,7 @@ bool Parser::ParseOptionAssignment(Message* options) {
// This field is a message/group. The user must identify a field within
// it to set.
return ParseOptionAssignment(reflection->MutableMessage(field));
return ParseOptionAssignment(reflection->MutableMessage(options, field));
}
DO(Consume("="));
@ -651,7 +651,7 @@ bool Parser::ParseOptionAssignment(Message* options) {
uint64 max_value = kint32max;
if (is_negative) ++max_value;
DO(ConsumeInteger64(max_value, &value, "Expected integer."));
reflection->SetInt32(field, is_negative ? -value : value);
reflection->SetInt32(options, field, is_negative ? -value : value);
break;
}
@ -661,21 +661,21 @@ bool Parser::ParseOptionAssignment(Message* options) {
uint64 max_value = kint64max;
if (is_negative) ++max_value;
DO(ConsumeInteger64(max_value, &value, "Expected integer."));
reflection->SetInt64(field, is_negative ? -value : value);
reflection->SetInt64(options, field, is_negative ? -value : value);
break;
}
case FieldDescriptor::CPPTYPE_UINT32: {
uint64 value;
DO(ConsumeInteger64(kuint32max, &value, "Expected integer."));
reflection->SetUInt32(field, value);
reflection->SetUInt32(options, field, value);
break;
}
case FieldDescriptor::CPPTYPE_UINT64: {
uint64 value;
DO(ConsumeInteger64(kuint64max, &value, "Expected integer."));
reflection->SetUInt64(field, value);
reflection->SetUInt64(options, field, value);
break;
}
@ -683,7 +683,7 @@ bool Parser::ParseOptionAssignment(Message* options) {
double value;
bool is_negative = TryConsume("-");
DO(ConsumeNumber(&value, "Expected number."));
reflection->SetDouble(field, is_negative ? -value : value);
reflection->SetDouble(options, field, is_negative ? -value : value);
break;
}
@ -691,15 +691,15 @@ bool Parser::ParseOptionAssignment(Message* options) {
double value;
bool is_negative = TryConsume("-");
DO(ConsumeNumber(&value, "Expected number."));
reflection->SetFloat(field, is_negative ? -value : value);
reflection->SetFloat(options, field, is_negative ? -value : value);
break;
}
case FieldDescriptor::CPPTYPE_BOOL:
if (TryConsume("true")) {
reflection->SetBool(field, true);
reflection->SetBool(options, field, true);
} else if (TryConsume("false")) {
reflection->SetBool(field, false);
reflection->SetBool(options, field, false);
} else {
AddError("Expected \"true\" or \"false\".");
return false;
@ -719,14 +719,14 @@ bool Parser::ParseOptionAssignment(Message* options) {
"named \"" + value_name + "\".");
return false;
}
reflection->SetEnum(field, value);
reflection->SetEnum(options, field, value);
break;
}
case FieldDescriptor::CPPTYPE_STRING: {
string value;
DO(ConsumeString(&value, "Expected string."));
reflection->SetString(field, value);
reflection->SetString(options, field, value);
break;
}

View file

@ -1232,9 +1232,9 @@ namespace {
// Used by each of the option formatters.
bool RetrieveOptions(const Message &options, vector<string> *option_entries) {
option_entries->clear();
const Message::Reflection *reflection = options.GetReflection();
const Reflection* reflection = options.GetReflection();
vector<const FieldDescriptor*> fields;
reflection->ListFields(&fields);
reflection->ListFields(options, &fields);
for (int i = 0; i < fields.size(); i++) {
// Doesn't make sense to have message type fields here
if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
@ -1243,7 +1243,7 @@ bool RetrieveOptions(const Message &options, vector<string> *option_entries) {
int count = 1;
bool repeated = false;
if (fields[i]->is_repeated()) {
count = reflection->FieldSize(fields[i]);
count = reflection->FieldSize(options, fields[i]);
repeated = true;
}
for (int j = 0; j < count; j++) {

View file

@ -232,9 +232,9 @@ class LIBPROTOBUF_EXPORT Descriptor {
// call Descriptor::FindExtensionByName() or
// FileDescriptor::FindExtensionByName().
// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber().
// - Given a Message::Reflection for a message object, call
// Message::Reflection::FindKnownExtensionByName() or
// Message::Reflection::FindKnownExtensionByNumber().
// - Given a Reflection for a message object, call
// Reflection::FindKnownExtensionByName() or
// Reflection::FindKnownExtensionByNumber().
// Use DescriptorPool to construct your own descriptors.
class LIBPROTOBUF_EXPORT FieldDescriptor {
public:

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 2000000
#if GOOGLE_PROTOBUF_VERSION < 2000001
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
@ -25,6 +25,10 @@
namespace google {
namespace protobuf {
// Internal implementation detail -- do not call this.
void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
class FileDescriptorSet;
class FileDescriptorProto;
class DescriptorProto;
class DescriptorProto_ExtensionRange;
@ -96,6 +100,92 @@ const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRIN
// ===================================================================
class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message {
public:
FileDescriptorSet();
virtual ~FileDescriptorSet();
FileDescriptorSet(const FileDescriptorSet& from);
inline FileDescriptorSet& operator=(const FileDescriptorSet& from) {
CopyFrom(from);
return *this;
}
inline static const FileDescriptorSet& default_instance() {
return default_instance_;
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
// implements Message ----------------------------------------------
FileDescriptorSet* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const FileDescriptorSet& from);
void MergeFrom(const FileDescriptorSet& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
bool SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// repeated .google.protobuf.FileDescriptorProto file = 1;
inline int file_size() const;
inline void clear_file();
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& file() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file();
inline const ::google::protobuf::FileDescriptorProto& file(int index) const;
inline ::google::protobuf::FileDescriptorProto* mutable_file(int index);
inline ::google::protobuf::FileDescriptorProto* add_file();
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const FileDescriptorSet default_instance_;
static const int _offsets_[1];
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
}
inline void _set_bit(int index) {
_has_bits_[index / 32] |= (1u << (index % 32));
}
inline void _clear_bit(int index) {
_has_bits_[index / 32] &= ~(1u << (index % 32));
}
};
// -------------------------------------------------------------------
class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Message {
public:
FileDescriptorProto();
@ -113,11 +203,11 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -143,8 +233,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -222,7 +311,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline ::google::protobuf::FileOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
@ -235,7 +324,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
::google::protobuf::FileOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const FileDescriptorProto default_instance_;
static const int _offsets_[8];
@ -271,11 +360,11 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -301,8 +390,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -321,12 +409,12 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
inline void set_end(::google::protobuf::int32 value);
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::int32 start_;
::google::protobuf::int32 end_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const DescriptorProto_ExtensionRange default_instance_;
static const int _offsets_[2];
@ -362,11 +450,11 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -392,8 +480,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -461,7 +548,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline ::google::protobuf::MessageOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
@ -472,7 +559,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
::google::protobuf::MessageOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const DescriptorProto default_instance_;
static const int _offsets_[7];
@ -508,11 +595,11 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -538,8 +625,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -649,7 +735,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline ::google::protobuf::FieldOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
@ -664,7 +750,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
::std::string* default_value_;
static const ::std::string _default_default_value_;
::google::protobuf::FieldOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const FieldDescriptorProto default_instance_;
static const int _offsets_[8];
@ -700,11 +786,11 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -730,8 +816,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -761,14 +846,14 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline ::google::protobuf::EnumOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
static const ::std::string _default_name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
::google::protobuf::EnumOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const EnumDescriptorProto default_instance_;
static const int _offsets_[3];
@ -804,11 +889,11 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -834,8 +919,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -862,14 +946,14 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline ::google::protobuf::EnumValueOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
static const ::std::string _default_name_;
::google::protobuf::int32 number_;
::google::protobuf::EnumValueOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const EnumValueDescriptorProto default_instance_;
static const int _offsets_[3];
@ -905,11 +989,11 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -935,8 +1019,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -966,14 +1049,14 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline ::google::protobuf::ServiceOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
static const ::std::string _default_name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
::google::protobuf::ServiceOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const ServiceDescriptorProto default_instance_;
static const int _offsets_[3];
@ -1009,11 +1092,11 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1039,8 +1122,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -1077,7 +1159,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline ::google::protobuf::MethodOptions* mutable_options();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* name_;
@ -1087,7 +1169,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
::std::string* output_type_;
static const ::std::string _default_output_type_;
::google::protobuf::MethodOptions* options_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const MethodDescriptorProto default_instance_;
static const int _offsets_[4];
@ -1123,11 +1205,11 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1153,8 +1235,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -1204,7 +1285,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::std::string* java_package_;
@ -1213,7 +1294,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
static const ::std::string _default_java_outer_classname_;
bool java_multiple_files_;
int optimize_for_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const FileOptions default_instance_;
static const int _offsets_[4];
@ -1249,11 +1330,11 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1279,8 +1360,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -1293,11 +1373,11 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
inline void set_message_set_wire_format(bool value);
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
bool message_set_wire_format_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const MessageOptions default_instance_;
static const int _offsets_[1];
@ -1333,11 +1413,11 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1363,8 +1443,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
@ -1400,13 +1479,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline ::std::string* mutable_experimental_map_key();
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
int ctype_;
::std::string* experimental_map_key_;
static const ::std::string _default_experimental_map_key_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const FieldOptions default_instance_;
static const int _offsets_[2];
@ -1442,11 +1521,11 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1472,18 +1551,17 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const EnumOptions default_instance_;
static const int _offsets_[1];
@ -1519,11 +1597,11 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1549,18 +1627,17 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const EnumValueOptions default_instance_;
static const int _offsets_[1];
@ -1596,11 +1673,11 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1626,18 +1703,17 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const ServiceOptions default_instance_;
static const int _offsets_[1];
@ -1673,11 +1749,11 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _reflection_.unknown_fields();
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return _reflection_.mutable_unknown_fields();
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
@ -1703,18 +1779,17 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
public:
const ::google::protobuf::Descriptor* GetDescriptor() const;
const ::google::protobuf::Message::Reflection* GetReflection() const;
::google::protobuf::Message::Reflection* GetReflection();
const ::google::protobuf::Reflection* GetReflection() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
private:
::google::protobuf::internal::GeneratedMessageReflection _reflection_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
static const MethodOptions default_instance_;
static const int _offsets_[1];
@ -1739,6 +1814,35 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
// ===================================================================
// FileDescriptorSet
// repeated .google.protobuf.FileDescriptorProto file = 1;
inline int FileDescriptorSet::file_size() const {
return file_.size();
}
inline void FileDescriptorSet::clear_file() {
file_.Clear();
}
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
FileDescriptorSet::file() const {
return file_;
}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
FileDescriptorSet::mutable_file() {
return &file_;
}
inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
return file_.Get(index);
}
inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
return file_.Mutable(index);
}
inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
return file_.Add();
}
// -------------------------------------------------------------------
// FileDescriptorProto
// optional string name = 1;

View file

@ -32,6 +32,12 @@ option java_outer_classname = "DescriptorProtos";
// algorithms don't work during bootstrapping.
option optimize_for = SPEED;
// The protocol compiler can output a FileDescriptorSet containing the .proto
// files it parses.
message FileDescriptorSet {
repeated FileDescriptorProto file = 1;
}
// Describes a complete .proto file.
message FileDescriptorProto {
optional string name = 1; // file name, relative to root of source tree

View file

@ -23,7 +23,7 @@
// Then, we use GeneratedMessageReflection to implement our reflection
// interface. All the other operations we need to implement (e.g.
// parsing, copying, etc.) are already implemented in terms of
// Message::Reflection, so the rest is easy.
// Reflection, so the rest is easy.
//
// The up side of this strategy is that it's very efficient. We don't
// need to use hash_maps or generic representations of fields. The
@ -141,6 +141,14 @@ inline int DivideRoundingUp(int i, int j) {
return (i + (j - 1)) / j;
}
static const int kSafeAlignment = sizeof(uint64);
// Rounds the given byte offset up to the next offset aligned such that any
// type may be stored at it.
inline int AlignOffset(int offset) {
return DivideRoundingUp(offset, kSafeAlignment) * kSafeAlignment;
}
#define bitsizeof(T) (sizeof(T) * 8)
} // namespace
@ -149,14 +157,29 @@ inline int DivideRoundingUp(int i, int j) {
class DynamicMessage : public Message {
public:
DynamicMessage(const Descriptor* descriptor,
uint8* base, const uint8* prototype_base,
int size, const int offsets[],
const DescriptorPool* pool, DynamicMessageFactory* factory);
struct TypeInfo {
int size;
int has_bits_offset;
int unknown_fields_offset;
int extensions_offset;
// Not owned by the TypeInfo.
DynamicMessageFactory* factory; // The factory that created this object.
const DescriptorPool* pool; // The factory's DescriptorPool.
const Descriptor* type; // Type of this DynamicMessage.
// Warning: The order in which the following pointers are defined is
// important (the prototype must be deleted *before* the offsets).
scoped_array<int> offsets;
scoped_ptr<const GeneratedMessageReflection> reflection;
scoped_ptr<const DynamicMessage> prototype;
};
DynamicMessage(const TypeInfo* type_info);
~DynamicMessage();
// Called on the prototype after construction to initialize message fields.
void CrossLinkPrototypes(DynamicMessageFactory* factory);
void CrossLinkPrototypes();
// implements Message ----------------------------------------------
@ -167,47 +190,32 @@ class DynamicMessage : public Message {
const Descriptor* GetDescriptor() const;
const Reflection* GetReflection() const;
Reflection* GetReflection();
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
inline bool is_prototype() { return base_ == prototype_base_; }
inline bool is_prototype() const {
return type_info_->prototype == this ||
// If type_info_->prototype is NULL, then we must be constructing
// the prototype now, which means we must be the prototype.
type_info_->prototype == NULL;
}
const Descriptor* descriptor_;
const DescriptorPool* descriptor_pool_;
DynamicMessageFactory* factory_;
scoped_ptr<ExtensionSet> extensions_;
GeneratedMessageReflection reflection_;
uint8* base_;
const uint8* prototype_base_;
const int* offsets_;
int size_;
inline void* OffsetToPointer(int offset) {
return reinterpret_cast<uint8*>(this) + offset;
}
inline const void* OffsetToPointer(int offset) const {
return reinterpret_cast<const uint8*>(this) + offset;
}
const TypeInfo* type_info_;
// TODO(kenton): Make this an atomic<int> when C++ supports it.
mutable int cached_byte_size_;
};
DynamicMessage::DynamicMessage(const Descriptor* descriptor,
uint8* base, const uint8* prototype_base,
int size, const int offsets[],
const DescriptorPool* pool,
DynamicMessageFactory* factory)
: descriptor_(descriptor),
descriptor_pool_((pool == NULL) ? descriptor->file()->pool() : pool),
factory_(factory),
extensions_(descriptor->extension_range_count() > 0 ?
new ExtensionSet(descriptor, descriptor_pool_, factory_) :
NULL),
reflection_(descriptor, base, prototype_base, offsets,
// has_bits
reinterpret_cast<uint32*>(base + size) -
DivideRoundingUp(descriptor->field_count(), bitsizeof(uint32)),
extensions_.get()),
base_(base),
prototype_base_(prototype_base),
offsets_(offsets),
size_(size),
DynamicMessage::DynamicMessage(const TypeInfo* type_info)
: type_info_(type_info),
cached_byte_size_(0) {
// We need to call constructors for various fields manually and set
// default values where appropriate. We use placement new to call
@ -217,9 +225,19 @@ DynamicMessage::DynamicMessage(const Descriptor* descriptor,
// any time you are trying to convert untyped memory to typed memory, though
// in practice that's not strictly necessary for types that don't have a
// constructor.)
const Descriptor* descriptor = type_info_->type;
new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
if (type_info_->extensions_offset != -1) {
new(OffsetToPointer(type_info_->extensions_offset))
ExtensionSet(&type_info_->type, type_info_->pool, type_info_->factory);
}
for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor* field = descriptor->field(i);
void* field_ptr = base + offsets[i];
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
switch (field->cpp_type()) {
#define HANDLE_TYPE(CPPTYPE, TYPE) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
@ -254,7 +272,8 @@ DynamicMessage::DynamicMessage(const Descriptor* descriptor,
} else {
string* default_value =
*reinterpret_cast<string* const*>(
prototype_base + offsets[i]);
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]));
new(field_ptr) string*(default_value);
}
} else {
@ -272,7 +291,8 @@ DynamicMessage::DynamicMessage(const Descriptor* descriptor,
} else {
const RepeatedPtrField<Message>* prototype_field =
reinterpret_cast<const RepeatedPtrField<Message>*>(
prototype_base + offsets[i]);
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]));
new(field_ptr) RepeatedPtrField<Message>(
prototype_field->prototype());
}
@ -284,16 +304,25 @@ DynamicMessage::DynamicMessage(const Descriptor* descriptor,
}
DynamicMessage::~DynamicMessage() {
const Descriptor* descriptor = type_info_->type;
reinterpret_cast<UnknownFieldSet*>(
OffsetToPointer(type_info_->unknown_fields_offset))->~UnknownFieldSet();
if (type_info_->extensions_offset != -1) {
reinterpret_cast<ExtensionSet*>(
OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet();
}
// We need to manually run the destructors for repeated fields and strings,
// just as we ran their constructors in the the DynamicMessage constructor.
// Additionally, if any singular embedded messages have been allocated, we
// need to delete them, UNLESS we are the prototype message of this type,
// in which case any embedded messages are other prototypes and shouldn't
// be touched.
const Descriptor* descriptor = GetDescriptor();
for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor* field = descriptor->field(i);
void* field_ptr = base_ + offsets_[i];
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
if (field->is_repeated()) {
GenericRepeatedField* field =
@ -313,26 +342,19 @@ DynamicMessage::~DynamicMessage() {
}
}
}
// OK, now we can delete our base pointer.
operator delete(base_);
// When the prototype is deleted, we also want to free the offsets table.
// (The prototype is only deleted when the factory that created it is
// deleted.)
if (is_prototype()) {
delete [] offsets_;
}
}
void DynamicMessage::CrossLinkPrototypes(DynamicMessageFactory* factory) {
void DynamicMessage::CrossLinkPrototypes() {
// This should only be called on the prototype message.
GOOGLE_CHECK(is_prototype());
DynamicMessageFactory* factory = type_info_->factory;
const Descriptor* descriptor = type_info_->type;
// Cross-link default messages.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
void* field_ptr = base_ + offsets_[i];
for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor* field = descriptor->field(i);
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// For fields with message types, we need to cross-link with the
@ -357,11 +379,9 @@ void DynamicMessage::CrossLinkPrototypes(DynamicMessageFactory* factory) {
}
Message* DynamicMessage::New() const {
uint8* new_base = reinterpret_cast<uint8*>(operator new(size_));
memset(new_base, 0, size_);
return new DynamicMessage(GetDescriptor(), new_base, prototype_base_,
size_, offsets_, descriptor_pool_, factory_);
void* new_base = reinterpret_cast<uint8*>(operator new(type_info_->size));
memset(new_base, 0, type_info_->size);
return new(new_base) DynamicMessage(type_info_);
}
int DynamicMessage::GetCachedSize() const {
@ -376,21 +396,17 @@ void DynamicMessage::SetCachedSize(int size) const {
}
const Descriptor* DynamicMessage::GetDescriptor() const {
return descriptor_;
return type_info_->type;
}
const Message::Reflection* DynamicMessage::GetReflection() const {
return &reflection_;
}
Message::Reflection* DynamicMessage::GetReflection() {
return &reflection_;
const Reflection* DynamicMessage::GetReflection() const {
return type_info_->reflection.get();
}
// ===================================================================
struct DynamicMessageFactory::PrototypeMap {
typedef hash_map<const Descriptor*, const Message*> Map;
typedef hash_map<const Descriptor*, const DynamicMessage::TypeInfo*> Map;
Map map_;
};
@ -411,12 +427,19 @@ DynamicMessageFactory::~DynamicMessageFactory() {
const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
const Message** target = &prototypes_->map_[type];
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
if (*target != NULL) {
// Already exists.
return *target;
return (*target)->prototype.get();
}
DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
*target = type_info;
type_info->type = type;
type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
type_info->factory = this;
// We need to construct all the structures passed to
// GeneratedMessageReflection's constructor. This includes:
// - A block of memory that contains space for all the message's fields.
@ -427,6 +450,7 @@ const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
// Compute size and offsets.
int* offsets = new int[type->field_count()];
type_info->offsets.reset(offsets);
// Sort the fields of this message in descending order by size. We
// assume that if we then pack the fields tightly in this order, all fields
@ -441,35 +465,68 @@ const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
DescendingFieldSizeOrder());
// Decide all field offsets by packing in order.
int current_offset = 0;
// We place the DynamicMessage object itself at the beginning of the allocated
// space.
int size = sizeof(DynamicMessage);
size = AlignOffset(size);
for (int i = 0; i < type->field_count(); i++) {
offsets[ordered_fields[i]->index()] = current_offset;
current_offset += FieldSpaceUsed(ordered_fields[i]);
// Next the has_bits, which is an array of uint32s.
type_info->has_bits_offset = size;
int has_bits_array_size =
DivideRoundingUp(type->field_count(), bitsizeof(uint32));
size += has_bits_array_size * sizeof(uint32);
size = AlignOffset(size);
// The ExtensionSet, if any.
if (type->extension_range_count() > 0) {
type_info->extensions_offset = size;
size += sizeof(ExtensionSet);
size = AlignOffset(size);
} else {
// No extensions.
type_info->extensions_offset = -1;
}
// Allocate space for all fields plus has_bits. We'll stick has_bits on
// the end.
int size = current_offset +
DivideRoundingUp(type->field_count(), bitsizeof(uint32)) * sizeof(uint32);
// All the fields. We don't need to align after each field because they are
// sorted in descending size order, and the size of a type is always a
// multiple of its alignment.
for (int i = 0; i < type->field_count(); i++) {
offsets[ordered_fields[i]->index()] = size;
size += FieldSpaceUsed(ordered_fields[i]);
}
// Round size up to the nearest 64-bit boundary just to make sure no
// clever allocators think that alignment is not necessary. This also
// insures that has_bits is properly-aligned, since we'll always align
// has_bits with the end of the structure.
size = DivideRoundingUp(size, sizeof(uint64)) * sizeof(uint64);
uint8* base = reinterpret_cast<uint8*>(operator new(size));
// Add the UnknownFieldSet to the end.
size = AlignOffset(size);
type_info->unknown_fields_offset = size;
size += sizeof(UnknownFieldSet);
// Align the final size to make sure no clever allocators think that
// alignment is not necessary.
size = AlignOffset(size);
type_info->size = size;
// Allocate the prototype.
void* base = operator new(size);
memset(base, 0, size);
DynamicMessage* prototype = new(base) DynamicMessage(type_info);
type_info->prototype.reset(prototype);
// Construct message.
DynamicMessage* result =
new DynamicMessage(type, base, base, size, offsets, pool_, this);
*target = result;
result->CrossLinkPrototypes(this);
// Construct the reflection object.
type_info->reflection.reset(
new GeneratedMessageReflection(
type_info->type,
type_info->prototype.get(),
type_info->offsets.get(),
type_info->has_bits_offset,
type_info->unknown_fields_offset,
type_info->extensions_offset,
type_info->pool));
return result;
// Cross link prototypes.
prototype->CrossLinkPrototypes();
return prototype;
}
} // namespace protobuf
} // namespace google

View file

@ -90,7 +90,7 @@ TEST_F(DynamicMessageTest, OnePrototype) {
TEST_F(DynamicMessageTest, Defaults) {
// Check that all default values are set correctly in the initial message.
TestUtil::ReflectionTester reflection_tester(descriptor_);
reflection_tester.ExpectClearViaReflection(*prototype_->GetReflection());
reflection_tester.ExpectClearViaReflection(*prototype_);
}
TEST_F(DynamicMessageTest, IndependentOffsets) {
@ -100,8 +100,8 @@ TEST_F(DynamicMessageTest, IndependentOffsets) {
scoped_ptr<Message> message(prototype_->New());
TestUtil::ReflectionTester reflection_tester(descriptor_);
reflection_tester.SetAllFieldsViaReflection(message->GetReflection());
reflection_tester.ExpectAllFieldsSetViaReflection(*message->GetReflection());
reflection_tester.SetAllFieldsViaReflection(message.get());
reflection_tester.ExpectAllFieldsSetViaReflection(*message);
}
TEST_F(DynamicMessageTest, Extensions) {
@ -109,8 +109,8 @@ TEST_F(DynamicMessageTest, Extensions) {
scoped_ptr<Message> message(extensions_prototype_->New());
TestUtil::ReflectionTester reflection_tester(extensions_descriptor_);
reflection_tester.SetAllFieldsViaReflection(message->GetReflection());
reflection_tester.ExpectAllFieldsSetViaReflection(*message->GetReflection());
reflection_tester.SetAllFieldsViaReflection(message.get());
reflection_tester.ExpectAllFieldsSetViaReflection(*message);
}
} // namespace protobuf

View file

@ -34,42 +34,10 @@ namespace internal {
// -------------------------------------------------------------------
// Lookup functions
const FieldDescriptor*
ExtensionSet::FindKnownExtensionByName(const string& name) const {
const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
if (result != NULL && result->containing_type() == extendee_) {
return result;
}
if (extendee_->options().message_set_wire_format()) {
// MessageSet extensions may be identified by type name.
const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
if (type != NULL) {
// Look for a matching extension in the foreign type's scope.
for (int i = 0; i < type->extension_count(); i++) {
const FieldDescriptor* extension = type->extension(i);
if (extension->containing_type() == extendee_ &&
extension->type() == FieldDescriptor::TYPE_MESSAGE &&
extension->is_optional() &&
extension->message_type() == type) {
// Found it.
return extension;
}
}
}
}
return NULL;
}
const FieldDescriptor*
ExtensionSet::FindKnownExtensionByNumber(int number) const {
return descriptor_pool_->FindExtensionByNumber(extendee_, number);
}
const FieldDescriptor*
ExtensionSet::FindKnownExtensionOrDie(int number) const {
const FieldDescriptor* descriptor = FindKnownExtensionByNumber(number);
const FieldDescriptor* descriptor =
descriptor_pool_->FindExtensionByNumber(*extendee_, number);
if (descriptor == NULL) {
// This extension doesn't exist, so we have to crash. However, let's
// try to provide an informative error message.
@ -77,7 +45,7 @@ ExtensionSet::FindKnownExtensionOrDie(int number) const {
message_factory_ == MessageFactory::generated_factory()) {
// This is probably the ExtensionSet for a generated class.
GOOGLE_LOG(FATAL) << ": No extension is registered for \""
<< extendee_->full_name() << "\" with number "
<< (*extendee_)->full_name() << "\" with number "
<< number << ". Perhaps you were trying to access it via "
"the Reflection interface, but you provided a "
"FieldDescriptor which did not come from a linked-in "
@ -87,7 +55,7 @@ ExtensionSet::FindKnownExtensionOrDie(int number) const {
} else {
// This is probably a DynamicMessage.
GOOGLE_LOG(FATAL) << ": No extension is registered for \""
<< extendee_->full_name() << "\" with number "
<< (*extendee_)->full_name() << "\" with number "
<< number << ". If you were using a DynamicMessage, "
"remember that you are only allowed to access extensions "
"which are defined in the DescriptorPool which you passed "
@ -105,7 +73,7 @@ ExtensionSet::GetPrototype(const Descriptor* message_type) const {
// ===================================================================
// Constructors and basic methods.
ExtensionSet::ExtensionSet(const Descriptor* extendee,
ExtensionSet::ExtensionSet(const Descriptor* const* extendee,
const DescriptorPool* pool,
MessageFactory* factory)
: extendee_(extendee),
@ -461,7 +429,7 @@ void MergeRepeatedFields(const RepeatedPtrField<Message>& source,
} // namespace
void ExtensionSet::MergeFrom(const ExtensionSet& other) {
GOOGLE_DCHECK_EQ(extendee_, other.extendee_);
GOOGLE_DCHECK_EQ(*extendee_, *other.extendee_);
for (map<int, Extension>::const_iterator iter = other.extensions_.begin();
iter != other.extensions_.end(); ++iter) {
@ -558,22 +526,23 @@ bool ExtensionSet::IsInitialized() const {
}
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
Message::Reflection* reflection) {
Message* message) {
const FieldDescriptor* field =
FindKnownExtensionByNumber(WireFormat::GetTagFieldNumber(tag));
message->GetReflection()
->FindKnownExtensionByNumber(WireFormat::GetTagFieldNumber(tag));
return WireFormat::ParseAndMergeField(tag, field, reflection, input);
return WireFormat::ParseAndMergeField(tag, field, message, input);
}
bool ExtensionSet::SerializeWithCachedSizes(
int start_field_number, int end_field_number,
const Message::Reflection* reflection,
const Message& message,
io::CodedOutputStream* output) const {
map<int, Extension>::const_iterator iter;
for (iter = extensions_.lower_bound(start_field_number);
iter != extensions_.end() && iter->first < end_field_number;
++iter) {
if (!iter->second.SerializeFieldWithCachedSizes(reflection, output)) {
if (!iter->second.SerializeFieldWithCachedSizes(message, output)) {
return false;
}
}
@ -581,12 +550,12 @@ bool ExtensionSet::SerializeWithCachedSizes(
return true;
}
int ExtensionSet::ByteSize(const Message::Reflection* reflection) const {
int ExtensionSet::ByteSize(const Message& message) const {
int total_size = 0;
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
total_size += iter->second.ByteSize(reflection);
total_size += iter->second.ByteSize(message);
}
return total_size;
@ -652,20 +621,19 @@ void ExtensionSet::Extension::Clear() {
}
bool ExtensionSet::Extension::SerializeFieldWithCachedSizes(
const Message::Reflection* reflection,
const Message& message,
io::CodedOutputStream* output) const {
if (descriptor->is_repeated() || !is_cleared) {
return WireFormat::SerializeFieldWithCachedSizes(
descriptor, reflection, output);
descriptor, message, output);
} else {
return true;
}
}
int64 ExtensionSet::Extension::ByteSize(
const Message::Reflection* reflection) const {
int64 ExtensionSet::Extension::ByteSize(const Message& message) const {
if (descriptor->is_repeated() || !is_cleared) {
return WireFormat::FieldByteSize(descriptor, reflection);
return WireFormat::FieldByteSize(descriptor, message);
} else {
// Cleared, non-repeated field.
return 0;

View file

@ -64,26 +64,28 @@ namespace internal {
class LIBPROTOBUF_EXPORT ExtensionSet {
public:
// Construct an ExtensionSet.
// extendee: Descriptor for the type being extended.
// extendee: Descriptor for the type being extended. We pass in a pointer
// to a pointer to the extendee to get around an initialization
// problem: when we create the ExtensionSet for a message type,
// its descriptor may not exist yet. But we know where that
// descriptor pointer will be placed, and by the time it's used
// by this ExtensionSet it will be fully initialized, so passing
// a pointer to that location works. Note that this problem
// will only occur for messages defined in descriptor.proto.
// pool: DescriptorPool to search for extension definitions.
// factory: MessageFactory used to construct implementations of messages
// for extensions with message type. This factory must be able
// to construct any message type found in "pool".
// All three objects remain property of the caller and must outlive the
// ExtensionSet.
ExtensionSet(const Descriptor* extendee,
ExtensionSet(const Descriptor* const* extendee,
const DescriptorPool* pool,
MessageFactory* factory);
~ExtensionSet();
// Search for a known (compiled-in) extension of this type by name or number.
// Returns NULL if no extension is known.
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
// Add all fields which are currently present to the given vector. This
// is useful to implement Message::Reflection::ListFields().
// is useful to implement Reflection::ListFields().
void AppendToList(vector<const FieldDescriptor*>* output) const;
// =================================================================
@ -110,7 +112,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// die on an assert failure. The message objects returned by the message
// accessors are guaranteed to be of the correct linked-in type.
//
// These methods pretty much match Message::Reflection except that:
// These methods pretty much match Reflection except that:
// - They're not virtual.
// - They identify fields by number rather than FieldDescriptors.
// - They identify enum values using integers rather than descriptors.
@ -196,7 +198,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool IsInitialized() const;
// These parsing and serialization functions all want a pointer to the
// reflection interface because they hand off the actual work to WireFormat,
// message object because they hand off the actual work to WireFormat,
// which works in terms of a reflection interface. Yes, this means there
// are some redundant virtual function calls that end up being made, but
// it probably doesn't matter much in practice, and the alternative would
@ -204,8 +206,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// Parses a single extension from the input. The input should start out
// positioned immediately after the tag.
bool ParseField(uint32 tag, io::CodedInputStream* input,
Message::Reflection* reflection);
bool ParseField(uint32 tag, io::CodedInputStream* input, Message* message);
// Write all extension fields with field numbers in the range
// [start_field_number, end_field_number)
@ -213,11 +214,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// last called. Note that the range bounds are inclusive-exclusive.
bool SerializeWithCachedSizes(int start_field_number,
int end_field_number,
const Message::Reflection* reflection,
const Message& message,
io::CodedOutputStream* output) const;
// Returns the total serialized size of all the extensions.
int ByteSize(const Message::Reflection* reflection) const;
int ByteSize(const Message& message) const;
private:
// Like FindKnownExtension(), but GOOGLE_CHECK-fail if not found.
@ -265,9 +266,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// Some helper methods for operations on a single Extension.
bool SerializeFieldWithCachedSizes(
const Message::Reflection* reflection,
const Message& message,
io::CodedOutputStream* output) const;
int64 ByteSize(const Message::Reflection* reflection) const;
int64 ByteSize(const Message& message) const;
void Clear();
int GetSize() const;
void Free();
@ -280,7 +281,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// for 100 elements or more. Also, we want AppendToList() to order fields
// by field number.
map<int, Extension> extensions_;
const Descriptor* extendee_;
const Descriptor* const* extendee_;
const DescriptorPool* descriptor_pool_;
MessageFactory* message_factory_;

View file

@ -43,7 +43,7 @@ void ReportReflectionUsageError(
const char* method, const char* description) {
GOOGLE_LOG(FATAL)
<< "Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::" << method << "\n"
" Method : google::protobuf::Reflection::" << method << "\n"
" Message type: " << descriptor->full_name() << "\n"
" Field : " << field->full_name() << "\n"
" Problem : " << description;
@ -69,7 +69,7 @@ static void ReportReflectionUsageTypeError(
FieldDescriptor::CppType expected_type) {
GOOGLE_LOG(FATAL)
<< "Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::" << method << "\n"
" Method : google::protobuf::Reflection::" << method << "\n"
" Message type: " << descriptor->full_name() << "\n"
" Field : " << field->full_name() << "\n"
" Problem : Field is not the right type for this message:\n"
@ -82,7 +82,7 @@ static void ReportReflectionUsageEnumTypeError(
const char* method, const EnumValueDescriptor* value) {
GOOGLE_LOG(FATAL)
<< "Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::" << method << "\n"
" Method : google::protobuf::Reflection::" << method << "\n"
" Message type: " << descriptor->full_name() << "\n"
" Field : " << field->full_name() << "\n"
" Problem : Enum value did not match field type:\n"
@ -128,64 +128,79 @@ static void ReportReflectionUsageEnumTypeError(
GeneratedMessageReflection::GeneratedMessageReflection(
const Descriptor* descriptor,
void* base, const void* default_base,
const int offsets[], uint32 has_bits[],
ExtensionSet* extensions)
: descriptor_ (descriptor),
base_ (base),
default_base_(default_base),
offsets_ (offsets),
has_bits_ (has_bits),
extensions_ (extensions) {
const Message* default_instance,
const int offsets[],
int has_bits_offset,
int unknown_fields_offset,
int extensions_offset,
const DescriptorPool* descriptor_pool)
: descriptor_ (descriptor),
default_instance_ (default_instance),
offsets_ (offsets),
has_bits_offset_ (has_bits_offset),
unknown_fields_offset_(unknown_fields_offset),
extensions_offset_(extensions_offset),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
descriptor_pool) {
}
GeneratedMessageReflection::~GeneratedMessageReflection() {}
const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields() const {
return unknown_fields_;
const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
const Message& message) const {
const void* ptr = reinterpret_cast<const uint8*>(&message) +
unknown_fields_offset_;
return *reinterpret_cast<const UnknownFieldSet*>(ptr);
}
UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields() {
return &unknown_fields_;
UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
Message* message) const {
void* ptr = reinterpret_cast<uint8*>(message) + unknown_fields_offset_;
return reinterpret_cast<UnknownFieldSet*>(ptr);
}
// -------------------------------------------------------------------
bool GeneratedMessageReflection::HasField(const FieldDescriptor* field) const {
bool GeneratedMessageReflection::HasField(const Message& message,
const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(HasField);
USAGE_CHECK_SINGULAR(HasField);
if (field->is_extension()) {
return extensions_->Has(field->number());
return GetExtensionSet(message).Has(field->number());
} else {
return HasBit(field);
return HasBit(message, field);
}
}
int GeneratedMessageReflection::FieldSize(const FieldDescriptor* field) const {
int GeneratedMessageReflection::FieldSize(const Message& message,
const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(HasField);
USAGE_CHECK_REPEATED(HasField);
if (field->is_extension()) {
return extensions_->ExtensionSize(field->number());
return GetExtensionSet(message).ExtensionSize(field->number());
} else {
return GetRaw<GenericRepeatedField>(field).GenericSize();
return GetRaw<GenericRepeatedField>(message, field).GenericSize();
}
}
void GeneratedMessageReflection::ClearField(const FieldDescriptor* field) {
void GeneratedMessageReflection::ClearField(
Message* message, const FieldDescriptor* field) const {
USAGE_CHECK_MESSAGE_TYPE(ClearField);
if (field->is_extension()) {
extensions_->ClearExtension(field->number());
MutableExtensionSet(message)->ClearExtension(field->number());
} else if (!field->is_repeated()) {
if (HasBit(field)) {
ClearBit(field);
if (HasBit(*message, field)) {
ClearBit(message, field);
// We need to set the field back to its default value.
switch (field->cpp_type()) {
#define CLEAR_TYPE(CPPTYPE, TYPE) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
*MutableRaw<TYPE>(field) = field->default_value_##TYPE(); \
*MutableRaw<TYPE>(message, field) = \
field->default_value_##TYPE(); \
break;
CLEAR_TYPE(INT32 , int32 );
@ -198,12 +213,13 @@ void GeneratedMessageReflection::ClearField(const FieldDescriptor* field) {
#undef CLEAR_TYPE
case FieldDescriptor::CPPTYPE_ENUM:
*MutableRaw<int>(field) = field->default_value_enum()->number();
*MutableRaw<int>(message, field) =
field->default_value_enum()->number();
break;
case FieldDescriptor::CPPTYPE_STRING: {
const string* default_ptr = DefaultRaw<const string*>(field);
string** value = MutableRaw<string*>(field);
string** value = MutableRaw<string*>(message, field);
if (*value != default_ptr) {
if (field->has_default_value()) {
(*value)->assign(field->default_value_string());
@ -215,12 +231,12 @@ void GeneratedMessageReflection::ClearField(const FieldDescriptor* field) {
}
case FieldDescriptor::CPPTYPE_MESSAGE:
(*MutableRaw<Message*>(field))->Clear();
(*MutableRaw<Message*>(message, field))->Clear();
break;
}
}
} else {
MutableRaw<GenericRepeatedField>(field)->GenericClear();
MutableRaw<GenericRepeatedField>(message, field)->GenericClear();
}
}
@ -235,27 +251,28 @@ struct FieldNumberSorter {
} // namespace
void GeneratedMessageReflection::ListFields(
const Message& message,
vector<const FieldDescriptor*>* output) const {
output->clear();
// Optimization: The default instance never has any fields set.
if (base_ == default_base_) return;
if (&message == default_instance_) return;
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
if (GetRaw<GenericRepeatedField>(field).GenericSize() > 0) {
if (GetRaw<GenericRepeatedField>(message, field).GenericSize() > 0) {
output->push_back(field);
}
} else {
if (HasBit(field)) {
if (HasBit(message, field)) {
output->push_back(field);
}
}
}
if (extensions_ != NULL) {
extensions_->AppendToList(output);
if (extensions_offset_ != -1) {
GetExtensionSet(message).AppendToList(output);
}
// ListFields() must sort output by field number.
@ -267,52 +284,59 @@ void GeneratedMessageReflection::ListFields(
#undef DEFINE_PRIMITIVE_ACCESSORS
#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \
PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \
const FieldDescriptor* field) const { \
const Message& message, const FieldDescriptor* field) const { \
USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return extensions_->Get##TYPENAME(field->number()); \
return GetExtensionSet(message).Get##TYPENAME(field->number()); \
} else { \
return GetField<TYPE>(field); \
return GetField<TYPE>(message, field); \
} \
} \
\
void GeneratedMessageReflection::Set##TYPENAME( \
const FieldDescriptor* field, PASSTYPE value) { \
Message* message, const FieldDescriptor* field, \
PASSTYPE value) const { \
USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return extensions_->Set##TYPENAME(field->number(), value); \
return MutableExtensionSet(message)->Set##TYPENAME( \
field->number(), value); \
} else { \
SetField<TYPE>(field, value); \
SetField<TYPE>(message, field, value); \
} \
} \
\
PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \
const Message& message, \
const FieldDescriptor* field, int index) const { \
USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
return extensions_->GetRepeated##TYPENAME(field->number(), index); \
return GetExtensionSet(message).GetRepeated##TYPENAME( \
field->number(), index); \
} else { \
return GetRepeatedField<TYPE>(field, index); \
return GetRepeatedField<TYPE>(message, field, index); \
} \
} \
\
void GeneratedMessageReflection::SetRepeated##TYPENAME( \
const FieldDescriptor* field, int index, PASSTYPE value) { \
Message* message, const FieldDescriptor* field, \
int index, PASSTYPE value) const { \
USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
extensions_->SetRepeated##TYPENAME(field->number(), index, value); \
MutableExtensionSet(message)->SetRepeated##TYPENAME( \
field->number(), index, value); \
} else { \
SetRepeatedField<TYPE>(field, index, value); \
SetRepeatedField<TYPE>(message, field, index, value); \
} \
} \
\
void GeneratedMessageReflection::Add##TYPENAME( \
const FieldDescriptor* field, PASSTYPE value) { \
Message* message, const FieldDescriptor* field, \
PASSTYPE value) const { \
USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
extensions_->Add##TYPENAME(field->number(), value); \
MutableExtensionSet(message)->Add##TYPENAME(field->number(), value); \
} else { \
AddField<TYPE>(field, value); \
AddField<TYPE>(message, field, value); \
} \
}
@ -328,33 +352,35 @@ DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL )
// -------------------------------------------------------------------
string GeneratedMessageReflection::GetString(
const FieldDescriptor* field) const {
const Message& message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
if (field->is_extension()) {
return extensions_->GetString(field->number());
return GetExtensionSet(message).GetString(field->number());
} else {
return *GetField<const string*>(field);
return *GetField<const string*>(message, field);
}
}
const string& GeneratedMessageReflection::GetStringReference(
const Message& message,
const FieldDescriptor* field, string* scratch) const {
USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
if (field->is_extension()) {
return extensions_->GetString(field->number());
return GetExtensionSet(message).GetString(field->number());
} else {
return *GetField<const string*>(field);
return *GetField<const string*>(message, field);
}
}
void GeneratedMessageReflection::SetString(
const FieldDescriptor* field, const string& value) {
Message* message, const FieldDescriptor* field,
const string& value) const {
USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
if (field->is_extension()) {
return extensions_->SetString(field->number(), value);
return MutableExtensionSet(message)->SetString(field->number(), value);
} else {
string** ptr = MutableField<string*>(field);
string** ptr = MutableField<string*>(message, field);
if (*ptr == DefaultRaw<const string*>(field)) {
*ptr = new string(value);
} else {
@ -365,44 +391,48 @@ void GeneratedMessageReflection::SetString(
string GeneratedMessageReflection::GetRepeatedString(
const FieldDescriptor* field, int index) const {
const Message& message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
if (field->is_extension()) {
return extensions_->GetRepeatedString(field->number(), index);
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
return GetRepeatedField<string>(field, index);
return GetRepeatedField<string>(message, field, index);
}
}
const string& GeneratedMessageReflection::GetRepeatedStringReference(
const FieldDescriptor* field, int index, string* scratch) const {
const Message& message, const FieldDescriptor* field,
int index, string* scratch) const {
USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
if (field->is_extension()) {
return extensions_->GetRepeatedString(field->number(), index);
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
return GetRepeatedField<string>(field, index);
return GetRepeatedField<string>(message, field, index);
}
}
void GeneratedMessageReflection::SetRepeatedString(
const FieldDescriptor* field, int index, const string& value) {
Message* message, const FieldDescriptor* field,
int index, const string& value) const {
USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
if (field->is_extension()) {
extensions_->SetRepeatedString(field->number(), index, value);
MutableExtensionSet(message)->SetRepeatedString(
field->number(), index, value);
} else {
SetRepeatedField<string>(field, index, value);
SetRepeatedField<string>(message, field, index, value);
}
}
void GeneratedMessageReflection::AddString(
const FieldDescriptor* field, const string& value) {
Message* message, const FieldDescriptor* field,
const string& value) const {
USAGE_CHECK_ALL(AddString, REPEATED, STRING);
if (field->is_extension()) {
extensions_->AddString(field->number(), value);
MutableExtensionSet(message)->AddString(field->number(), value);
} else {
AddField<string>(field, value);
AddField<string>(message, field, value);
}
}
@ -410,14 +440,14 @@ void GeneratedMessageReflection::AddString(
// -------------------------------------------------------------------
const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
const FieldDescriptor* field) const {
const Message& message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
int value;
if (field->is_extension()) {
value = extensions_->GetEnum(field->number());
value = GetExtensionSet(message).GetEnum(field->number());
} else {
value = GetField<int>(field);
value = GetField<int>(message, field);
}
const EnumValueDescriptor* result =
field->enum_type()->FindValueByNumber(value);
@ -425,27 +455,28 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
return result;
}
void GeneratedMessageReflection::SetEnum(const FieldDescriptor* field,
const EnumValueDescriptor* value) {
void GeneratedMessageReflection::SetEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
USAGE_CHECK_ENUM_VALUE(SetEnum);
if (field->is_extension()) {
extensions_->SetEnum(field->number(), value->number());
MutableExtensionSet(message)->SetEnum(field->number(), value->number());
} else {
SetField<int>(field, value->number());
SetField<int>(message, field, value->number());
}
}
const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
const FieldDescriptor* field, int index) const {
const Message& message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
int value;
if (field->is_extension()) {
value = extensions_->GetRepeatedEnum(field->number(), index);
value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index);
} else {
value = GetRepeatedField<int>(field, index);
value = GetRepeatedField<int>(message, field, index);
}
const EnumValueDescriptor* result =
field->enum_type()->FindValueByNumber(value);
@ -454,40 +485,43 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
}
void GeneratedMessageReflection::SetRepeatedEnum(
Message* message,
const FieldDescriptor* field, int index,
const EnumValueDescriptor* value) {
const EnumValueDescriptor* value) const {
USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
if (field->is_extension()) {
extensions_->SetRepeatedEnum(field->number(), index, value->number());
MutableExtensionSet(message)->SetRepeatedEnum(
field->number(), index, value->number());
} else {
SetRepeatedField<int>(field, index, value->number());
SetRepeatedField<int>(message, field, index, value->number());
}
}
void GeneratedMessageReflection::AddEnum(const FieldDescriptor* field,
const EnumValueDescriptor* value) {
void GeneratedMessageReflection::AddEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
USAGE_CHECK_ENUM_VALUE(AddEnum);
if (field->is_extension()) {
extensions_->AddEnum(field->number(), value->number());
MutableExtensionSet(message)->AddEnum(field->number(), value->number());
} else {
AddField<int>(field, value->number());
AddField<int>(message, field, value->number());
}
}
// -------------------------------------------------------------------
const Message& GeneratedMessageReflection::GetMessage(
const FieldDescriptor* field) const {
const Message& message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
return extensions_->GetMessage(field->number());
return GetExtensionSet(message).GetMessage(field->number());
} else {
const Message* result = GetRaw<const Message*>(field);
const Message* result = GetRaw<const Message*>(message, field);
if (result == NULL) {
result = DefaultRaw<const Message*>(field);
}
@ -496,13 +530,13 @@ const Message& GeneratedMessageReflection::GetMessage(
}
Message* GeneratedMessageReflection::MutableMessage(
const FieldDescriptor* field) {
Message* message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
return extensions_->MutableMessage(field->number());
return MutableExtensionSet(message)->MutableMessage(field->number());
} else {
Message** result = MutableField<Message*>(field);
Message** result = MutableField<Message*>(message, field);
if (*result == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
*result = default_message->New();
@ -513,34 +547,36 @@ Message* GeneratedMessageReflection::MutableMessage(
}
const Message& GeneratedMessageReflection::GetRepeatedMessage(
const FieldDescriptor* field, int index) const {
const Message& message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
if (field->is_extension()) {
return extensions_->GetRepeatedMessage(field->number(), index);
return GetExtensionSet(message).GetRepeatedMessage(field->number(), index);
} else {
return GetRepeatedField<Message>(field, index);
return GetRepeatedField<Message>(message, field, index);
}
}
Message* GeneratedMessageReflection::MutableRepeatedMessage(
const FieldDescriptor* field, int index) {
Message* message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
if (field->is_extension()) {
return extensions_->MutableRepeatedMessage(field->number(), index);
return MutableExtensionSet(message)->MutableRepeatedMessage(
field->number(), index);
} else {
return MutableRepeatedField<Message>(field, index);
return MutableRepeatedField<Message>(message, field, index);
}
}
Message* GeneratedMessageReflection::AddMessage(const FieldDescriptor* field) {
Message* GeneratedMessageReflection::AddMessage(
Message* message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
if (field->is_extension()) {
return extensions_->AddMessage(field->number());
return MutableExtensionSet(message)->AddMessage(field->number());
} else {
return AddField<Message>(field);
return AddField<Message>(message, field);
}
}
@ -548,14 +584,38 @@ Message* GeneratedMessageReflection::AddMessage(const FieldDescriptor* field) {
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
const string& name) const {
if (extensions_ == NULL) return NULL;
return extensions_->FindKnownExtensionByName(name);
if (extensions_offset_ == -1) return NULL;
const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
if (result != NULL && result->containing_type() == descriptor_) {
return result;
}
if (descriptor_->options().message_set_wire_format()) {
// MessageSet extensions may be identified by type name.
const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
if (type != NULL) {
// Look for a matching extension in the foreign type's scope.
for (int i = 0; i < type->extension_count(); i++) {
const FieldDescriptor* extension = type->extension(i);
if (extension->containing_type() == descriptor_ &&
extension->type() == FieldDescriptor::TYPE_MESSAGE &&
extension->is_optional() &&
extension->message_type() == type) {
// Found it.
return extension;
}
}
}
}
return NULL;
}
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
int number) const {
if (extensions_ == NULL) return NULL;
return extensions_->FindKnownExtensionByNumber(number);
if (extensions_offset_ == -1) return NULL;
return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
}
// ===================================================================
@ -565,41 +625,67 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
// the given field.
template <typename Type>
inline const Type& GeneratedMessageReflection::GetRaw(
const FieldDescriptor* field) const {
const void* ptr = reinterpret_cast<const uint8*>(base_) +
const Message& message, const FieldDescriptor* field) const {
const void* ptr = reinterpret_cast<const uint8*>(&message) +
offsets_[field->index()];
return *reinterpret_cast<const Type*>(ptr);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableRaw(
const FieldDescriptor* field) {
void* ptr = reinterpret_cast<uint8*>(base_) + offsets_[field->index()];
Message* message, const FieldDescriptor* field) const {
void* ptr = reinterpret_cast<uint8*>(message) + offsets_[field->index()];
return reinterpret_cast<Type*>(ptr);
}
template <typename Type>
inline const Type& GeneratedMessageReflection::DefaultRaw(
const FieldDescriptor* field) const {
const void* ptr = reinterpret_cast<const uint8*>(default_base_) +
const void* ptr = reinterpret_cast<const uint8*>(default_instance_) +
offsets_[field->index()];
return *reinterpret_cast<const Type*>(ptr);
}
inline const uint32* GeneratedMessageReflection::GetHasBits(
const Message& message) const {
const void* ptr = reinterpret_cast<const uint8*>(&message) + has_bits_offset_;
return reinterpret_cast<const uint32*>(ptr);
}
inline uint32* GeneratedMessageReflection::MutableHasBits(
Message* message) const {
void* ptr = reinterpret_cast<uint8*>(message) + has_bits_offset_;
return reinterpret_cast<uint32*>(ptr);
}
inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
const Message& message) const {
GOOGLE_DCHECK_NE(extensions_offset_, -1);
const void* ptr = reinterpret_cast<const uint8*>(&message) +
extensions_offset_;
return *reinterpret_cast<const ExtensionSet*>(ptr);
}
inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
Message* message) const {
GOOGLE_DCHECK_NE(extensions_offset_, -1);
void* ptr = reinterpret_cast<uint8*>(message) + extensions_offset_;
return reinterpret_cast<ExtensionSet*>(ptr);
}
// Simple accessors for manipulating has_bits_.
inline bool GeneratedMessageReflection::HasBit(
const FieldDescriptor* field) const {
return has_bits_[field->index() / 32] & (1 << (field->index() % 32));
const Message& message, const FieldDescriptor* field) const {
return GetHasBits(message)[field->index() / 32] &
(1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::SetBit(
const FieldDescriptor* field) {
has_bits_[field->index() / 32] |= (1 << (field->index() % 32));
Message* message, const FieldDescriptor* field) const {
MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::ClearBit(
const FieldDescriptor* field) {
has_bits_[field->index() / 32] &= ~(1 << (field->index() % 32));
Message* message, const FieldDescriptor* field) const {
MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
}
// Template implementations of basic accessors. Inline because each
@ -607,56 +693,61 @@ inline void GeneratedMessageReflection::ClearBit(
// used for all types except messages.
template <typename Type>
inline const Type& GeneratedMessageReflection::GetField(
const FieldDescriptor* field) const {
return GetRaw<Type>(field);
const Message& message, const FieldDescriptor* field) const {
return GetRaw<Type>(message, field);
}
template <typename Type>
inline void GeneratedMessageReflection::SetField(
const FieldDescriptor* field, const Type& value) {
*MutableRaw<Type>(field) = value;
SetBit(field);
Message* message, const FieldDescriptor* field, const Type& value) const {
*MutableRaw<Type>(message, field) = value;
SetBit(message, field);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableField(
const FieldDescriptor* field) {
SetBit(field);
return MutableRaw<Type>(field);
Message* message, const FieldDescriptor* field) const {
SetBit(message, field);
return MutableRaw<Type>(message, field);
}
template <typename Type>
inline const Type& GeneratedMessageReflection::GetRepeatedField(
const FieldDescriptor* field, int index) const {
const Message& message, const FieldDescriptor* field, int index) const {
return *reinterpret_cast<const Type*>(
GetRaw<GenericRepeatedField>(field).GenericGet(index));
GetRaw<GenericRepeatedField>(message, field).GenericGet(index));
}
template <typename Type>
inline void GeneratedMessageReflection::SetRepeatedField(
const FieldDescriptor* field, int index, const Type& value) {
GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
Message* message, const FieldDescriptor* field,
int index, const Type& value) const {
GenericRepeatedField* repeated =
MutableRaw<GenericRepeatedField>(message, field);
*reinterpret_cast<Type*>(repeated->GenericMutable(index)) = value;
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableRepeatedField(
const FieldDescriptor* field, int index) {
GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
Message* message, const FieldDescriptor* field, int index) const {
GenericRepeatedField* repeated =
MutableRaw<GenericRepeatedField>(message, field);
return reinterpret_cast<Type*>(repeated->GenericMutable(index));
}
template <typename Type>
inline void GeneratedMessageReflection::AddField(
const FieldDescriptor* field, const Type& value) {
GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
Message* message, const FieldDescriptor* field, const Type& value) const {
GenericRepeatedField* repeated =
MutableRaw<GenericRepeatedField>(message, field);
*reinterpret_cast<Type*>(repeated->GenericAdd()) = value;
}
template <typename Type>
inline Type* GeneratedMessageReflection::AddField(
const FieldDescriptor* field) {
GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
Message* message, const FieldDescriptor* field) const {
GenericRepeatedField* repeated =
MutableRaw<GenericRepeatedField>(message, field);
return reinterpret_cast<Type*>(repeated->GenericAdd());
}

View file

@ -30,10 +30,13 @@
#include <google/protobuf/unknown_field_set.h>
// Generated code needs this to have been forward-declared. Easier to do it
// here than to print it inside every .pb.h file.
namespace google {
namespace protobuf { class EnumDescriptor; }
namespace protobuf {
class DescriptorPool;
// Generated code needs this to have been forward-declared. Easier to do it
// here than to print it inside every .pb.h file.
class EnumDescriptor;
}
namespace protobuf {
namespace internal {
@ -48,7 +51,7 @@ class ExtensionSet; // extension_set.h
// by generated code. This class is just a big hack that reduces code
// size.
//
// A GeneratedMessageReflection is an implementation of Message::Reflection
// A GeneratedMessageReflection is an implementation of Reflection
// which expects all fields to be backed by simple variables located in
// memory. The locations are given using a base pointer and a set of
// offsets.
@ -68,122 +71,172 @@ class ExtensionSet; // extension_set.h
// of whatever type the individual field would be. Strings and
// Messages use RepeatedPtrFields while everything else uses
// RepeatedFields.
class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Message::Reflection {
class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
public:
// Constructs a GeneratedMessageReflection.
// Parameters:
// descriptor: The descriptor for the message type being implemented.
// base: Pointer to the location where the message object is
// stored.
// default_base: Pointer to the location where the message's default
// instance is stored. This is only used to obtain
// pointers to default instances of embedded messages,
// which GetMessage() will return if the particular sub-
// message has not been initialized yet. (Thus, all
// default_instance: The default instance of the message. This is only
// used to obtain pointers to default instances of embedded
// messages, which GetMessage() will return if the particular
// sub-message has not been initialized yet. (Thus, all
// embedded message fields *must* have non-NULL pointers
// in the default instance.)
// offsets: An array of bits giving the byte offsets, relative to
// "base" and "default_base", of each field. These can
// offsets: An array of ints giving the byte offsets, relative to
// the start of the message object, of each field. These can
// be computed at compile time using the
// GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro, defined
// below.
// has_bits: An array of uint32s of size descriptor->field_count()/32,
// rounded up. This is a bitfield where each bit indicates
// whether or not the corresponding field of the message
// has been initialized. The bit for field index i is
// obtained by the expression:
// has_bits_offset: Offset in the message of an array of uint32s of size
// descriptor->field_count()/32, rounded up. This is a
// bitfield where each bit indicates whether or not the
// corresponding field of the message has been initialized.
// The bit for field index i is obtained by the expression:
// has_bits[i / 32] & (1 << (i % 32))
// extensions: The ExtensionSet for this message, or NULL if the
// message type has no extension ranges.
// unknown_fields_offset: Offset in the message of the UnknownFieldSet for
// the message.
// extensions_offset: Offset in the message of the ExtensionSet for the
// message, or -1 if the message type has no extension
// ranges.
// pool: DescriptorPool to search for extension definitions. Only
// used by FindKnownExtensionByName() and
// FindKnownExtensionByNumber().
GeneratedMessageReflection(const Descriptor* descriptor,
void* base, const void* default_base,
const int offsets[], uint32 has_bits[],
ExtensionSet* extensions);
const Message* default_instance,
const int offsets[],
int has_bits_offset,
int unknown_fields_offset,
int extensions_offset,
const DescriptorPool* pool);
~GeneratedMessageReflection();
inline const UnknownFieldSet& unknown_fields() const {
return unknown_fields_;
}
inline UnknownFieldSet* mutable_unknown_fields() {
return &unknown_fields_;
}
// implements Reflection -------------------------------------------
// implements Message::Reflection ----------------------------------
const UnknownFieldSet& GetUnknownFields(const Message& message) const;
UnknownFieldSet* MutableUnknownFields(Message* message) const;
const UnknownFieldSet& GetUnknownFields() const;
UnknownFieldSet* MutableUnknownFields();
bool HasField(const Message& message, const FieldDescriptor* field) const;
int FieldSize(const Message& message, const FieldDescriptor* field) const;
void ClearField(Message* message, const FieldDescriptor* field) const;
void ListFields(const Message& message,
vector<const FieldDescriptor*>* output) const;
bool HasField(const FieldDescriptor* field) const;
int FieldSize(const FieldDescriptor* field) const;
void ClearField(const FieldDescriptor* field);
void ListFields(vector<const FieldDescriptor*>* output) const;
int32 GetInt32 (const FieldDescriptor* field) const;
int64 GetInt64 (const FieldDescriptor* field) const;
uint32 GetUInt32(const FieldDescriptor* field) const;
uint64 GetUInt64(const FieldDescriptor* field) const;
float GetFloat (const FieldDescriptor* field) const;
double GetDouble(const FieldDescriptor* field) const;
bool GetBool (const FieldDescriptor* field) const;
string GetString(const FieldDescriptor* field) const;
const string& GetStringReference(const FieldDescriptor* field,
int32 GetInt32 (const Message& message,
const FieldDescriptor* field) const;
int64 GetInt64 (const Message& message,
const FieldDescriptor* field) const;
uint32 GetUInt32(const Message& message,
const FieldDescriptor* field) const;
uint64 GetUInt64(const Message& message,
const FieldDescriptor* field) const;
float GetFloat (const Message& message,
const FieldDescriptor* field) const;
double GetDouble(const Message& message,
const FieldDescriptor* field) const;
bool GetBool (const Message& message,
const FieldDescriptor* field) const;
string GetString(const Message& message,
const FieldDescriptor* field) const;
const string& GetStringReference(const Message& message,
const FieldDescriptor* field,
string* scratch) const;
const EnumValueDescriptor* GetEnum(const FieldDescriptor* field) const;
const Message& GetMessage(const FieldDescriptor* field) const;
const EnumValueDescriptor* GetEnum(const Message& message,
const FieldDescriptor* field) const;
const Message& GetMessage(const Message& message,
const FieldDescriptor* field) const;
void SetInt32 (const FieldDescriptor* field, int32 value);
void SetInt64 (const FieldDescriptor* field, int64 value);
void SetUInt32(const FieldDescriptor* field, uint32 value);
void SetUInt64(const FieldDescriptor* field, uint64 value);
void SetFloat (const FieldDescriptor* field, float value);
void SetDouble(const FieldDescriptor* field, double value);
void SetBool (const FieldDescriptor* field, bool value);
void SetString(const FieldDescriptor* field,
const string& value);
void SetEnum (const FieldDescriptor* field,
const EnumValueDescriptor* value);
Message* MutableMessage(const FieldDescriptor* field);
void SetInt32 (Message* message,
const FieldDescriptor* field, int32 value) const;
void SetInt64 (Message* message,
const FieldDescriptor* field, int64 value) const;
void SetUInt32(Message* message,
const FieldDescriptor* field, uint32 value) const;
void SetUInt64(Message* message,
const FieldDescriptor* field, uint64 value) const;
void SetFloat (Message* message,
const FieldDescriptor* field, float value) const;
void SetDouble(Message* message,
const FieldDescriptor* field, double value) const;
void SetBool (Message* message,
const FieldDescriptor* field, bool value) const;
void SetString(Message* message,
const FieldDescriptor* field,
const string& value) const;
void SetEnum (Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
Message* MutableMessage(Message* message, const FieldDescriptor* field) const;
int32 GetRepeatedInt32 (const FieldDescriptor* field, int index) const;
int64 GetRepeatedInt64 (const FieldDescriptor* field, int index) const;
uint32 GetRepeatedUInt32(const FieldDescriptor* field, int index) const;
uint64 GetRepeatedUInt64(const FieldDescriptor* field, int index) const;
float GetRepeatedFloat (const FieldDescriptor* field, int index) const;
double GetRepeatedDouble(const FieldDescriptor* field, int index) const;
bool GetRepeatedBool (const FieldDescriptor* field, int index) const;
string GetRepeatedString(const FieldDescriptor* field, int index) const;
const string& GetRepeatedStringReference(const FieldDescriptor* field,
int32 GetRepeatedInt32 (const Message& message,
const FieldDescriptor* field, int index) const;
int64 GetRepeatedInt64 (const Message& message,
const FieldDescriptor* field, int index) const;
uint32 GetRepeatedUInt32(const Message& message,
const FieldDescriptor* field, int index) const;
uint64 GetRepeatedUInt64(const Message& message,
const FieldDescriptor* field, int index) const;
float GetRepeatedFloat (const Message& message,
const FieldDescriptor* field, int index) const;
double GetRepeatedDouble(const Message& message,
const FieldDescriptor* field, int index) const;
bool GetRepeatedBool (const Message& message,
const FieldDescriptor* field, int index) const;
string GetRepeatedString(const Message& message,
const FieldDescriptor* field, int index) const;
const string& GetRepeatedStringReference(const Message& message,
const FieldDescriptor* field,
int index, string* scratch) const;
const EnumValueDescriptor* GetRepeatedEnum(const FieldDescriptor* field,
const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
const FieldDescriptor* field,
int index) const;
const Message& GetRepeatedMessage(const FieldDescriptor* field,
const Message& GetRepeatedMessage(const Message& message,
const FieldDescriptor* field,
int index) const;
// Set the value of a field.
void SetRepeatedInt32 (const FieldDescriptor* field, int index, int32 value);
void SetRepeatedInt64 (const FieldDescriptor* field, int index, int64 value);
void SetRepeatedUInt32(const FieldDescriptor* field, int index, uint32 value);
void SetRepeatedUInt64(const FieldDescriptor* field, int index, uint64 value);
void SetRepeatedFloat (const FieldDescriptor* field, int index, float value);
void SetRepeatedDouble(const FieldDescriptor* field, int index, double value);
void SetRepeatedBool (const FieldDescriptor* field, int index, bool value);
void SetRepeatedString(const FieldDescriptor* field, int index,
const string& value);
void SetRepeatedEnum (const FieldDescriptor* field, int index,
const EnumValueDescriptor* value);
void SetRepeatedInt32 (Message* message,
const FieldDescriptor* field, int index, int32 value) const;
void SetRepeatedInt64 (Message* message,
const FieldDescriptor* field, int index, int64 value) const;
void SetRepeatedUInt32(Message* message,
const FieldDescriptor* field, int index, uint32 value) const;
void SetRepeatedUInt64(Message* message,
const FieldDescriptor* field, int index, uint64 value) const;
void SetRepeatedFloat (Message* message,
const FieldDescriptor* field, int index, float value) const;
void SetRepeatedDouble(Message* message,
const FieldDescriptor* field, int index, double value) const;
void SetRepeatedBool (Message* message,
const FieldDescriptor* field, int index, bool value) const;
void SetRepeatedString(Message* message,
const FieldDescriptor* field, int index,
const string& value) const;
void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
int index, const EnumValueDescriptor* value) const;
// Get a mutable pointer to a field with a message type.
Message* MutableRepeatedMessage(const FieldDescriptor* field, int index);
Message* MutableRepeatedMessage(Message* message,
const FieldDescriptor* field,
int index) const;
void AddInt32 (const FieldDescriptor* field, int32 value);
void AddInt64 (const FieldDescriptor* field, int64 value);
void AddUInt32(const FieldDescriptor* field, uint32 value);
void AddUInt64(const FieldDescriptor* field, uint64 value);
void AddFloat (const FieldDescriptor* field, float value);
void AddDouble(const FieldDescriptor* field, double value);
void AddBool (const FieldDescriptor* field, bool value);
void AddString(const FieldDescriptor* field, const string& value);
void AddEnum(const FieldDescriptor* field, const EnumValueDescriptor* value);
Message* AddMessage(const FieldDescriptor* field);
void AddInt32 (Message* message,
const FieldDescriptor* field, int32 value) const;
void AddInt64 (Message* message,
const FieldDescriptor* field, int64 value) const;
void AddUInt32(Message* message,
const FieldDescriptor* field, uint32 value) const;
void AddUInt64(Message* message,
const FieldDescriptor* field, uint64 value) const;
void AddFloat (Message* message,
const FieldDescriptor* field, float value) const;
void AddDouble(Message* message,
const FieldDescriptor* field, double value) const;
void AddBool (Message* message,
const FieldDescriptor* field, bool value) const;
void AddString(Message* message,
const FieldDescriptor* field, const string& value) const;
void AddEnum(Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
Message* AddMessage(Message* message, const FieldDescriptor* field) const;
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
@ -192,50 +245,64 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Message::Reflection
friend class GeneratedMessage;
const Descriptor* descriptor_;
void* base_;
const void* default_base_;
const Message* default_instance_;
const int* offsets_;
// TODO(kenton): These two pointers just point back into the message object.
// We could save space by removing them and using offsets instead.
uint32* has_bits_;
ExtensionSet* extensions_;
int has_bits_offset_;
int unknown_fields_offset_;
int extensions_offset_;
// We put this directly in the GeneratedMessageReflection because every
// message class needs it, and if we don't find any unknown fields, it
// takes up only one pointer of space.
UnknownFieldSet unknown_fields_;
const DescriptorPool* descriptor_pool_;
template <typename Type>
inline const Type& GetRaw(const FieldDescriptor* field) const;
inline const Type& GetRaw(const Message& message,
const FieldDescriptor* field) const;
template <typename Type>
inline Type* MutableRaw(const FieldDescriptor* field);
inline Type* MutableRaw(Message* message,
const FieldDescriptor* field) const;
template <typename Type>
inline const Type& DefaultRaw(const FieldDescriptor* field) const;
inline const Message* GetMessagePrototype(const FieldDescriptor* field) const;
inline bool HasBit(const FieldDescriptor* field) const;
inline void SetBit(const FieldDescriptor* field);
inline void ClearBit(const FieldDescriptor* field);
inline const uint32* GetHasBits(const Message& message) const;
inline uint32* MutableHasBits(Message* message) const;
inline const ExtensionSet& GetExtensionSet(const Message& message) const;
inline ExtensionSet* MutableExtensionSet(Message* message) const;
inline bool HasBit(const Message& message,
const FieldDescriptor* field) const;
inline void SetBit(Message* message,
const FieldDescriptor* field) const;
inline void ClearBit(Message* message,
const FieldDescriptor* field) const;
template <typename Type>
inline const Type& GetField(const FieldDescriptor* field) const;
inline const Type& GetField(const Message& message,
const FieldDescriptor* field) const;
template <typename Type>
inline void SetField(const FieldDescriptor* field, const Type& value);
inline void SetField(Message* message,
const FieldDescriptor* field, const Type& value) const;
template <typename Type>
inline Type* MutableField(const FieldDescriptor* field);
inline Type* MutableField(Message* message,
const FieldDescriptor* field) const;
template <typename Type>
inline const Type& GetRepeatedField(const FieldDescriptor* field,
inline const Type& GetRepeatedField(const Message& message,
const FieldDescriptor* field,
int index) const;
template <typename Type>
inline void SetRepeatedField(const FieldDescriptor* field, int index,
const Type& value);
inline void SetRepeatedField(Message* message,
const FieldDescriptor* field, int index,
const Type& value) const;
template <typename Type>
inline Type* MutableRepeatedField(const FieldDescriptor* field, int index);
inline Type* MutableRepeatedField(Message* message,
const FieldDescriptor* field,
int index) const;
template <typename Type>
inline void AddField(const FieldDescriptor* field, const Type& value);
inline void AddField(Message* message,
const FieldDescriptor* field, const Type& value) const;
template <typename Type>
inline Type* AddField(const FieldDescriptor* field);
inline Type* AddField(Message* message,
const FieldDescriptor* field) const;
int GetExtensionNumberOrDie(const Descriptor* type) const;

View file

@ -56,21 +56,21 @@ TEST(GeneratedMessageReflectionTest, Defaults) {
TestUtil::ReflectionTester reflection_tester(
unittest::TestAllTypes::descriptor());
reflection_tester.ExpectClearViaReflection(*message.GetReflection());
reflection_tester.ExpectClearViaReflection(message);
const Message::Reflection& reflection = *message.GetReflection();
const Reflection* reflection = message.GetReflection();
// Messages should return pointers to default instances until first use.
// (This is not checked by ExpectClear() since it is not actually true after
// the fields have been set and then cleared.)
EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(),
&reflection.GetMessage(F("optionalgroup")));
&reflection->GetMessage(message, F("optionalgroup")));
EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
&reflection.GetMessage(F("optional_nested_message")));
&reflection->GetMessage(message, F("optional_nested_message")));
EXPECT_EQ(&unittest::ForeignMessage::default_instance(),
&reflection.GetMessage(F("optional_foreign_message")));
&reflection->GetMessage(message, F("optional_foreign_message")));
EXPECT_EQ(&unittest_import::ImportMessage::default_instance(),
&reflection.GetMessage(F("optional_import_message")));
&reflection->GetMessage(message, F("optional_import_message")));
}
TEST(GeneratedMessageReflectionTest, Accessors) {
@ -80,11 +80,11 @@ TEST(GeneratedMessageReflectionTest, Accessors) {
TestUtil::ReflectionTester reflection_tester(
unittest::TestAllTypes::descriptor());
reflection_tester.SetAllFieldsViaReflection(message.GetReflection());
reflection_tester.SetAllFieldsViaReflection(&message);
TestUtil::ExpectAllFieldsSet(message);
reflection_tester.ExpectAllFieldsSetViaReflection(*message.GetReflection());
reflection_tester.ExpectAllFieldsSetViaReflection(message);
reflection_tester.ModifyRepeatedFieldsViaReflection(message.GetReflection());
reflection_tester.ModifyRepeatedFieldsViaReflection(&message);
TestUtil::ExpectRepeatedFieldsModified(message);
}
@ -95,15 +95,16 @@ TEST(GeneratedMessageReflectionTest, GetStringReference) {
message.set_optional_string("foo");
message.add_repeated_string("foo");
const Message::Reflection& reflection = *message.GetReflection();
const Reflection* reflection = message.GetReflection();
string scratch;
EXPECT_EQ(&message.optional_string(),
&reflection.GetStringReference(F("optional_string"), &scratch))
&reflection->GetStringReference(message, F("optional_string"), &scratch))
<< "For simple string fields, GetStringReference() should return a "
"reference to the underlying string.";
EXPECT_EQ(&message.repeated_string(0),
&reflection.GetRepeatedStringReference(F("repeated_string"), 0, &scratch))
&reflection->GetRepeatedStringReference(message, F("repeated_string"),
0, &scratch))
<< "For simple string fields, GetRepeatedStringReference() should return "
"a reference to the underlying string.";
}
@ -119,16 +120,16 @@ TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) {
TestUtil::SetAllFields(&message);
message.Clear();
const Message::Reflection& reflection = *message.GetReflection();
const Reflection* reflection = message.GetReflection();
EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(),
&reflection.GetMessage(F("optionalgroup")));
&reflection->GetMessage(message, F("optionalgroup")));
EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(),
&reflection.GetMessage(F("optional_nested_message")));
&reflection->GetMessage(message, F("optional_nested_message")));
EXPECT_NE(&unittest::ForeignMessage::default_instance(),
&reflection.GetMessage(F("optional_foreign_message")));
&reflection->GetMessage(message, F("optional_foreign_message")));
EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
&reflection.GetMessage(F("optional_import_message")));
&reflection->GetMessage(message, F("optional_import_message")));
}
TEST(GeneratedMessageReflectionTest, Extensions) {
@ -138,17 +139,17 @@ TEST(GeneratedMessageReflectionTest, Extensions) {
TestUtil::ReflectionTester reflection_tester(
unittest::TestAllExtensions::descriptor());
reflection_tester.SetAllFieldsViaReflection(message.GetReflection());
reflection_tester.SetAllFieldsViaReflection(&message);
TestUtil::ExpectAllExtensionsSet(message);
reflection_tester.ExpectAllFieldsSetViaReflection(*message.GetReflection());
reflection_tester.ExpectAllFieldsSetViaReflection(message);
reflection_tester.ModifyRepeatedFieldsViaReflection(message.GetReflection());
reflection_tester.ModifyRepeatedFieldsViaReflection(&message);
TestUtil::ExpectRepeatedExtensionsModified(message);
}
TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) {
const Message::Reflection& reflection =
*unittest::TestAllExtensions::default_instance().GetReflection();
const Reflection* reflection =
unittest::TestAllExtensions::default_instance().GetReflection();
const FieldDescriptor* extension1 =
unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
@ -158,12 +159,12 @@ TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) {
"repeated_string_extension");
EXPECT_EQ(extension1,
reflection.FindKnownExtensionByNumber(extension1->number()));
reflection->FindKnownExtensionByNumber(extension1->number()));
EXPECT_EQ(extension2,
reflection.FindKnownExtensionByNumber(extension2->number()));
reflection->FindKnownExtensionByNumber(extension2->number()));
// Non-existent extension.
EXPECT_TRUE(reflection.FindKnownExtensionByNumber(62341) == NULL);
EXPECT_TRUE(reflection->FindKnownExtensionByNumber(62341) == NULL);
// Extensions of TestAllExtensions should not show up as extensions of
// other types.
@ -172,8 +173,8 @@ TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) {
}
TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) {
const Message::Reflection& reflection =
*unittest::TestAllExtensions::default_instance().GetReflection();
const Reflection* reflection =
unittest::TestAllExtensions::default_instance().GetReflection();
const FieldDescriptor* extension1 =
unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName(
@ -183,12 +184,12 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) {
"repeated_string_extension");
EXPECT_EQ(extension1,
reflection.FindKnownExtensionByName(extension1->full_name()));
reflection->FindKnownExtensionByName(extension1->full_name()));
EXPECT_EQ(extension2,
reflection.FindKnownExtensionByName(extension2->full_name()));
reflection->FindKnownExtensionByName(extension2->full_name()));
// Non-existent extension.
EXPECT_TRUE(reflection.FindKnownExtensionByName("no_such_ext") == NULL);
EXPECT_TRUE(reflection->FindKnownExtensionByName("no_such_ext") == NULL);
// Extensions of TestAllExtensions should not show up as extensions of
// other types.
@ -200,7 +201,7 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) {
TEST(GeneratedMessageReflectionTest, UsageErrors) {
unittest::TestAllTypes message;
Message::Reflection* reflection = message.GetReflection();
const Reflection* reflection = message.GetReflection();
const Descriptor* descriptor = message.GetDescriptor();
#define f(NAME) descriptor->FindFieldByName(NAME)
@ -208,34 +209,36 @@ TEST(GeneratedMessageReflectionTest, UsageErrors) {
// Testing every single failure mode would be too much work. Let's just
// check a few.
EXPECT_DEATH(
reflection->GetInt32(descriptor->FindFieldByName("optional_int64")),
reflection->GetInt32(
message, descriptor->FindFieldByName("optional_int64")),
"Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::GetInt32\n"
" Method : google::protobuf::Reflection::GetInt32\n"
" Message type: protobuf_unittest\\.TestAllTypes\n"
" Field : protobuf_unittest\\.TestAllTypes\\.optional_int64\n"
" Problem : Field is not the right type for this message:\n"
" Expected : CPPTYPE_INT32\n"
" Field type: CPPTYPE_INT64");
EXPECT_DEATH(
reflection->GetInt32(descriptor->FindFieldByName("repeated_int32")),
reflection->GetInt32(
message, descriptor->FindFieldByName("repeated_int32")),
"Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::GetInt32\n"
" Method : google::protobuf::Reflection::GetInt32\n"
" Message type: protobuf_unittest.TestAllTypes\n"
" Field : protobuf_unittest.TestAllTypes.repeated_int32\n"
" Problem : Field is repeated; the method requires a singular field.");
EXPECT_DEATH(
reflection->GetInt32(
unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
"Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::GetInt32\n"
" Method : google::protobuf::Reflection::GetInt32\n"
" Message type: protobuf_unittest.TestAllTypes\n"
" Field : protobuf_unittest.ForeignMessage.c\n"
" Problem : Field does not match message type.");
EXPECT_DEATH(
reflection->HasField(
unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")),
"Protocol Buffer reflection usage error:\n"
" Method : google::protobuf::Message::Reflection::HasField\n"
" Method : google::protobuf::Reflection::HasField\n"
" Message type: protobuf_unittest.TestAllTypes\n"
" Field : protobuf_unittest.ForeignMessage.c\n"
" Problem : Field does not match message type.");

View file

@ -50,7 +50,6 @@ static string InitializationErrorMessage(const char* action,
}
Message::~Message() {}
Message::Reflection::~Reflection() {}
void Message::MergeFrom(const Message& from) {
const Descriptor* descriptor = GetDescriptor();
@ -58,7 +57,7 @@ void Message::MergeFrom(const Message& from) {
<< ": Tried to merge from a message with a different type. "
"to: " << descriptor->full_name() << ", "
"from:" << from.GetDescriptor()->full_name();
ReflectionOps::Merge(descriptor, *from.GetReflection(), GetReflection());
ReflectionOps::Merge(from, this);
}
void Message::CopyFrom(const Message& from) {
@ -67,20 +66,19 @@ void Message::CopyFrom(const Message& from) {
<< ": Tried to copy from a message with a different type."
"to: " << descriptor->full_name() << ", "
"from:" << from.GetDescriptor()->full_name();
ReflectionOps::Copy(descriptor, *from.GetReflection(), GetReflection());
ReflectionOps::Copy(from, this);
}
void Message::Clear() {
ReflectionOps::Clear(GetDescriptor(), GetReflection());
ReflectionOps::Clear(this);
}
bool Message::IsInitialized() const {
return ReflectionOps::IsInitialized(GetDescriptor(), *GetReflection());
return ReflectionOps::IsInitialized(*this);
}
void Message::FindInitializationErrors(vector<string>* errors) const {
return ReflectionOps::FindInitializationErrors(
GetDescriptor(), *GetReflection(), "", errors);
return ReflectionOps::FindInitializationErrors(*this, "", errors);
}
string Message::InitializationErrorString() const {
@ -96,12 +94,11 @@ void Message::CheckInitialized() const {
}
void Message::DiscardUnknownFields() {
return ReflectionOps::DiscardUnknownFields(GetDescriptor(), GetReflection());
return ReflectionOps::DiscardUnknownFields(this);
}
bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) {
return WireFormat::ParseAndMergePartial(
GetDescriptor(), input, GetReflection());
return WireFormat::ParseAndMergePartial(input, this);
}
bool Message::MergeFromCodedStream(io::CodedInputStream* input) {
@ -178,12 +175,11 @@ bool Message::ParsePartialFromIstream(istream* input) {
bool Message::SerializeWithCachedSizes(
io::CodedOutputStream* output) const {
return WireFormat::SerializeWithCachedSizes(
GetDescriptor(), GetReflection(), GetCachedSize(), output);
return WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
}
int Message::ByteSize() const {
int size = WireFormat::ByteSize(GetDescriptor(), GetReflection());
int size = WireFormat::ByteSize(*this);
SetCachedSize(size);
return size;
}
@ -281,6 +277,8 @@ bool Message::SerializePartialToOstream(ostream* output) const {
}
Reflection::~Reflection() {}
// ===================================================================
// MessageFactory

View file

@ -81,12 +81,12 @@
// foo->ParseFromString(data);
//
// // Use the reflection interface to examine the contents.
// Message::Reflection* reflection = foo->GetReflection();
// assert(reflection->GetString(text_field) == "Hello World!");
// assert(reflection->CountField(numbers_field) == 3);
// assert(reflection->GetInt32(numbers_field, 0) == 1);
// assert(reflection->GetInt32(numbers_field, 1) == 5);
// assert(reflection->GetInt32(numbers_field, 2) == 42);
// Reflection* reflection = foo->GetReflection();
// assert(reflection->GetString(foo, text_field) == "Hello World!");
// assert(reflection->CountField(foo, numbers_field) == 3);
// assert(reflection->GetInt32(foo, numbers_field, 0) == 1);
// assert(reflection->GetInt32(foo, numbers_field, 1) == 5);
// assert(reflection->GetInt32(foo, numbers_field, 2) == 42);
//
// delete foo;
// }
@ -105,6 +105,7 @@ namespace protobuf {
// Defined in this file.
class Message;
class Reflection;
// Defined in other files.
class Descriptor; // descriptor.h
@ -336,7 +337,8 @@ class LIBPROTOBUF_EXPORT Message {
// Introspection ---------------------------------------------------
class Reflection; // Defined below.
// Typedef for backwards-compatibility.
typedef google::protobuf::Reflection Reflection;
// Get a Descriptor for this message's type. This describes what
// fields the message contains, the types of those fields, etc.
@ -348,12 +350,6 @@ class LIBPROTOBUF_EXPORT Message {
// property of the Message.
virtual const Reflection* GetReflection() const = 0;
// Get the Reflection interface for this Message, which can be used to
// read and modify the fields of the Message dynamically (in other words,
// without knowing the message type at compile time). This object remains
// property of the Message.
virtual Reflection* GetReflection() = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
};
@ -367,7 +363,9 @@ class LIBPROTOBUF_EXPORT Message {
// This interface is separate from Message only for efficiency reasons;
// the vast majority of implementations of Message will share the same
// implementation of Reflection (GeneratedMessageReflection,
// defined in generated_message.h).
// defined in generated_message.h), and all Messages of a particular class
// should share the same Reflection object (though you should not rely on
// the latter fact).
//
// There are several ways that these methods can be used incorrectly. For
// example, any of the following conditions will lead to undefined
@ -382,6 +380,8 @@ class LIBPROTOBUF_EXPORT Message {
// field.
// - GetRepeated*(), SetRepeated*(), or Add*() is called on a non-repeated
// field.
// - The Message object passed to any method is not of the right type for
// this Reflection object (i.e. message.GetReflection() != reflection).
//
// You might wonder why there is not any abstract representation for a field
// of arbitrary type. E.g., why isn't there just a "GetField()" method that
@ -393,54 +393,75 @@ class LIBPROTOBUF_EXPORT Message {
// objects on-demand, on the other hand, would be expensive and prone to
// memory leaks. So, instead we ended up with this flat interface.
//
// WARNING: This class is currently in the process of being converted from
// a per-instance object to a per-class object. You'll notice that there
// are two sets of methods below: ones that take a Message pointer or
// reference as a parameter, and ones that don't. The former ones are the
// new interface; the latter ones will go away soon.
//
// TODO(kenton): Create a utility class which callers can use to read and
// write fields from a Reflection without paying attention to the type.
class LIBPROTOBUF_EXPORT Message::Reflection {
class LIBPROTOBUF_EXPORT Reflection {
public:
// TODO(kenton): Remove parameter.
inline Reflection() {}
virtual ~Reflection();
// Get the UnknownFieldSet for the message. This contains fields which
// were seen when the Message was parsed but were not recognized according
// to the Message's definition.
virtual const UnknownFieldSet& GetUnknownFields() const = 0;
virtual const UnknownFieldSet& GetUnknownFields(
const Message& message) const = 0;
// Get a mutable pointer to the UnknownFieldSet for the message. This
// contains fields which were seen when the Message was parsed but were not
// recognized according to the Message's definition.
virtual UnknownFieldSet* MutableUnknownFields() = 0;
virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0;
// Check if the given non-repeated field is set.
virtual bool HasField(const FieldDescriptor* field) const = 0;
virtual bool HasField(const Message& message,
const FieldDescriptor* field) const = 0;
// Get the number of elements of a repeated field.
virtual int FieldSize(const FieldDescriptor* field) const = 0;
virtual int FieldSize(const Message& message,
const FieldDescriptor* field) const = 0;
// Clear the value of a field, so that HasField() returns false or
// FieldSize() returns zero.
virtual void ClearField(const FieldDescriptor* field) = 0;
virtual void ClearField(Message* message,
const FieldDescriptor* field) const = 0;
// List all fields of the message which are currently set. This includes
// extensions. Singular fields will only be listed if HasField(field) would
// return true and repeated fields will only be listed if FieldSize(field)
// would return non-zero. Fields (both normal fields and extension fields)
// will be listed ordered by field number.
virtual void ListFields(vector<const FieldDescriptor*>* output) const = 0;
virtual void ListFields(const Message& message,
vector<const FieldDescriptor*>* output) const = 0;
// Singular field getters ------------------------------------------
// These get the value of a non-repeated field. They return the default
// value for fields that aren't set.
virtual int32 GetInt32 (const FieldDescriptor* field) const = 0;
virtual int64 GetInt64 (const FieldDescriptor* field) const = 0;
virtual uint32 GetUInt32(const FieldDescriptor* field) const = 0;
virtual uint64 GetUInt64(const FieldDescriptor* field) const = 0;
virtual float GetFloat (const FieldDescriptor* field) const = 0;
virtual double GetDouble(const FieldDescriptor* field) const = 0;
virtual bool GetBool (const FieldDescriptor* field) const = 0;
virtual string GetString(const FieldDescriptor* field) const = 0;
virtual int32 GetInt32 (const Message& message,
const FieldDescriptor* field) const = 0;
virtual int64 GetInt64 (const Message& message,
const FieldDescriptor* field) const = 0;
virtual uint32 GetUInt32(const Message& message,
const FieldDescriptor* field) const = 0;
virtual uint64 GetUInt64(const Message& message,
const FieldDescriptor* field) const = 0;
virtual float GetFloat (const Message& message,
const FieldDescriptor* field) const = 0;
virtual double GetDouble(const Message& message,
const FieldDescriptor* field) const = 0;
virtual bool GetBool (const Message& message,
const FieldDescriptor* field) const = 0;
virtual string GetString(const Message& message,
const FieldDescriptor* field) const = 0;
virtual const EnumValueDescriptor* GetEnum(
const FieldDescriptor* field) const = 0;
virtual const Message& GetMessage(const FieldDescriptor* field) const = 0;
const Message& message, const FieldDescriptor* field) const = 0;
virtual const Message& GetMessage(const Message& message,
const FieldDescriptor* field) const = 0;
// Get a string value without copying, if possible.
//
@ -457,98 +478,140 @@ class LIBPROTOBUF_EXPORT Message::Reflection {
// a newly-constructed string, though, it's just as fast and more readable
// to use code like:
// string str = reflection->GetString(field);
virtual const string& GetStringReference(const FieldDescriptor* field,
virtual const string& GetStringReference(const Message& message,
const FieldDescriptor* field,
string* scratch) const = 0;
// Singular field mutators -----------------------------------------
// These mutate the value of a non-repeated field.
virtual void SetInt32 (const FieldDescriptor* field, int32 value) = 0;
virtual void SetInt64 (const FieldDescriptor* field, int64 value) = 0;
virtual void SetUInt32(const FieldDescriptor* field, uint32 value) = 0;
virtual void SetUInt64(const FieldDescriptor* field, uint64 value) = 0;
virtual void SetFloat (const FieldDescriptor* field, float value) = 0;
virtual void SetDouble(const FieldDescriptor* field, double value) = 0;
virtual void SetBool (const FieldDescriptor* field, bool value) = 0;
virtual void SetString(const FieldDescriptor* field, const string& value) = 0;
virtual void SetEnum (const FieldDescriptor* field,
const EnumValueDescriptor* value) = 0;
virtual void SetInt32 (Message* message,
const FieldDescriptor* field, int32 value) const = 0;
virtual void SetInt64 (Message* message,
const FieldDescriptor* field, int64 value) const = 0;
virtual void SetUInt32(Message* message,
const FieldDescriptor* field, uint32 value) const = 0;
virtual void SetUInt64(Message* message,
const FieldDescriptor* field, uint64 value) const = 0;
virtual void SetFloat (Message* message,
const FieldDescriptor* field, float value) const = 0;
virtual void SetDouble(Message* message,
const FieldDescriptor* field, double value) const = 0;
virtual void SetBool (Message* message,
const FieldDescriptor* field, bool value) const = 0;
virtual void SetString(Message* message,
const FieldDescriptor* field,
const string& value) const = 0;
virtual void SetEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
// Get a mutable pointer to a field with a message type.
virtual Message* MutableMessage(const FieldDescriptor* field) = 0;
virtual Message* MutableMessage(Message* message,
const FieldDescriptor* field) const = 0;
// Repeated field getters ------------------------------------------
// These get the value of one element of a repeated field.
virtual int32 GetRepeatedInt32 (const FieldDescriptor* field,
virtual int32 GetRepeatedInt32 (const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual int64 GetRepeatedInt64 (const FieldDescriptor* field,
virtual int64 GetRepeatedInt64 (const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual uint32 GetRepeatedUInt32(const FieldDescriptor* field,
virtual uint32 GetRepeatedUInt32(const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual uint64 GetRepeatedUInt64(const FieldDescriptor* field,
virtual uint64 GetRepeatedUInt64(const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual float GetRepeatedFloat (const FieldDescriptor* field,
virtual float GetRepeatedFloat (const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual double GetRepeatedDouble(const FieldDescriptor* field,
virtual double GetRepeatedDouble(const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual bool GetRepeatedBool (const FieldDescriptor* field,
virtual bool GetRepeatedBool (const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual string GetRepeatedString(const FieldDescriptor* field,
virtual string GetRepeatedString(const Message& message,
const FieldDescriptor* field,
int index) const = 0;
virtual const EnumValueDescriptor* GetRepeatedEnum(
const Message& message,
const FieldDescriptor* field, int index) const = 0;
virtual const Message& GetRepeatedMessage(
const Message& message,
const FieldDescriptor* field, int index) const = 0;
// See GetStringReference(), above.
virtual const string& GetRepeatedStringReference(
const FieldDescriptor* field, int index,
string* scratch) const = 0;
const Message& message, const FieldDescriptor* field,
int index, string* scratch) const = 0;
// Repeated field mutators -----------------------------------------
// These mutate the value of one element of a repeated field.
virtual void SetRepeatedInt32 (const FieldDescriptor* field,
int index, int32 value) = 0;
virtual void SetRepeatedInt64 (const FieldDescriptor* field,
int index, int64 value) = 0;
virtual void SetRepeatedUInt32(const FieldDescriptor* field,
int index, uint32 value) = 0;
virtual void SetRepeatedUInt64(const FieldDescriptor* field,
int index, uint64 value) = 0;
virtual void SetRepeatedFloat (const FieldDescriptor* field,
int index, float value) = 0;
virtual void SetRepeatedDouble(const FieldDescriptor* field,
int index, double value) = 0;
virtual void SetRepeatedBool (const FieldDescriptor* field,
int index, bool value) = 0;
virtual void SetRepeatedString(const FieldDescriptor* field,
int index, const string& value) = 0;
virtual void SetRepeatedEnum(const FieldDescriptor* field,
int index, const EnumValueDescriptor* value) = 0;
virtual void SetRepeatedInt32 (Message* message,
const FieldDescriptor* field,
int index, int32 value) const = 0;
virtual void SetRepeatedInt64 (Message* message,
const FieldDescriptor* field,
int index, int64 value) const = 0;
virtual void SetRepeatedUInt32(Message* message,
const FieldDescriptor* field,
int index, uint32 value) const = 0;
virtual void SetRepeatedUInt64(Message* message,
const FieldDescriptor* field,
int index, uint64 value) const = 0;
virtual void SetRepeatedFloat (Message* message,
const FieldDescriptor* field,
int index, float value) const = 0;
virtual void SetRepeatedDouble(Message* message,
const FieldDescriptor* field,
int index, double value) const = 0;
virtual void SetRepeatedBool (Message* message,
const FieldDescriptor* field,
int index, bool value) const = 0;
virtual void SetRepeatedString(Message* message,
const FieldDescriptor* field,
int index, const string& value) const = 0;
virtual void SetRepeatedEnum(Message* message,
const FieldDescriptor* field, int index,
const EnumValueDescriptor* value) const = 0;
// Get a mutable pointer to an element of a repeated field with a message
// type.
virtual Message* MutableRepeatedMessage(
const FieldDescriptor* field, int index) = 0;
Message* message, const FieldDescriptor* field, int index) const = 0;
// Repeated field adders -------------------------------------------
// These add an element to a repeated field.
virtual void AddInt32 (const FieldDescriptor* field, int32 value) = 0;
virtual void AddInt64 (const FieldDescriptor* field, int64 value) = 0;
virtual void AddUInt32(const FieldDescriptor* field, uint32 value) = 0;
virtual void AddUInt64(const FieldDescriptor* field, uint64 value) = 0;
virtual void AddFloat (const FieldDescriptor* field, float value) = 0;
virtual void AddDouble(const FieldDescriptor* field, double value) = 0;
virtual void AddBool (const FieldDescriptor* field, bool value) = 0;
virtual void AddString(const FieldDescriptor* field, const string& value) = 0;
virtual void AddEnum (const FieldDescriptor* field,
const EnumValueDescriptor* value) = 0;
virtual Message* AddMessage(const FieldDescriptor* field) = 0;
virtual void AddInt32 (Message* message,
const FieldDescriptor* field, int32 value) const = 0;
virtual void AddInt64 (Message* message,
const FieldDescriptor* field, int64 value) const = 0;
virtual void AddUInt32(Message* message,
const FieldDescriptor* field, uint32 value) const = 0;
virtual void AddUInt64(Message* message,
const FieldDescriptor* field, uint64 value) const = 0;
virtual void AddFloat (Message* message,
const FieldDescriptor* field, float value) const = 0;
virtual void AddDouble(Message* message,
const FieldDescriptor* field, double value) const = 0;
virtual void AddBool (Message* message,
const FieldDescriptor* field, bool value) const = 0;
virtual void AddString(Message* message,
const FieldDescriptor* field,
const string& value) const = 0;
virtual void AddEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
virtual Message* AddMessage(Message* message,
const FieldDescriptor* field) const = 0;
// Extensions ------------------------------------------------------

View file

@ -27,31 +27,35 @@ namespace google {
namespace protobuf {
namespace internal {
void ReflectionOps::Copy(const Descriptor* descriptor,
const Message::Reflection& from,
Message::Reflection* to) {
void ReflectionOps::Copy(const Message& from, Message* to) {
if (&from == to) return;
Clear(descriptor, to);
Merge(descriptor, from, to);
Clear(to);
Merge(from, to);
}
void ReflectionOps::Merge(const Descriptor* descriptor,
const Message::Reflection& from,
Message::Reflection* to) {
void ReflectionOps::Merge(const Message& from, Message* to) {
GOOGLE_CHECK_NE(&from, to);
const Descriptor* descriptor = from.GetDescriptor();
GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor)
<< "Tried to merge messages of different types.";
const Reflection* from_reflection = from.GetReflection();
const Reflection* to_reflection = to->GetReflection();
vector<const FieldDescriptor*> fields;
from.ListFields(&fields);
from_reflection->ListFields(from, &fields);
for (int i = 0; i < fields.size(); i++) {
const FieldDescriptor* field = fields[i];
if (field->is_repeated()) {
int count = from.FieldSize(field);
int count = from_reflection->FieldSize(from, field);
for (int j = 0; j < count; j++) {
switch (field->cpp_type()) {
#define HANDLE_TYPE(CPPTYPE, METHOD) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
to->Add##METHOD(field, \
from.GetRepeated##METHOD(field, j)); \
to_reflection->Add##METHOD(to, field, \
from_reflection->GetRepeated##METHOD(from, field, j)); \
break;
HANDLE_TYPE(INT32 , Int32 );
@ -66,16 +70,17 @@ void ReflectionOps::Merge(const Descriptor* descriptor,
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_MESSAGE:
to->AddMessage(field)->MergeFrom(
from.GetRepeatedMessage(field, j));
to_reflection->AddMessage(to, field)->MergeFrom(
from_reflection->GetRepeatedMessage(from, field, j));
break;
}
}
} else if (from.HasField(field)) {
} else {
switch (field->cpp_type()) {
#define HANDLE_TYPE(CPPTYPE, METHOD) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
to->Set##METHOD(field, from.Get##METHOD(field)); \
to_reflection->Set##METHOD(to, field, \
from_reflection->Get##METHOD(from, field)); \
break;
HANDLE_TYPE(INT32 , Int32 );
@ -90,33 +95,37 @@ void ReflectionOps::Merge(const Descriptor* descriptor,
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_MESSAGE:
to->MutableMessage(field)->MergeFrom(
from.GetMessage(field));
to_reflection->MutableMessage(to, field)->MergeFrom(
from_reflection->GetMessage(from, field));
break;
}
}
}
to->MutableUnknownFields()->MergeFrom(from.GetUnknownFields());
to_reflection->MutableUnknownFields(to)->MergeFrom(
from_reflection->GetUnknownFields(from));
}
void ReflectionOps::Clear(const Descriptor* descriptor,
Message::Reflection* reflection) {
void ReflectionOps::Clear(Message* message) {
const Reflection* reflection = message->GetReflection();
vector<const FieldDescriptor*> fields;
reflection->ListFields(&fields);
reflection->ListFields(*message, &fields);
for (int i = 0; i < fields.size(); i++) {
reflection->ClearField(fields[i]);
reflection->ClearField(message, fields[i]);
}
reflection->MutableUnknownFields()->Clear();
reflection->MutableUnknownFields(message)->Clear();
}
bool ReflectionOps::IsInitialized(const Descriptor* descriptor,
const Message::Reflection& reflection) {
bool ReflectionOps::IsInitialized(const Message& message) {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = message.GetReflection();
// Check required fields of this message.
for (int i = 0; i < descriptor->field_count(); i++) {
if (descriptor->field(i)->is_required()) {
if (!reflection.HasField(descriptor->field(i))) {
if (!reflection->HasField(message, descriptor->field(i))) {
return false;
}
}
@ -124,21 +133,21 @@ bool ReflectionOps::IsInitialized(const Descriptor* descriptor,
// Check that sub-messages are initialized.
vector<const FieldDescriptor*> fields;
reflection.ListFields(&fields);
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
const FieldDescriptor* field = fields[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (field->is_repeated()) {
int size = reflection.FieldSize(field);
int size = reflection->FieldSize(message, field);
for (int i = 0; i < size; i++) {
if (!reflection.GetRepeatedMessage(field, i).IsInitialized()) {
if (!reflection->GetRepeatedMessage(message, field, i)
.IsInitialized()) {
return false;
}
}
} else {
if (reflection.HasField(field) &&
!reflection.GetMessage(field).IsInitialized()) {
if (!reflection->GetMessage(message, field).IsInitialized()) {
return false;
}
}
@ -148,25 +157,24 @@ bool ReflectionOps::IsInitialized(const Descriptor* descriptor,
return true;
}
void ReflectionOps::DiscardUnknownFields(
const Descriptor* descriptor,
Message::Reflection* reflection) {
reflection->MutableUnknownFields()->Clear();
void ReflectionOps::DiscardUnknownFields(Message* message) {
const Reflection* reflection = message->GetReflection();
reflection->MutableUnknownFields(message)->Clear();
vector<const FieldDescriptor*> fields;
reflection->ListFields(&fields);
reflection->ListFields(*message, &fields);
for (int i = 0; i < fields.size(); i++) {
const FieldDescriptor* field = fields[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (field->is_repeated()) {
int size = reflection->FieldSize(field);
int size = reflection->FieldSize(*message, field);
for (int i = 0; i < size; i++) {
reflection->MutableRepeatedMessage(field, i)->DiscardUnknownFields();
reflection->MutableRepeatedMessage(message, field, i)
->DiscardUnknownFields();
}
} else {
if (reflection->HasField(field)) {
reflection->MutableMessage(field)->DiscardUnknownFields();
}
reflection->MutableMessage(message, field)->DiscardUnknownFields();
}
}
}
@ -193,14 +201,16 @@ static string SubMessagePrefix(const string& prefix,
}
void ReflectionOps::FindInitializationErrors(
const Descriptor* descriptor,
const Message::Reflection& reflection,
const Message& message,
const string& prefix,
vector<string>* errors) {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = message.GetReflection();
// Check required fields of this message.
for (int i = 0; i < descriptor->field_count(); i++) {
if (descriptor->field(i)->is_required()) {
if (!reflection.HasField(descriptor->field(i))) {
if (!reflection->HasField(message, descriptor->field(i))) {
errors->push_back(prefix + descriptor->field(i)->name());
}
}
@ -208,29 +218,26 @@ void ReflectionOps::FindInitializationErrors(
// Check sub-messages.
vector<const FieldDescriptor*> fields;
reflection.ListFields(&fields);
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
const FieldDescriptor* field = fields[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (field->is_repeated()) {
int size = reflection.FieldSize(field);
int size = reflection->FieldSize(message, field);
for (int i = 0; i < size; i++) {
const Message& sub_message = reflection.GetRepeatedMessage(field, i);
FindInitializationErrors(field->message_type(),
*sub_message.GetReflection(),
const Message& sub_message =
reflection->GetRepeatedMessage(message, field, i);
FindInitializationErrors(sub_message,
SubMessagePrefix(prefix, field, i),
errors);
}
} else {
if (reflection.HasField(field)) {
const Message& sub_message = reflection.GetMessage(field);
FindInitializationErrors(field->message_type(),
*sub_message.GetReflection(),
SubMessagePrefix(prefix, field, -1),
errors);
}
const Message& sub_message = reflection->GetMessage(message, field);
FindInitializationErrors(sub_message,
SubMessagePrefix(prefix, field, -1),
errors);
}
}
}

View file

@ -30,7 +30,7 @@ namespace google {
namespace protobuf {
namespace internal {
// Basic operations that can be performed using Message::Reflection.
// Basic operations that can be performed using reflection.
// These can be used as a cheap way to implement the corresponding
// methods of the Message interface, though they are likely to be
// slower than implementations tailored for the specific message type.
@ -41,24 +41,16 @@ namespace internal {
// This class is really a namespace that contains only static methods.
class LIBPROTOBUF_EXPORT ReflectionOps {
public:
static void Copy(const Descriptor* descriptor,
const Message::Reflection& from,
Message::Reflection* to);
static void Merge(const Descriptor* descriptor,
const Message::Reflection& from,
Message::Reflection* to);
static void Clear(const Descriptor* descriptor,
Message::Reflection* reflection);
static bool IsInitialized(const Descriptor* descriptor,
const Message::Reflection& reflection);
static void DiscardUnknownFields(const Descriptor* descriptor,
Message::Reflection* reflection);
static void Copy(const Message& from, Message* to);
static void Merge(const Message& from, Message* to);
static void Clear(Message* message);
static bool IsInitialized(const Message& message);
static void DiscardUnknownFields(Message* message);
// Finds all unset required fields in the message and adds their full
// paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to
// the front of each name.
static void FindInitializationErrors(const Descriptor* descriptor,
const Message::Reflection& reflection,
static void FindInitializationErrors(const Message& message,
const string& prefix,
vector<string>* errors);

View file

@ -45,14 +45,12 @@ TEST(ReflectionOpsTest, Copy) {
TestUtil::SetAllFields(&message);
ReflectionOps::Copy(message.descriptor(), *message.GetReflection(),
message2.GetReflection());
ReflectionOps::Copy(message, &message2);
TestUtil::ExpectAllFieldsSet(message2);
// Copying from self should be a no-op.
ReflectionOps::Copy(message2.descriptor(), *message2.GetReflection(),
message2.GetReflection());
ReflectionOps::Copy(message2, &message2);
TestUtil::ExpectAllFieldsSet(message2);
}
@ -61,8 +59,7 @@ TEST(ReflectionOpsTest, CopyExtensions) {
TestUtil::SetAllExtensions(&message);
ReflectionOps::Copy(message.descriptor(), *message.GetReflection(),
message2.GetReflection());
ReflectionOps::Copy(message, &message2);
TestUtil::ExpectAllExtensionsSet(message2);
}
@ -89,8 +86,7 @@ TEST(ReflectionOpsTest, Merge) {
message.clear_repeated_int32();
message.add_repeated_int32(i);
ReflectionOps::Merge(message2.descriptor(), *message2.GetReflection(),
message.GetReflection());
ReflectionOps::Merge(message2, &message);
TestUtil::ExpectAllFieldsSet(message);
}
@ -120,8 +116,7 @@ TEST(ReflectionOpsTest, MergeExtensions) {
message.ClearExtension(unittest::repeated_int32_extension);
message.AddExtension(unittest::repeated_int32_extension, i);
ReflectionOps::Merge(message2.descriptor(), *message2.GetReflection(),
message.GetReflection());
ReflectionOps::Merge(message2, &message);
TestUtil::ExpectAllExtensionsSet(message);
}
@ -132,9 +127,7 @@ TEST(ReflectionOpsTest, MergeUnknown) {
message1.mutable_unknown_fields()->AddField(1234)->add_varint(1);
message2.mutable_unknown_fields()->AddField(1234)->add_varint(2);
ReflectionOps::Merge(unittest::TestEmptyMessage::descriptor(),
*message2.GetReflection(),
message1.GetReflection());
ReflectionOps::Merge(message2, &message1);
ASSERT_EQ(1, message1.unknown_fields().field_count());
const UnknownField& field = message1.unknown_fields().field(0);
@ -152,8 +145,7 @@ TEST(ReflectionOpsTest, MergeFromSelf) {
unittest::TestAllTypes message;
EXPECT_DEATH(
ReflectionOps::Merge(message.descriptor(), *message.GetReflection(),
message.GetReflection()),
ReflectionOps::Merge(message, &message),
"&from");
}
@ -164,7 +156,7 @@ TEST(ReflectionOpsTest, Clear) {
TestUtil::SetAllFields(&message);
ReflectionOps::Clear(message.descriptor(), message.GetReflection());
ReflectionOps::Clear(&message);
TestUtil::ExpectClear(message);
@ -185,7 +177,7 @@ TEST(ReflectionOpsTest, ClearExtensions) {
TestUtil::SetAllExtensions(&message);
ReflectionOps::Clear(message.descriptor(), message.GetReflection());
ReflectionOps::Clear(&message);
TestUtil::ExpectExtensionsClear(message);
@ -207,7 +199,7 @@ TEST(ReflectionOpsTest, ClearUnknown) {
unittest::TestEmptyMessage message;
message.mutable_unknown_fields()->AddField(1234)->add_varint(1);
ReflectionOps::Clear(message.descriptor(), message.GetReflection());
ReflectionOps::Clear(&message);
EXPECT_EQ(0, message.unknown_fields().field_count());
}
@ -236,8 +228,7 @@ TEST(ReflectionOpsTest, DiscardUnknownFields) {
.unknown_fields().field_count());
// Discard them.
ReflectionOps::DiscardUnknownFields(message.GetDescriptor(),
message.GetReflection());
ReflectionOps::DiscardUnknownFields(&message);
TestUtil::ExpectAllFieldsSet(message);
EXPECT_EQ(0, message.unknown_fields().field_count());
@ -273,8 +264,7 @@ TEST(ReflectionOpsTest, DiscardUnknownExtensions) {
.unknown_fields().field_count());
// Discard them.
ReflectionOps::DiscardUnknownFields(message.GetDescriptor(),
message.GetReflection());
ReflectionOps::DiscardUnknownFields(&message);
TestUtil::ExpectAllExtensionsSet(message);
EXPECT_EQ(0, message.unknown_fields().field_count());
@ -289,17 +279,13 @@ TEST(ReflectionOpsTest, DiscardUnknownExtensions) {
TEST(ReflectionOpsTest, IsInitialized) {
unittest::TestRequired message;
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
message.set_a(1);
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
message.set_b(2);
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
message.set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
}
TEST(ReflectionOpsTest, ForeignIsInitialized) {
@ -307,32 +293,27 @@ TEST(ReflectionOpsTest, ForeignIsInitialized) {
// Starts out initialized because the foreign message is itself an optional
// field.
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
// Once we create that field, the message is no longer initialized.
message.mutable_optional_message();
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
// Initialize it. Now we're initialized.
message.mutable_optional_message()->set_a(1);
message.mutable_optional_message()->set_b(2);
message.mutable_optional_message()->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
// Add a repeated version of the message. No longer initialized.
unittest::TestRequired* sub_message = message.add_repeated_message();
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
// Initialize that repeated version.
sub_message->set_a(1);
sub_message->set_b(2);
sub_message->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
}
TEST(ReflectionOpsTest, ExtensionIsInitialized) {
@ -340,39 +321,32 @@ TEST(ReflectionOpsTest, ExtensionIsInitialized) {
// Starts out initialized because the foreign message is itself an optional
// field.
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
// Once we create that field, the message is no longer initialized.
message.MutableExtension(unittest::TestRequired::single);
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
// Initialize it. Now we're initialized.
message.MutableExtension(unittest::TestRequired::single)->set_a(1);
message.MutableExtension(unittest::TestRequired::single)->set_b(2);
message.MutableExtension(unittest::TestRequired::single)->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
// Add a repeated version of the message. No longer initialized.
message.AddExtension(unittest::TestRequired::multi);
EXPECT_FALSE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
// Initialize that repeated version.
message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message.descriptor(),
*message.GetReflection()));
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
}
static string FindInitializationErrors(const Message& message) {
vector<string> errors;
ReflectionOps::FindInitializationErrors(message.GetDescriptor(),
*message.GetReflection(),
"", &errors);
ReflectionOps::FindInitializationErrors(message, "", &errors);
return JoinStrings(errors, ",");
}

View file

@ -103,7 +103,7 @@ class Message; // message.h
// themselves are abstract interfaces (implemented either by servers or as
// stubs), but they subclass this base interface. The methods of this
// interface can be used to call the methods of the Service without knowing
// its exact type at compile time (analogous to Message::Reflection).
// its exact type at compile time (analogous to Reflection).
class LIBPROTOBUF_EXPORT Service {
public:
inline Service() {}

View file

@ -69,20 +69,20 @@ namespace internal {
// The minimum library version which works with the current version of the
// headers.
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2000000
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2000001
// The minimum header version which works with the current version of
// the library. This constant should only be used by protoc's C++ code
// generator.
static const int kMinHeaderVersionForLibrary = 2000000;
static const int kMinHeaderVersionForLibrary = 2000001;
// The minimum protoc version which works with the current version of the
// headers.
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2000000
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2000001
// The minimum header version which works with the current version of
// protoc. This constant should only be used in VerifyVersion().
static const int kMinHeaderVersionForProtoc = 2000000;
static const int kMinHeaderVersionForProtoc = 2000001;
// Verifies that the headers and libraries are compatible. Use the macro
// below to call this.

File diff suppressed because it is too large Load diff

View file

@ -78,11 +78,10 @@ class TestUtil {
// its file.
explicit ReflectionTester(const Descriptor* base_descriptor);
void SetAllFieldsViaReflection(Message::Reflection* message);
void ModifyRepeatedFieldsViaReflection(Message::Reflection* message);
void ExpectAllFieldsSetViaReflection(
const Message::Reflection& message);
void ExpectClearViaReflection(const Message::Reflection& message);
void SetAllFieldsViaReflection(Message* message);
void ModifyRepeatedFieldsViaReflection(Message* message);
void ExpectAllFieldsSetViaReflection(const Message& message);
void ExpectClearViaReflection(const Message& message);
private:
const FieldDescriptor* F(const string& name);

View file

@ -126,9 +126,28 @@ string TestTempDir() {
return temp_dir_deleter_.GetTempDir();
}
// TODO(kenton): Share duplicated code below. Too busy/lazy for now.
static string stdout_capture_filename_;
static string stderr_capture_filename_;
static int original_stdout_ = -1;
static int original_stderr_ = -1;
void CaptureTestStdout() {
GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing.";
stdout_capture_filename_ = TestTempDir() + "/captured_stdout";
int fd = open(stdout_capture_filename_.c_str(),
O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777);
GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno);
original_stdout_ = dup(1);
close(1);
dup2(fd, 1);
close(fd);
}
void CaptureTestStderr() {
GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing.";
@ -144,6 +163,21 @@ void CaptureTestStderr() {
close(fd);
}
string GetCapturedTestStdout() {
GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing.";
close(1);
dup2(original_stdout_, 1);
original_stdout_ = -1;
string result;
File::ReadFileToStringOrDie(stdout_capture_filename_, &result);
remove(stdout_capture_filename_.c_str());
return result;
}
string GetCapturedTestStderr() {
GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing.";

View file

@ -33,10 +33,12 @@ string TestSourceDir();
// placed.
string TestTempDir();
// Capture all text written to stderr.
// Capture all text written to stdout or stderr.
void CaptureTestStdout();
void CaptureTestStderr();
// Stop capturing stderr and return the text captured.
// Stop capturing stdout or stderr and return the text captured.
string GetCapturedTestStdout();
string GetCapturedTestStderr();
// For use with ScopedMemoryLog::GetMessages(). Inside Google the LogLevel

View file

@ -103,9 +103,7 @@ class TextFormat::ParserImpl {
// false if an error occurs (an error will also be logged to
// GOOGLE_LOG(ERROR)).
bool Parse(Message* output) {
Message::Reflection* reflection = output->GetReflection();
const Descriptor* descriptor = output->GetDescriptor();
root_message_type_ = descriptor;
root_message_type_ = output->GetDescriptor();
// Consume fields until we cannot do so anymore.
while(true) {
@ -113,7 +111,7 @@ class TextFormat::ParserImpl {
return true;
}
DO(ConsumeField(reflection, descriptor));
DO(ConsumeField(output));
}
}
@ -148,11 +146,8 @@ class TextFormat::ParserImpl {
// This method checks to see that the end delimeter at the conclusion of
// the consumption matches the starting delimeter passed in here.
bool ConsumeMessage(Message* message, const string delimeter) {
Message::Reflection* reflection = message->GetReflection();
const Descriptor* descriptor = message->GetDescriptor();
while (!LookingAt(">") && !LookingAt("}")) {
DO(ConsumeField(reflection, descriptor));
DO(ConsumeField(message));
}
// Confirm that we have a valid ending delimeter.
@ -163,8 +158,10 @@ class TextFormat::ParserImpl {
// Consumes the current field (as returned by the tokenizer) on the
// passed in message.
bool ConsumeField(Message::Reflection* reflection,
const Descriptor* descriptor) {
bool ConsumeField(Message* message) {
const Reflection* reflection = message->GetReflection();
const Descriptor* descriptor = message->GetDescriptor();
string field_name;
const FieldDescriptor* field = NULL;
@ -232,19 +229,21 @@ class TextFormat::ParserImpl {
}
if (field->is_repeated()) {
DO(ConsumeMessage(reflection->AddMessage(field), delimeter));
DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter));
} else {
DO(ConsumeMessage(reflection->MutableMessage(field), delimeter));
DO(ConsumeMessage(reflection->MutableMessage(message, field),
delimeter));
}
} else {
DO(Consume(":"));
DO(ConsumeFieldValue(reflection, field));
DO(ConsumeFieldValue(message, reflection, field));
}
return true;
}
bool ConsumeFieldValue(Message::Reflection* reflection,
bool ConsumeFieldValue(Message* message,
const Reflection* reflection,
const FieldDescriptor* field) {
// Define an easy to use macro for setting fields. This macro checks
@ -252,9 +251,9 @@ class TextFormat::ParserImpl {
// methods or not (in which case we need to use the Set methods).
#define SET_FIELD(CPPTYPE, VALUE) \
if (field->is_repeated()) { \
reflection->Add##CPPTYPE(field, VALUE); \
reflection->Add##CPPTYPE(message, field, VALUE); \
} else { \
reflection->Set##CPPTYPE(field, VALUE); \
reflection->Set##CPPTYPE(message, field, VALUE); \
} \
switch(field->cpp_type()) {
@ -742,7 +741,7 @@ bool TextFormat::Parser::MergeFromString(const string& input,
io::ZeroCopyOutputStream* output) {
TextGenerator generator(output);
Print(message.GetDescriptor(), message.GetReflection(), generator);
Print(message, generator);
// Output false if the generator failed internally.
return !generator.failed();
@ -759,15 +758,15 @@ bool TextFormat::Parser::MergeFromString(const string& input,
return !generator.failed();
}
/* static */ void TextFormat::Print(const Descriptor* descriptor,
const Message::Reflection* message,
/* static */ void TextFormat::Print(const Message& message,
TextGenerator& generator) {
const Reflection* reflection = message.GetReflection();
vector<const FieldDescriptor*> fields;
message->ListFields(&fields);
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
PrintField(fields[i], message, generator);
PrintField(message, reflection, fields[i], generator);
}
PrintUnknownFields(message->GetUnknownFields(), generator);
PrintUnknownFields(reflection->GetUnknownFields(message), generator);
}
/* static */ void TextFormat::PrintFieldValueToString(
@ -782,17 +781,18 @@ bool TextFormat::Parser::MergeFromString(const string& input,
io::StringOutputStream output_stream(output);
TextGenerator generator(&output_stream);
PrintFieldValue(message.GetReflection(), field, index, generator);
PrintFieldValue(message, message.GetReflection(), field, index, generator);
}
/* static */ void TextFormat::PrintField(const FieldDescriptor* field,
const Message::Reflection* message,
/* static */ void TextFormat::PrintField(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
TextGenerator& generator) {
int count = 0;
if (field->is_repeated()) {
count = message->FieldSize(field);
} else if (message->HasField(field)) {
count = reflection->FieldSize(message, field);
} else if (reflection->HasField(message, field)) {
count = 1;
}
@ -831,7 +831,7 @@ bool TextFormat::Parser::MergeFromString(const string& input,
field_index = -1;
}
PrintFieldValue(message, field, field_index, generator);
PrintFieldValue(message, reflection, field, field_index, generator);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
generator.Outdent();
@ -843,7 +843,8 @@ bool TextFormat::Parser::MergeFromString(const string& input,
}
/* static */ void TextFormat::PrintFieldValue(
const Message::Reflection* reflection,
const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
int index,
TextGenerator& generator) {
@ -854,8 +855,8 @@ bool TextFormat::Parser::MergeFromString(const string& input,
#define OUTPUT_FIELD(CPPTYPE, METHOD, TO_STRING) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
generator.Print(TO_STRING(field->is_repeated() ? \
reflection->GetRepeated##METHOD(field, index) : \
reflection->Get##METHOD(field))); \
reflection->GetRepeated##METHOD(message, field, index) : \
reflection->Get##METHOD(message, field))); \
break; \
OUTPUT_FIELD( INT32, Int32, SimpleItoa);
@ -869,8 +870,9 @@ bool TextFormat::Parser::MergeFromString(const string& input,
case FieldDescriptor::CPPTYPE_STRING: {
string scratch;
const string& value = field->is_repeated() ?
reflection->GetRepeatedStringReference(field, index, &scratch) :
reflection->GetStringReference(field, &scratch);
reflection->GetRepeatedStringReference(
message, field, index, &scratch) :
reflection->GetStringReference(message, field, &scratch);
generator.Print("\"");
generator.Print(CEscape(value));
@ -881,24 +883,25 @@ bool TextFormat::Parser::MergeFromString(const string& input,
case FieldDescriptor::CPPTYPE_BOOL:
if (field->is_repeated()) {
generator.Print(reflection->GetRepeatedBool(field, index)
generator.Print(reflection->GetRepeatedBool(message, field, index)
? "true" : "false");
} else {
generator.Print(reflection->GetBool(field) ? "true" : "false");
generator.Print(reflection->GetBool(message, field)
? "true" : "false");
}
break;
case FieldDescriptor::CPPTYPE_ENUM:
generator.Print(field->is_repeated() ?
reflection->GetRepeatedEnum(field, index)->name()
: reflection->GetEnum(field)->name());
reflection->GetRepeatedEnum(message, field, index)->name() :
reflection->GetEnum(message, field)->name());
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
Print(field->message_type(),
field->is_repeated() ?
reflection->GetRepeatedMessage(field, index).GetReflection()
: reflection->GetMessage(field).GetReflection(), generator);
Print(field->is_repeated() ?
reflection->GetRepeatedMessage(message, field, index) :
reflection->GetMessage(message, field),
generator);
break;
}
}

View file

@ -25,7 +25,7 @@
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
#include <string>
#include <google/protobuf/message.h> // Message, Message::Reflection
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
namespace google {
@ -124,18 +124,19 @@ class LIBPROTOBUF_EXPORT TextFormat {
// Internal Print method, used for writing to the OutputStream via
// the TextGenerator class.
static void Print(const Descriptor* descriptor,
const Message::Reflection* message,
static void Print(const Message& message,
TextGenerator& generator);
// Print a single field.
static void PrintField(const FieldDescriptor* field,
const Message::Reflection* message,
static void PrintField(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
TextGenerator& generator);
// Outputs a textual representation of the value of the field supplied on
// the message supplied or the default value if not set.
static void PrintFieldValue(const Message::Reflection* reflection,
static void PrintFieldValue(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
int index,
TextGenerator& generator);

View file

@ -731,7 +731,8 @@ TEST_F(TextFormatMessageSetTest, Deserialize) {
// Ensure that these are the only entries present.
vector<const FieldDescriptor*> descriptors;
proto.message_set().GetReflection()->ListFields(&descriptors);
proto.message_set().GetReflection()->ListFields(
proto.message_set(), &descriptors);
EXPECT_EQ(2, descriptors.size());
}

View file

@ -43,7 +43,7 @@ class UnknownField; // below
// to be updated every time a new field is added to the message definition.
//
// To get the UnknownFieldSet attached to any message, call
// Message::Reflection::GetUnknownFields().
// Reflection::GetUnknownFields().
//
// This class is necessarily tied to the protocol buffer wire format, unlike
// the Reflection interface which is independent of any serialization scheme.

View file

@ -176,8 +176,7 @@ TEST_F(UnknownFieldSetTest, ParseViaReflection) {
io::ArrayInputStream raw_input(all_fields_data_.data(),
all_fields_data_.size());
io::CodedInputStream input(&raw_input);
ASSERT_TRUE(WireFormat::ParseAndMergePartial(message.GetDescriptor(), &input,
message.GetReflection()));
ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message));
EXPECT_EQ(message.DebugString(), empty_message_.DebugString());
}
@ -191,12 +190,9 @@ TEST_F(UnknownFieldSetTest, SerializeViaReflection) {
{
io::StringOutputStream raw_output(&data);
io::CodedOutputStream output(&raw_output);
int size = WireFormat::ByteSize(empty_message_.GetDescriptor(),
empty_message_.GetReflection());
int size = WireFormat::ByteSize(empty_message_);
ASSERT_TRUE(
WireFormat::SerializeWithCachedSizes(empty_message_.GetDescriptor(),
empty_message_.GetReflection(),
size, &output));
WireFormat::SerializeWithCachedSizes(empty_message_, size, &output));
}
// Don't use EXPECT_EQ because we don't want to dump raw binary data to
@ -290,9 +286,7 @@ TEST_F(UnknownFieldSetTest, WrongTypeTreatedAsUnknownViaReflection) {
string bizarro_data = GetBizarroData();
io::ArrayInputStream raw_input(bizarro_data.data(), bizarro_data.size());
io::CodedInputStream input(&raw_input);
ASSERT_TRUE(WireFormat::ParseAndMergePartial(
all_types_message.GetDescriptor(), &input,
all_types_message.GetReflection()));
ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &all_types_message));
ASSERT_TRUE(empty_message.ParseFromString(bizarro_data));
EXPECT_EQ(empty_message.DebugString(), all_types_message.DebugString());
@ -315,8 +309,7 @@ TEST_F(UnknownFieldSetTest, UnknownExtensionsReflection) {
io::ArrayInputStream raw_input(all_fields_data_.data(),
all_fields_data_.size());
io::CodedInputStream input(&raw_input);
ASSERT_TRUE(WireFormat::ParseAndMergePartial(message.GetDescriptor(), &input,
message.GetReflection()));
ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message));
EXPECT_EQ(message.DebugString(), empty_message_.DebugString());
}

View file

@ -117,7 +117,9 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
if (field == NULL) {
if (!input->Skip(length)) return false;
} else {
input->ReadString(field->add_length_delimited(), length);
if (!input->ReadString(field->add_length_delimited(), length)) {
return false;
}
}
return true;
}
@ -299,9 +301,11 @@ int WireFormat::ComputeUnknownMessageSetItemsSize(
// ===================================================================
bool WireFormat::ParseAndMergePartial(const Descriptor* descriptor,
io::CodedInputStream* input,
Message::Reflection* message_reflection) {
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) {
@ -330,14 +334,14 @@ bool WireFormat::ParseAndMergePartial(const Descriptor* descriptor,
if (field == NULL &&
descriptor->options().message_set_wire_format() &&
tag == kMessageSetItemStartTag) {
if (!ParseAndMergeMessageSetItem(input, message_reflection)) {
if (!ParseAndMergeMessageSetItem(input, message)) {
return false;
}
continue; // Skip ParseAndMergeField(); already taken care of.
}
}
if (!ParseAndMergeField(tag, field, message_reflection, input)) {
if (!ParseAndMergeField(tag, field, message, input)) {
return false;
}
}
@ -346,13 +350,16 @@ bool WireFormat::ParseAndMergePartial(const Descriptor* descriptor,
bool WireFormat::ParseAndMergeField(
uint32 tag,
const FieldDescriptor* field, // May be NULL for unknown
Message::Reflection* message_reflection,
Message* message,
io::CodedInputStream* input) {
const Reflection* message_reflection = message->GetReflection();
if (field == NULL ||
GetTagWireType(tag) != WireTypeForFieldType(field->type())) {
// We don't recognize this field. Either the field number is unknown
// or the wire type doesn't match. Put it in our unknown field set.
return SkipField(input, tag, message_reflection->MutableUnknownFields());
return SkipField(input, tag,
message_reflection->MutableUnknownFields(message));
}
switch (field->type()) {
@ -361,9 +368,9 @@ bool WireFormat::ParseAndMergeField(
CPPTYPE value; \
if (!Read##TYPE_METHOD(input, &value)) return false; \
if (field->is_repeated()) { \
message_reflection->Add##CPPTYPE_METHOD(field, value); \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} else { \
message_reflection->Set##CPPTYPE_METHOD(field, value); \
message_reflection->Set##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
@ -397,15 +404,15 @@ bool WireFormat::ParseAndMergeField(
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
if (field->is_repeated()) {
message_reflection->AddEnum(field, enum_value);
message_reflection->AddEnum(message, field, enum_value);
} else {
message_reflection->SetEnum(field, enum_value);
message_reflection->SetEnum(message, field, enum_value);
}
} else {
// The enum value is not one of the known values. Add it to the
// UnknownFieldSet.
int64 sign_extended_value = static_cast<int64>(value);
message_reflection->MutableUnknownFields()
message_reflection->MutableUnknownFields(message)
->AddField(GetTagFieldNumber(tag))
->add_varint(sign_extended_value);
}
@ -416,9 +423,9 @@ bool WireFormat::ParseAndMergeField(
case FieldDescriptor::TYPE_GROUP: {
Message* sub_message;
if (field->is_repeated()) {
sub_message = message_reflection->AddMessage(field);
sub_message = message_reflection->AddMessage(message, field);
} else {
sub_message = message_reflection->MutableMessage(field);
sub_message = message_reflection->MutableMessage(message, field);
}
if (!ReadGroup(GetTagFieldNumber(tag), input, sub_message)) return false;
@ -428,9 +435,9 @@ bool WireFormat::ParseAndMergeField(
case FieldDescriptor::TYPE_MESSAGE: {
Message* sub_message;
if (field->is_repeated()) {
sub_message = message_reflection->AddMessage(field);
sub_message = message_reflection->AddMessage(message, field);
} else {
sub_message = message_reflection->MutableMessage(field);
sub_message = message_reflection->MutableMessage(message, field);
}
if (!ReadMessage(input, sub_message)) return false;
@ -443,7 +450,9 @@ bool WireFormat::ParseAndMergeField(
bool WireFormat::ParseAndMergeMessageSetItem(
io::CodedInputStream* input,
Message::Reflection* message_reflection) {
Message* message) {
const Reflection* message_reflection = message->GetReflection();
// This method parses a group which should contain two fields:
// required int32 type_id = 2;
// required data message = 3;
@ -481,7 +490,7 @@ bool WireFormat::ParseAndMergeMessageSetItem(
io::ArrayInputStream raw_input(message_data.data(),
message_data.size());
io::CodedInputStream sub_input(&raw_input);
if (!ParseAndMergeField(fake_tag, field, message_reflection,
if (!ParseAndMergeField(fake_tag, field, message,
&sub_input)) {
return false;
}
@ -501,7 +510,7 @@ bool WireFormat::ParseAndMergeMessageSetItem(
message_data.append(temp);
} else {
// Already saw type_id, so we can parse this directly.
if (!ParseAndMergeField(fake_tag, field, message_reflection, input)) {
if (!ParseAndMergeField(fake_tag, field, message, input)) {
return false;
}
}
@ -523,27 +532,28 @@ bool WireFormat::ParseAndMergeMessageSetItem(
// ===================================================================
bool WireFormat::SerializeWithCachedSizes(
const Descriptor* descriptor,
const Message::Reflection* message_reflection,
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(&fields);
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
if (!SerializeFieldWithCachedSizes(fields[i], message_reflection, output)) {
if (!SerializeFieldWithCachedSizes(fields[i], message, output)) {
return false;
}
}
if (descriptor->options().message_set_wire_format()) {
if (!SerializeUnknownMessageSetItems(
message_reflection->GetUnknownFields(), output)) {
message_reflection->GetUnknownFields(message), output)) {
return false;
}
} else {
if (!SerializeUnknownFields(
message_reflection->GetUnknownFields(), output)) {
message_reflection->GetUnknownFields(message), output)) {
return false;
}
}
@ -558,21 +568,23 @@ bool WireFormat::SerializeWithCachedSizes(
bool WireFormat::SerializeFieldWithCachedSizes(
const FieldDescriptor* field,
const Message::Reflection* message_reflection,
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()) {
return SerializeMessageSetItemWithCachedSizes(
field, message_reflection, output);
field, message, output);
}
int count = 0;
if (field->is_repeated()) {
count = message_reflection->FieldSize(field);
} else if (message_reflection->HasField(field)) {
count = message_reflection->FieldSize(message, field);
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
@ -583,8 +595,9 @@ bool WireFormat::SerializeFieldWithCachedSizes(
if (!Write##TYPE_METHOD( \
field->number(), \
field->is_repeated() ? \
message_reflection->GetRepeated##CPPTYPE_METHOD(field, j) : \
message_reflection->Get##CPPTYPE_METHOD(field), \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j) : \
message_reflection->Get##CPPTYPE_METHOD(message, field), \
output)) { \
return false; \
} \
@ -613,8 +626,8 @@ bool WireFormat::SerializeFieldWithCachedSizes(
case FieldDescriptor::TYPE_ENUM: {
const EnumValueDescriptor* value = field->is_repeated() ?
message_reflection->GetRepeatedEnum(field, j) :
message_reflection->GetEnum(field);
message_reflection->GetRepeatedEnum(message, field, j) :
message_reflection->GetEnum(message, field);
if (!WriteEnum(field->number(), value->number(), output)) return false;
break;
}
@ -625,8 +638,9 @@ bool WireFormat::SerializeFieldWithCachedSizes(
case FieldDescriptor::TYPE_BYTES: {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(field, j, &scratch) :
message_reflection->GetStringReference(field, &scratch);
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
if (!WriteString(field->number(), value, output)) return false;
break;
}
@ -638,8 +652,10 @@ bool WireFormat::SerializeFieldWithCachedSizes(
bool WireFormat::SerializeMessageSetItemWithCachedSizes(
const FieldDescriptor* field,
const Message::Reflection* message_reflection,
const Message& message,
io::CodedOutputStream* output) {
const Reflection* message_reflection = message.GetReflection();
// Start group.
if (!output->WriteVarint32(kMessageSetItemStartTag)) return false;
@ -650,7 +666,7 @@ bool WireFormat::SerializeMessageSetItemWithCachedSizes(
// Write message.
if (!output->WriteVarint32(kMessageSetMessageTag)) return false;
const Message& sub_message = message_reflection->GetMessage(field);
const Message& sub_message = message_reflection->GetMessage(message, field);
if (!output->WriteVarint32(sub_message.GetCachedSize())) return false;
if (!sub_message.SerializeWithCachedSizes(output)) return false;
@ -662,23 +678,24 @@ bool WireFormat::SerializeMessageSetItemWithCachedSizes(
// ===================================================================
int WireFormat::ByteSize(
const Descriptor* descriptor,
const Message::Reflection* message_reflection) {
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(&fields);
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
our_size += FieldByteSize(fields[i], message_reflection);
our_size += FieldByteSize(fields[i], message);
}
if (descriptor->options().message_set_wire_format()) {
our_size += ComputeUnknownMessageSetItemsSize(
message_reflection->GetUnknownFields());
message_reflection->GetUnknownFields(message));
} else {
our_size += ComputeUnknownFieldsSize(
message_reflection->GetUnknownFields());
message_reflection->GetUnknownFields(message));
}
return our_size;
@ -686,12 +703,14 @@ int WireFormat::ByteSize(
int WireFormat::FieldByteSize(
const FieldDescriptor* field,
const Message::Reflection* message_reflection) {
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_reflection);
return MessageSetItemByteSize(field, message);
}
int our_size = 0;
@ -699,8 +718,8 @@ int WireFormat::FieldByteSize(
int count = 0;
if (field->is_repeated()) {
count = message_reflection->FieldSize(field);
} else if (message_reflection->HasField(field)) {
count = message_reflection->FieldSize(message, field);
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
@ -712,11 +731,12 @@ int WireFormat::FieldByteSize(
if (field->is_repeated()) { \
for (int j = 0; j < count; j++) { \
our_size += TYPE_METHOD##Size( \
message_reflection->GetRepeated##CPPTYPE_METHOD(field, j)); \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j)); \
} \
} else { \
our_size += TYPE_METHOD##Size( \
message_reflection->Get##CPPTYPE_METHOD(field)); \
message_reflection->Get##CPPTYPE_METHOD(message, field)); \
} \
break;
@ -751,11 +771,11 @@ int WireFormat::FieldByteSize(
if (field->is_repeated()) {
for (int j = 0; j < count; j++) {
our_size += EnumSize(
message_reflection->GetRepeatedEnum(field, j)->number());
message_reflection->GetRepeatedEnum(message, field, j)->number());
}
} else {
our_size += EnumSize(
message_reflection->GetEnum(field)->number());
message_reflection->GetEnum(message, field)->number());
}
break;
}
@ -767,8 +787,9 @@ int WireFormat::FieldByteSize(
for (int j = 0; j < count; j++) {
string scratch;
const string& value = field->is_repeated() ?
message_reflection->GetRepeatedStringReference(field, j, &scratch) :
message_reflection->GetStringReference(field, &scratch);
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
our_size += StringSize(value);
}
break;
@ -780,14 +801,16 @@ int WireFormat::FieldByteSize(
int WireFormat::MessageSetItemByteSize(
const FieldDescriptor* field,
const Message::Reflection* message_reflection) {
const Message& message) {
const Reflection* message_reflection = message.GetReflection();
int our_size = kMessageSetItemTagsSize;
// type_id
our_size += io::CodedOutputStream::VarintSize32(field->number());
// message
const Message& sub_message = message_reflection->GetMessage(field);
const Message& sub_message = message_reflection->GetMessage(message, field);
int message_size = sub_message.ByteSize();
our_size += io::CodedOutputStream::VarintSize32(message_size);

View file

@ -26,7 +26,7 @@
#define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
#include <string>
#include <google/protobuf/message.h> // Message::Reflection
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
namespace google {
@ -55,7 +55,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
public:
// These procedures can be used to implement the methods of Message which
// handle parsing and serialization of the protocol buffer wire format
// using only the Message::Reflection interface. When you ask the protocol
// using only the Reflection interface. When you ask the protocol
// compiler to optimize for code size rather than speed, it will implement
// those methods in terms of these procedures. Of course, these are much
// slower than the specialized implementations which the protocol compiler
@ -69,9 +69,8 @@ class LIBPROTOBUF_EXPORT WireFormat {
//
// Required fields are NOT checked by this method. You must call
// IsInitialized() on the resulting message yourself.
static bool ParseAndMergePartial(const Descriptor* descriptor,
io::CodedInputStream* input,
Message::Reflection* message_reflection);
static bool ParseAndMergePartial(io::CodedInputStream* input,
Message* message);
// Serialize a message in protocol buffer wire format.
//
@ -81,8 +80,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
//
// These return false iff the underlying stream returns a write error.
static bool SerializeWithCachedSizes(
const Descriptor* descriptor,
const Message::Reflection* message_reflection,
const Message& message,
int size, io::CodedOutputStream* output);
// Implements Message::ByteSize() via reflection. WARNING: The result
@ -90,8 +88,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
// will have their ByteSize() methods called, so their sizes will be cached.
// Therefore, calling this method is sufficient to allow you to call
// WireFormat::SerializeWithCachedSizes() on the same object.
static int ByteSize(const Descriptor* descriptor,
const Message::Reflection* message_reflection);
static int ByteSize(const Message& message);
// -----------------------------------------------------------------
// Helpers for dealing with unknown fields
@ -188,13 +185,13 @@ class LIBPROTOBUF_EXPORT WireFormat {
static bool ParseAndMergeField(
uint32 tag,
const FieldDescriptor* field, // May be NULL for unknown
Message::Reflection* message_reflection,
Message* message,
io::CodedInputStream* input);
// Serialize a single field.
static bool SerializeFieldWithCachedSizes(
const FieldDescriptor* field, // Cannot be NULL
const Message::Reflection* message_reflection,
const Message& message,
io::CodedOutputStream* output);
// Compute size of a single field. If the field is a message type, this
@ -202,7 +199,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
// its size.
static int FieldByteSize(
const FieldDescriptor* field, // Cannot be NULL
const Message::Reflection* message_reflection);
const Message& message);
// =================================================================
// Methods for reading/writing individual field. The implementations
@ -335,14 +332,14 @@ class LIBPROTOBUF_EXPORT WireFormat {
// opion message_set_wire_format = true.
static bool ParseAndMergeMessageSetItem(
io::CodedInputStream* input,
Message::Reflection* message_reflection);
Message* message);
static bool SerializeMessageSetItemWithCachedSizes(
const FieldDescriptor* field,
const Message::Reflection* message_reflection,
const Message& message,
io::CodedOutputStream* output);
static int MessageSetItemByteSize(
const FieldDescriptor* field,
const Message::Reflection* message_reflection);
const Message& message);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
};

View file

@ -53,8 +53,7 @@ TEST(WireFormatTest, Parse) {
// Parse using WireFormat.
io::ArrayInputStream raw_input(data.data(), data.size());
io::CodedInputStream input(&raw_input);
WireFormat::ParseAndMergePartial(unittest::TestAllTypes::descriptor(),
&input, dest.GetReflection());
WireFormat::ParseAndMergePartial(&input, &dest);
// Check.
TestUtil::ExpectAllFieldsSet(dest);
@ -71,8 +70,7 @@ TEST(WireFormatTest, ParseExtensions) {
// Parse using WireFormat.
io::ArrayInputStream raw_input(data.data(), data.size());
io::CodedInputStream input(&raw_input);
WireFormat::ParseAndMergePartial(unittest::TestAllExtensions::descriptor(),
&input, dest.GetReflection());
WireFormat::ParseAndMergePartial(&input, &dest);
// Check.
TestUtil::ExpectAllExtensionsSet(dest);
@ -82,13 +80,10 @@ TEST(WireFormatTest, ByteSize) {
unittest::TestAllTypes message;
TestUtil::SetAllFields(&message);
EXPECT_EQ(message.ByteSize(),
WireFormat::ByteSize(unittest::TestAllTypes::descriptor(),
message.GetReflection()));
EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message));
message.Clear();
EXPECT_EQ(0, message.ByteSize());
EXPECT_EQ(0, WireFormat::ByteSize(unittest::TestAllTypes::descriptor(),
message.GetReflection()));
EXPECT_EQ(0, WireFormat::ByteSize(message));
}
TEST(WireFormatTest, ByteSizeExtensions) {
@ -96,12 +91,10 @@ TEST(WireFormatTest, ByteSizeExtensions) {
TestUtil::SetAllExtensions(&message);
EXPECT_EQ(message.ByteSize(),
WireFormat::ByteSize(unittest::TestAllExtensions::descriptor(),
message.GetReflection()));
WireFormat::ByteSize(message));
message.Clear();
EXPECT_EQ(0, message.ByteSize());
EXPECT_EQ(0, WireFormat::ByteSize(unittest::TestAllExtensions::descriptor(),
message.GetReflection()));
EXPECT_EQ(0, WireFormat::ByteSize(message));
}
TEST(WireFormatTest, Serialize) {
@ -123,9 +116,7 @@ TEST(WireFormatTest, Serialize) {
{
io::StringOutputStream raw_output(&dynamic_data);
io::CodedOutputStream output(&raw_output);
WireFormat::SerializeWithCachedSizes(
unittest::TestAllTypes::descriptor(),
message.GetReflection(), size, &output);
WireFormat::SerializeWithCachedSizes(message, size, &output);
}
// Should be the same.
@ -153,9 +144,7 @@ TEST(WireFormatTest, SerializeExtensions) {
{
io::StringOutputStream raw_output(&dynamic_data);
io::CodedOutputStream output(&raw_output);
WireFormat::SerializeWithCachedSizes(
unittest::TestAllExtensions::descriptor(),
message.GetReflection(), size, &output);
WireFormat::SerializeWithCachedSizes(message, size, &output);
}
// Should be the same.
@ -183,9 +172,7 @@ TEST(WireFormatTest, SerializeFieldsAndExtensions) {
{
io::StringOutputStream raw_output(&dynamic_data);
io::CodedOutputStream output(&raw_output);
WireFormat::SerializeWithCachedSizes(
unittest::TestFieldOrderings::descriptor(),
message.GetReflection(), size, &output);
WireFormat::SerializeWithCachedSizes(message, size, &output);
}
// Should be the same.
@ -497,9 +484,9 @@ TEST_F(WireFormatInvalidInputTest, InvalidGroup) {
}
TEST_F(WireFormatInvalidInputTest, InvalidUnknownGroup) {
// Use ForeignMessage so that the group made by MakeInvalidGroup will not
// Use TestEmptyMessage so that the group made by MakeInvalidGroup will not
// be a known tag number.
unittest::ForeignMessage message;
unittest::TestEmptyMessage message;
// Control case.
EXPECT_TRUE(message.ParseFromString(MakeInvalidGroup("", 0, true)));
@ -520,6 +507,26 @@ TEST_F(WireFormatInvalidInputTest, InvalidUnknownGroup) {
EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\017", 1, true)));
}
TEST_F(WireFormatInvalidInputTest, InvalidStringInUnknownGroup) {
// Test a bug fix: SkipMessage should fail if the message contains a string
// whose length would extend beyond the message end.
unittest::TestAllTypes message;
message.set_optional_string("foo foo foo foo");
string data;
message.SerializeToString(&data);
// Chop some bytes off the end.
data.resize(data.size() - 4);
// Try to skip it. Note that the bug was only present when parsing to an
// UnknownFieldSet.
io::ArrayInputStream raw_input(data.data(), data.size());
io::CodedInputStream coded_input(&raw_input);
UnknownFieldSet unknown_fields;
EXPECT_FALSE(WireFormat::SkipMessage(&coded_input, &unknown_fields));
}
} // namespace
} // namespace internal
} // namespace protobuf