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:
parent
a0f27fcd96
commit
779f61c6a3
44 changed files with 3369 additions and 2067 deletions
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, ",");
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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.";
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue