Down integrate to GitHub
This commit is contained in:
parent
fbe4ccccc5
commit
1d4e959374
@ -2,6 +2,7 @@ set(libprotobuf_lite_files
|
|||||||
${protobuf_source_dir}/src/google/protobuf/any_lite.cc
|
${protobuf_source_dir}/src/google/protobuf/any_lite.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/arena.cc
|
${protobuf_source_dir}/src/google/protobuf/arena.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/extension_set.cc
|
${protobuf_source_dir}/src/google/protobuf/extension_set.cc
|
||||||
|
${protobuf_source_dir}/src/google/protobuf/generated_enum_util.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc
|
${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc
|
${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/implicit_weak_message.cc
|
${protobuf_source_dir}/src/google/protobuf/implicit_weak_message.cc
|
||||||
@ -9,6 +10,7 @@ set(libprotobuf_lite_files
|
|||||||
${protobuf_source_dir}/src/google/protobuf/io/io_win32.cc
|
${protobuf_source_dir}/src/google/protobuf/io/io_win32.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/strtod.cc
|
${protobuf_source_dir}/src/google/protobuf/io/strtod.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
|
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
|
||||||
|
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
|
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/message_lite.cc
|
${protobuf_source_dir}/src/google/protobuf/message_lite.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/parse_context.cc
|
${protobuf_source_dir}/src/google/protobuf/parse_context.cc
|
||||||
@ -36,6 +38,7 @@ set(libprotobuf_lite_includes
|
|||||||
${protobuf_source_dir}/src/google/protobuf/io/coded_stream.h
|
${protobuf_source_dir}/src/google/protobuf/io/coded_stream.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/strtod.h
|
${protobuf_source_dir}/src/google/protobuf/io/strtod.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.h
|
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.h
|
||||||
|
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
|
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/message_lite.h
|
${protobuf_source_dir}/src/google/protobuf/message_lite.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/repeated_field.h
|
${protobuf_source_dir}/src/google/protobuf/repeated_field.h
|
||||||
|
@ -17,7 +17,6 @@ set(libprotobuf_files
|
|||||||
${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc
|
${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/printer.cc
|
${protobuf_source_dir}/src/google/protobuf/io/printer.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/tokenizer.cc
|
${protobuf_source_dir}/src/google/protobuf/io/tokenizer.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc
|
|
||||||
${protobuf_source_dir}/src/google/protobuf/map_field.cc
|
${protobuf_source_dir}/src/google/protobuf/map_field.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/message.cc
|
${protobuf_source_dir}/src/google/protobuf/message.cc
|
||||||
${protobuf_source_dir}/src/google/protobuf/reflection_ops.cc
|
${protobuf_source_dir}/src/google/protobuf/reflection_ops.cc
|
||||||
@ -72,7 +71,6 @@ set(libprotobuf_includes
|
|||||||
${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.h
|
${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/printer.h
|
${protobuf_source_dir}/src/google/protobuf/io/printer.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/tokenizer.h
|
${protobuf_source_dir}/src/google/protobuf/io/tokenizer.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.h
|
|
||||||
${protobuf_source_dir}/src/google/protobuf/map_field.h
|
${protobuf_source_dir}/src/google/protobuf/map_field.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/message.h
|
${protobuf_source_dir}/src/google/protobuf/message.h
|
||||||
${protobuf_source_dir}/src/google/protobuf/reflection_ops.h
|
${protobuf_source_dir}/src/google/protobuf/reflection_ops.h
|
||||||
|
@ -123,8 +123,7 @@ public class ExtensionRegistryFactoryTest extends TestCase {
|
|||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"Test is using a non-lite extension",
|
"Test is using a non-lite extension",
|
||||||
GeneratedMessage.GeneratedExtension.class.isAssignableFrom(
|
Extension.class.isAssignableFrom(NonNestedExtension.nonNestedExtension.getClass()));
|
||||||
NonNestedExtension.nonNestedExtension.getClass()));
|
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
"Extension is registered in masqueraded full registry",
|
"Extension is registered in masqueraded full registry",
|
||||||
fullRegistry2.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension"));
|
fullRegistry2.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension"));
|
||||||
|
104
js/gulpfile.js
104
js/gulpfile.js
@ -144,7 +144,7 @@ function getClosureBuilderCommand(exportsFile, outputFile) {
|
|||||||
exportsFile + ' > ' + outputFile;
|
exportsFile + ' > ' + outputFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task('dist', gulp.series(['genproto_wellknowntypes'], function (cb) {
|
gulp.task('dist', gulp.series(['genproto_wellknowntypes'], function(cb) {
|
||||||
// TODO(haberman): minify this more aggressively.
|
// TODO(haberman): minify this more aggressively.
|
||||||
// Will require proper externs/exports.
|
// Will require proper externs/exports.
|
||||||
exec(getClosureBuilderCommand('commonjs/export.js', 'google-protobuf.js'),
|
exec(getClosureBuilderCommand('commonjs/export.js', 'google-protobuf.js'),
|
||||||
@ -179,49 +179,75 @@ gulp.task('commonjs_testdeps', function (cb) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('make_commonjs_out', gulp.series(['dist', 'genproto_well_known_types_commonjs', 'genproto_group1_commonjs', 'genproto_group2_commonjs', 'genproto_commonjs_wellknowntypes', 'commonjs_asserts', 'commonjs_testdeps', 'genproto_group3_commonjs_strict'], function (cb) {
|
gulp.task(
|
||||||
// TODO(haberman): minify this more aggressively.
|
'make_commonjs_out',
|
||||||
// Will require proper externs/exports.
|
gulp.series(
|
||||||
var cmd = "mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && ";
|
[
|
||||||
function addTestFile(file) {
|
'dist', 'genproto_well_known_types_commonjs',
|
||||||
cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file +
|
'genproto_group1_commonjs', 'genproto_group2_commonjs',
|
||||||
' > commonjs_out/' + file + '&& ';
|
'genproto_commonjs_wellknowntypes', 'commonjs_asserts',
|
||||||
}
|
'commonjs_testdeps', 'genproto_group3_commonjs_strict'
|
||||||
|
],
|
||||||
|
function(cb) {
|
||||||
|
// TODO(haberman): minify this more aggressively.
|
||||||
|
// Will require proper externs/exports.
|
||||||
|
var cmd =
|
||||||
|
'mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && ';
|
||||||
|
function addTestFile(file) {
|
||||||
|
cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file +
|
||||||
|
' > commonjs_out/' + file + '&& ';
|
||||||
|
}
|
||||||
|
|
||||||
glob.sync('*_test.js').forEach(addTestFile);
|
glob.sync('*_test.js').forEach(addTestFile);
|
||||||
glob.sync('binary/*_test.js').forEach(addTestFile);
|
glob.sync('binary/*_test.js').forEach(addTestFile);
|
||||||
|
|
||||||
exec(cmd +
|
exec(
|
||||||
'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' +
|
cmd + 'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' +
|
||||||
'cp google-protobuf.js commonjs_out/test_node_modules && ' +
|
'cp google-protobuf.js commonjs_out/test_node_modules && ' +
|
||||||
'cp commonjs/strict_test.js commonjs_out/strict_test.js &&' +
|
'cp commonjs/strict_test.js commonjs_out/strict_test.js &&' +
|
||||||
'cp commonjs/import_test.js commonjs_out/import_test.js',
|
'cp commonjs/import_test.js commonjs_out/import_test.js',
|
||||||
function (err, stdout, stderr) {
|
function(err, stdout, stderr) {
|
||||||
console.log(stdout);
|
console.log(stdout);
|
||||||
console.log(stderr);
|
console.log(stderr);
|
||||||
cb(err);
|
cb(err);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task('deps', gulp.series(['genproto_well_known_types_closure', 'genproto_group1_closure', 'genproto_group2_closure'], function (cb) {
|
gulp.task(
|
||||||
exec('./node_modules/google-closure-library/closure/bin/build/depswriter.py binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js',
|
'deps',
|
||||||
function (err, stdout, stderr) {
|
gulp.series(
|
||||||
console.log(stdout);
|
[
|
||||||
console.log(stderr);
|
'genproto_well_known_types_closure', 'genproto_group1_closure',
|
||||||
cb(err);
|
'genproto_group2_closure'
|
||||||
});
|
],
|
||||||
}));
|
function(cb) {
|
||||||
|
exec(
|
||||||
|
'./node_modules/google-closure-library/closure/bin/build/depswriter.py binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js',
|
||||||
|
function(err, stdout, stderr) {
|
||||||
|
console.log(stdout);
|
||||||
|
console.log(stderr);
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
gulp.task('test_closure', gulp.series(['genproto_well_known_types_closure', 'genproto_group1_closure', 'genproto_group2_closure', 'deps'], function (cb) {
|
gulp.task(
|
||||||
exec('JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine',
|
'test_closure',
|
||||||
function (err, stdout, stderr) {
|
gulp.series(
|
||||||
console.log(stdout);
|
[
|
||||||
console.log(stderr);
|
'genproto_well_known_types_closure', 'genproto_group1_closure',
|
||||||
cb(err);
|
'genproto_group2_closure', 'deps'
|
||||||
});
|
],
|
||||||
}));
|
function(cb) {
|
||||||
|
exec(
|
||||||
|
'JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine',
|
||||||
|
function(err, stdout, stderr) {
|
||||||
|
console.log(stdout);
|
||||||
|
console.log(stderr);
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
gulp.task('test_commonjs', gulp.series(['make_commonjs_out'], function (cb) {
|
gulp.task('test_commonjs', gulp.series(['make_commonjs_out'], function(cb) {
|
||||||
exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine',
|
exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine',
|
||||||
function (err, stdout, stderr) {
|
function (err, stdout, stderr) {
|
||||||
console.log(stdout);
|
console.log(stdout);
|
||||||
|
@ -316,6 +316,18 @@ class TextFormatMessageToStringTests(TextFormatBase):
|
|||||||
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(
|
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(
|
||||||
*formatted_fields))
|
*formatted_fields))
|
||||||
|
|
||||||
|
# Test default float_format has 8 valid digits.
|
||||||
|
message.payload.optional_float = 1.2345678912
|
||||||
|
message.payload.optional_double = 1.2345678912
|
||||||
|
formatted_fields = ['optional_float: 1.2345679',
|
||||||
|
'optional_double: 1.2345678912',
|
||||||
|
'repeated_float: -5642', 'repeated_double: 7.89e-5']
|
||||||
|
text_message = text_format.MessageToString(message)
|
||||||
|
self.CompareToGoldenText(
|
||||||
|
self.RemoveRedundantZeros(text_message),
|
||||||
|
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(
|
||||||
|
*formatted_fields))
|
||||||
|
|
||||||
def testMessageToString(self, message_module):
|
def testMessageToString(self, message_module):
|
||||||
message = message_module.ForeignMessage()
|
message = message_module.ForeignMessage()
|
||||||
message.c = 123
|
message.c = 123
|
||||||
|
@ -133,10 +133,10 @@ def MessageToString(message,
|
|||||||
# type: (...) -> str
|
# type: (...) -> str
|
||||||
"""Convert protobuf message to text format.
|
"""Convert protobuf message to text format.
|
||||||
|
|
||||||
Floating point values can be formatted compactly with 15 digits of
|
Double values can be formatted compactly with 15 digits of
|
||||||
precision (which is the most that IEEE 754 "double" can guarantee)
|
precision (which is the most that IEEE 754 "double" can guarantee)
|
||||||
using float_format='.15g'. To ensure that converting to text and back to a
|
using double_format='.15g'. To ensure that converting to text and back to a
|
||||||
proto will result in an identical value, float_format='.17g' should be used.
|
proto will result in an identical value, double_format='.17g' should be used.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: The protocol buffers message.
|
message: The protocol buffers message.
|
||||||
@ -153,11 +153,12 @@ def MessageToString(message,
|
|||||||
determined by the extension number. By default, use the field number
|
determined by the extension number. By default, use the field number
|
||||||
order.
|
order.
|
||||||
float_format: If set, use this to specify float field formatting
|
float_format: If set, use this to specify float field formatting
|
||||||
(per the "Format Specification Mini-Language"); otherwise, str() is used.
|
(per the "Format Specification Mini-Language"); otherwise, 8 valid digits
|
||||||
Also affect double field if double_format is not set.
|
is used (default '.8g'). Also affect double field if double_format is
|
||||||
|
not set but float_format is set.
|
||||||
double_format: If set, use this to specify double field formatting
|
double_format: If set, use this to specify double field formatting
|
||||||
(per the "Format Specification Mini-Language"); otherwise, float_format
|
(per the "Format Specification Mini-Language"); if it is not set but
|
||||||
is used.
|
float_format is set, use float_format. Otherwise, use str()
|
||||||
use_field_number: If True, print field numbers instead of names.
|
use_field_number: If True, print field numbers instead of names.
|
||||||
descriptor_pool: A DescriptorPool used to resolve Any types.
|
descriptor_pool: A DescriptorPool used to resolve Any types.
|
||||||
indent: The initial indent level, in terms of spaces, for pretty print.
|
indent: The initial indent level, in terms of spaces, for pretty print.
|
||||||
@ -322,10 +323,10 @@ class _Printer(object):
|
|||||||
print_unknown_fields=False):
|
print_unknown_fields=False):
|
||||||
"""Initialize the Printer.
|
"""Initialize the Printer.
|
||||||
|
|
||||||
Floating point values can be formatted compactly with 15 digits of
|
Double values can be formatted compactly with 15 digits of precision
|
||||||
precision (which is the most that IEEE 754 "double" can guarantee)
|
(which is the most that IEEE 754 "double" can guarantee) using
|
||||||
using float_format='.15g'. To ensure that converting to text and back to a
|
double_format='.15g'. To ensure that converting to text and back to a proto
|
||||||
proto will result in an identical value, float_format='.17g' should be used.
|
will result in an identical value, double_format='.17g' should be used.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
out: To record the text format result.
|
out: To record the text format result.
|
||||||
@ -340,11 +341,13 @@ class _Printer(object):
|
|||||||
use_index_order: If True, print fields of a proto message using the order
|
use_index_order: If True, print fields of a proto message using the order
|
||||||
defined in source code instead of the field number. By default, use the
|
defined in source code instead of the field number. By default, use the
|
||||||
field number order.
|
field number order.
|
||||||
float_format: If set, use this to specify floating point number formatting
|
float_format: If set, use this to specify float field formatting
|
||||||
(per the "Format Specification Mini-Language"); otherwise, str() is
|
(per the "Format Specification Mini-Language"); otherwise, 8 valid
|
||||||
used. Also affect double field if double_format is not set.
|
digits is used (default '.8g'). Also affect double field if
|
||||||
double_format: If set, use this to specify double field formatting;
|
double_format is not set but float_format is set.
|
||||||
otherwise, float_format is used.
|
double_format: If set, use this to specify double field formatting
|
||||||
|
(per the "Format Specification Mini-Language"); if it is not set but
|
||||||
|
float_format is set, use float_format. Otherwise, str() is used.
|
||||||
use_field_number: If True, print field numbers instead of names.
|
use_field_number: If True, print field numbers instead of names.
|
||||||
descriptor_pool: A DescriptorPool used to resolve Any types.
|
descriptor_pool: A DescriptorPool used to resolve Any types.
|
||||||
message_formatter: A function(message, indent, as_one_line): unicode|None
|
message_formatter: A function(message, indent, as_one_line): unicode|None
|
||||||
@ -589,9 +592,11 @@ class _Printer(object):
|
|||||||
out.write('true')
|
out.write('true')
|
||||||
else:
|
else:
|
||||||
out.write('false')
|
out.write('false')
|
||||||
elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT and
|
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
|
||||||
self.float_format is not None):
|
if self.float_format is not None:
|
||||||
out.write('{1:{0}}'.format(self.float_format, value))
|
out.write('{1:{0}}'.format(self.float_format, value))
|
||||||
|
else:
|
||||||
|
out.write(str(float(format(value, '.8g'))))
|
||||||
elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and
|
elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and
|
||||||
self.double_format is not None):
|
self.double_format is not None):
|
||||||
out.write('{1:{0}}'.format(self.double_format, value))
|
out.write('{1:{0}}'.format(self.double_format, value))
|
||||||
|
@ -202,6 +202,7 @@ libprotobuf_lite_la_SOURCES = \
|
|||||||
google/protobuf/any_lite.cc \
|
google/protobuf/any_lite.cc \
|
||||||
google/protobuf/arena.cc \
|
google/protobuf/arena.cc \
|
||||||
google/protobuf/extension_set.cc \
|
google/protobuf/extension_set.cc \
|
||||||
|
google/protobuf/generated_enum_util.cc \
|
||||||
google/protobuf/generated_message_util.cc \
|
google/protobuf/generated_message_util.cc \
|
||||||
google/protobuf/generated_message_table_driven_lite.h \
|
google/protobuf/generated_message_table_driven_lite.h \
|
||||||
google/protobuf/generated_message_table_driven_lite.cc \
|
google/protobuf/generated_message_table_driven_lite.cc \
|
||||||
@ -214,6 +215,7 @@ libprotobuf_lite_la_SOURCES = \
|
|||||||
google/protobuf/io/coded_stream_inl.h \
|
google/protobuf/io/coded_stream_inl.h \
|
||||||
google/protobuf/io/strtod.cc \
|
google/protobuf/io/strtod.cc \
|
||||||
google/protobuf/io/zero_copy_stream.cc \
|
google/protobuf/io/zero_copy_stream.cc \
|
||||||
|
google/protobuf/io/zero_copy_stream_impl.cc \
|
||||||
google/protobuf/io/zero_copy_stream_impl_lite.cc
|
google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||||
|
|
||||||
libprotobuf_la_LIBADD = $(PTHREAD_LIBS) $(LIBATOMIC_LIBS)
|
libprotobuf_la_LIBADD = $(PTHREAD_LIBS) $(LIBATOMIC_LIBS)
|
||||||
@ -258,7 +260,6 @@ libprotobuf_la_SOURCES = \
|
|||||||
google/protobuf/io/gzip_stream.cc \
|
google/protobuf/io/gzip_stream.cc \
|
||||||
google/protobuf/io/printer.cc \
|
google/protobuf/io/printer.cc \
|
||||||
google/protobuf/io/tokenizer.cc \
|
google/protobuf/io/tokenizer.cc \
|
||||||
google/protobuf/io/zero_copy_stream_impl.cc \
|
|
||||||
google/protobuf/compiler/importer.cc \
|
google/protobuf/compiler/importer.cc \
|
||||||
google/protobuf/compiler/parser.cc \
|
google/protobuf/compiler/parser.cc \
|
||||||
google/protobuf/util/delimited_message_util.cc \
|
google/protobuf/util/delimited_message_util.cc \
|
||||||
|
@ -57,6 +57,17 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
|
|||||||
}
|
}
|
||||||
return max_value != kint32max;
|
return max_value != kint32max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the number of unique numeric enum values. This is less than
|
||||||
|
// descriptor->value_count() when there are aliased values.
|
||||||
|
int CountUniqueValues(const EnumDescriptor* descriptor) {
|
||||||
|
std::set<int> values;
|
||||||
|
for (int i = 0; i < descriptor->value_count(); ++i) {
|
||||||
|
values.insert(descriptor->value(i)->number());
|
||||||
|
}
|
||||||
|
return values.size();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
|
||||||
@ -143,25 +154,42 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
|||||||
format(
|
format(
|
||||||
"$dllexport_decl $const ::$proto_ns$::EnumDescriptor* "
|
"$dllexport_decl $const ::$proto_ns$::EnumDescriptor* "
|
||||||
"$classname$_descriptor();\n");
|
"$classname$_descriptor();\n");
|
||||||
// The _Name and _Parse methods
|
}
|
||||||
// Support a stricter, type-checked enum-to-string method that
|
|
||||||
// statically checks whether the parameter is the exact enum type or is
|
// The _Name and _Parse functions. The lite implementation is table-based, so
|
||||||
// an integral type.
|
// we make sure to keep the tables hidden in the .cc file.
|
||||||
|
if (!HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||||
|
format("const std::string& $classname$_Name($classname$ value);\n");
|
||||||
|
}
|
||||||
|
// The _Name() function accepts the enum type itself but also any integral
|
||||||
|
// type.
|
||||||
|
format(
|
||||||
|
"template<typename T>\n"
|
||||||
|
"inline const std::string& $classname$_Name(T enum_t_value) {\n"
|
||||||
|
" static_assert(::std::is_same<T, $classname$>::value ||\n"
|
||||||
|
" ::std::is_integral<T>::value,\n"
|
||||||
|
" \"Incorrect type passed to function $classname$_Name.\");\n");
|
||||||
|
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||||
format(
|
format(
|
||||||
"template<typename T>\n"
|
|
||||||
"inline const std::string& $classname$_Name(T enum_t_value) {\n"
|
|
||||||
" static_assert(::std::is_same<T, $classname$>::value ||\n"
|
|
||||||
" ::std::is_integral<T>::value,\n"
|
|
||||||
" \"Incorrect type passed to function $classname$_Name.\");\n"
|
|
||||||
" return ::$proto_ns$::internal::NameOfEnum(\n"
|
" return ::$proto_ns$::internal::NameOfEnum(\n"
|
||||||
" $classname$_descriptor(), enum_t_value);\n"
|
" $classname$_descriptor(), enum_t_value);\n");
|
||||||
"}\n");
|
} else {
|
||||||
|
format(
|
||||||
|
" return $classname$_Name(static_cast<$classname$>(enum_t_value));\n");
|
||||||
|
}
|
||||||
|
format("}\n");
|
||||||
|
|
||||||
|
if (HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||||
format(
|
format(
|
||||||
"inline bool $classname$_Parse(\n"
|
"inline bool $classname$_Parse(\n"
|
||||||
" const std::string& name, $classname$* value) {\n"
|
" const std::string& name, $classname$* value) {\n"
|
||||||
" return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
|
" return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
|
||||||
" $classname$_descriptor(), name, value);\n"
|
" $classname$_descriptor(), name, value);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
|
} else {
|
||||||
|
format(
|
||||||
|
"bool $classname$_Parse(\n"
|
||||||
|
" const std::string& name, $classname$* value);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,24 +244,21 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const {
|
|||||||
"$nested_name$_descriptor() {\n"
|
"$nested_name$_descriptor() {\n"
|
||||||
" return $classname$_descriptor();\n"
|
" return $classname$_descriptor();\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
// Support a stricter, type-checked enum-to-string method that
|
|
||||||
// statically checks whether the parameter is the exact enum type or is
|
|
||||||
// an integral type.
|
|
||||||
format(
|
|
||||||
"template<typename T>\n"
|
|
||||||
"static inline const std::string& $nested_name$_Name(T enum_t_value) "
|
|
||||||
"{\n"
|
|
||||||
" static_assert(::std::is_same<T, $resolved_name$>::value ||\n"
|
|
||||||
" ::std::is_integral<T>::value,\n"
|
|
||||||
" \"Incorrect type passed to function $nested_name$_Name.\");\n"
|
|
||||||
" return $classname$_Name(enum_t_value);\n"
|
|
||||||
"}\n");
|
|
||||||
format(
|
|
||||||
"static inline bool $nested_name$_Parse(const std::string& name,\n"
|
|
||||||
" $resolved_name$* value) {\n"
|
|
||||||
" return $classname$_Parse(name, value);\n"
|
|
||||||
"}\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
format(
|
||||||
|
"template<typename T>\n"
|
||||||
|
"static inline const std::string& $nested_name$_Name(T enum_t_value) {\n"
|
||||||
|
" static_assert(::std::is_same<T, $resolved_name$>::value ||\n"
|
||||||
|
" ::std::is_integral<T>::value,\n"
|
||||||
|
" \"Incorrect type passed to function $nested_name$_Name.\");\n"
|
||||||
|
" return $classname$_Name(enum_t_value);\n"
|
||||||
|
"}\n");
|
||||||
|
format(
|
||||||
|
"static inline bool $nested_name$_Parse(const std::string& name,\n"
|
||||||
|
" $resolved_name$* value) {\n"
|
||||||
|
" return $classname$_Parse(name, value);\n"
|
||||||
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
|
void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
|
||||||
@ -274,6 +299,104 @@ void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
|
|||||||
"}\n"
|
"}\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
|
if (!HasDescriptorMethods(descriptor_->file(), options_)) {
|
||||||
|
// In lite mode (where descriptors are unavailable), we generate separate
|
||||||
|
// tables for mapping between enum names and numbers. The _entries table
|
||||||
|
// contains the bulk of the data and is sorted by name, while
|
||||||
|
// _entries_by_number is sorted by number and just contains pointers into
|
||||||
|
// _entries. The two tables allow mapping from name to number and number to
|
||||||
|
// name, both in time logarithmic in the number of enum entries. This could
|
||||||
|
// probably be made faster, but for now the tables are intended to be simple
|
||||||
|
// and compact.
|
||||||
|
//
|
||||||
|
// Enums with allow_alias = true support multiple entries with the same
|
||||||
|
// numerical value. In cases where there are multiple names for the same
|
||||||
|
// number, we treat the first name appearing in the .proto file as the
|
||||||
|
// canonical one.
|
||||||
|
std::map<std::string, int> name_to_number;
|
||||||
|
std::map<int, std::string> number_to_canonical_name;
|
||||||
|
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||||
|
const EnumValueDescriptor* value = descriptor_->value(i);
|
||||||
|
name_to_number.emplace(value->name(), value->number());
|
||||||
|
// The same number may appear with multiple names, so we use emplace() to
|
||||||
|
// let the first name win.
|
||||||
|
number_to_canonical_name.emplace(value->number(), value->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
format(
|
||||||
|
"static ::$proto_ns$::internal::ExplicitlyConstructed<std::string> "
|
||||||
|
"$classname$_strings[$1$] = {};\n\n",
|
||||||
|
CountUniqueValues(descriptor_));
|
||||||
|
|
||||||
|
// We concatenate all the names for a given enum into one big string
|
||||||
|
// literal. If instead we store an array of string literals, the linker
|
||||||
|
// seems to put all enum strings for a given .proto file in the same
|
||||||
|
// section, which hinders its ability to strip out unused strings.
|
||||||
|
format("static const char $classname$_names[] =");
|
||||||
|
for (const auto& p : name_to_number) {
|
||||||
|
format("\n \"$1$\"", p.first);
|
||||||
|
}
|
||||||
|
format(";\n\n");
|
||||||
|
|
||||||
|
format(
|
||||||
|
"static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] "
|
||||||
|
"= {\n");
|
||||||
|
int i = 0;
|
||||||
|
std::map<int, int> number_to_index;
|
||||||
|
int data_index = 0;
|
||||||
|
for (const auto& p : name_to_number) {
|
||||||
|
format(" { {$classname$_names + $1$, $2$}, $3$ },\n", data_index,
|
||||||
|
p.first.size(), p.second);
|
||||||
|
if (number_to_canonical_name[p.second] == p.first) {
|
||||||
|
number_to_index.emplace(p.second, i);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
data_index += p.first.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
format(
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"static const int $classname$_entries_by_number[] = {\n");
|
||||||
|
for (const auto& p : number_to_index) {
|
||||||
|
format(" $1$, // $2$ -> $3$\n", p.second, p.first,
|
||||||
|
number_to_canonical_name[p.first]);
|
||||||
|
}
|
||||||
|
format(
|
||||||
|
"};\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
format(
|
||||||
|
"const std::string& $classname$_Name(\n"
|
||||||
|
" $classname$ value) {\n"
|
||||||
|
" static const bool dummy =\n"
|
||||||
|
" ::$proto_ns$::internal::InitializeEnumStrings(\n"
|
||||||
|
" $classname$_entries,\n"
|
||||||
|
" $classname$_entries_by_number,\n"
|
||||||
|
" $1$, $classname$_strings);\n"
|
||||||
|
" (void) dummy;\n"
|
||||||
|
" int idx = ::$proto_ns$::internal::LookUpEnumName(\n"
|
||||||
|
" $classname$_entries,\n"
|
||||||
|
" $classname$_entries_by_number,\n"
|
||||||
|
" $1$, value);\n"
|
||||||
|
" return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n"
|
||||||
|
" $classname$_strings[idx].get();\n"
|
||||||
|
"}\n",
|
||||||
|
CountUniqueValues(descriptor_));
|
||||||
|
format(
|
||||||
|
"bool $classname$_Parse(\n"
|
||||||
|
" const std::string& name, $classname$* value) {\n"
|
||||||
|
" int int_value;\n"
|
||||||
|
" bool success = ::$proto_ns$::internal::LookUpEnumValue(\n"
|
||||||
|
" $classname$_entries, $1$, name, &int_value);\n"
|
||||||
|
" if (success) {\n"
|
||||||
|
" *value = static_cast<$classname$>(int_value);\n"
|
||||||
|
" }\n"
|
||||||
|
" return success;\n"
|
||||||
|
"}\n",
|
||||||
|
descriptor_->value_count());
|
||||||
|
}
|
||||||
|
|
||||||
if (descriptor_->containing_type() != NULL) {
|
if (descriptor_->containing_type() != NULL) {
|
||||||
std::string parent = ClassName(descriptor_->containing_type(), false);
|
std::string parent = ClassName(descriptor_->containing_type(), false);
|
||||||
// Before C++17, we must define the static constants which were
|
// Before C++17, we must define the static constants which were
|
||||||
|
@ -892,11 +892,17 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
|
|||||||
protodef_name, file_data.size(), sccs_.size(), num_deps,
|
protodef_name, file_data.size(), sccs_.size(), num_deps,
|
||||||
message_generators_.size());
|
message_generators_.size());
|
||||||
|
|
||||||
format(
|
// For descriptor.proto we want to avoid doing any dynamic initialization,
|
||||||
"// Force running AddDescriptors() at dynamic initialization time.\n"
|
// because in some situations that would otherwise pull in a lot of
|
||||||
"static bool $1$ = ("
|
// unnecessary code that can't be stripped by --gc-sections. Descriptor
|
||||||
" ::$proto_ns$::internal::AddDescriptors(&$desc_table$), true);\n",
|
// initialization will still be performed lazily when it's needed.
|
||||||
UniqueName("dynamic_init_dummy", file_, options_));
|
if (file_->name() != "net/proto2/proto/descriptor.proto") {
|
||||||
|
format(
|
||||||
|
"// Force running AddDescriptors() at dynamic initialization time.\n"
|
||||||
|
"static bool $1$ = ("
|
||||||
|
" ::$proto_ns$::internal::AddDescriptors(&$desc_table$), true);\n",
|
||||||
|
UniqueName("dynamic_init_dummy", file_, options_));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
|
void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) {
|
||||||
|
@ -65,15 +65,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
|
|||||||
switch (val->cpp_type()) {
|
switch (val->cpp_type()) {
|
||||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||||
(*variables)["val_cpp"] = FieldMessageTypeName(val, options);
|
(*variables)["val_cpp"] = FieldMessageTypeName(val, options);
|
||||||
(*variables)["wrapper"] = "MapEntryWrapper";
|
|
||||||
break;
|
break;
|
||||||
case FieldDescriptor::CPPTYPE_ENUM:
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
(*variables)["val_cpp"] = ClassName(val->enum_type(), true);
|
(*variables)["val_cpp"] = ClassName(val->enum_type(), true);
|
||||||
(*variables)["wrapper"] = "MapEnumEntryWrapper";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
(*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
|
(*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
|
||||||
(*variables)["wrapper"] = "MapEntryWrapper";
|
|
||||||
}
|
}
|
||||||
(*variables)["key_wire_type"] =
|
(*variables)["key_wire_type"] =
|
||||||
"TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
|
"TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
|
||||||
@ -250,17 +247,16 @@ static void GenerateSerializationLoop(const Formatter& format, bool string_key,
|
|||||||
}
|
}
|
||||||
format.Indent();
|
format.Indent();
|
||||||
|
|
||||||
format(
|
|
||||||
"$map_classname$::$wrapper$ entry(nullptr, $1$->first, $1$->second);\n",
|
|
||||||
ptr);
|
|
||||||
if (to_array) {
|
if (to_array) {
|
||||||
format(
|
format(
|
||||||
"target = ::$proto_ns$::internal::WireFormatLite::InternalWrite"
|
"target = $map_classname$::Funcs::SerializeToArray($number$, "
|
||||||
"$declared_type$NoVirtualToArray($number$, entry, target);\n");
|
"$1$->first, $1$->second, target);\n",
|
||||||
|
ptr);
|
||||||
} else {
|
} else {
|
||||||
format(
|
format(
|
||||||
"::$proto_ns$::internal::WireFormatLite::Write$stream_writer$($number$,"
|
"$map_classname$::Funcs::SerializeToCodedStream($number$, "
|
||||||
" entry, output);\n");
|
"$1$->first, $1$->second, output);\n",
|
||||||
|
ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string_key || string_value) {
|
if (string_key || string_value) {
|
||||||
@ -370,9 +366,8 @@ void MapFieldGenerator::GenerateByteSize(io::Printer* printer) const {
|
|||||||
"for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
"for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
|
||||||
" it = this->$name$().begin();\n"
|
" it = this->$name$().begin();\n"
|
||||||
" it != this->$name$().end(); ++it) {\n"
|
" it != this->$name$().end(); ++it) {\n"
|
||||||
" $map_classname$::$wrapper$ entry(nullptr, it->first, it->second);\n"
|
" total_size += $map_classname$::Funcs::ByteSizeLong(it->first, "
|
||||||
" total_size += ::$proto_ns$::internal::WireFormatLite::\n"
|
"it->second);\n"
|
||||||
" $declared_type$SizeNoVirtual(entry);\n"
|
|
||||||
"}\n");
|
"}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1335,7 +1335,10 @@ DescriptorPool* DescriptorPool::internal_generated_pool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DescriptorPool* DescriptorPool::generated_pool() {
|
const DescriptorPool* DescriptorPool::generated_pool() {
|
||||||
return internal_generated_pool();
|
const DescriptorPool* pool = internal_generated_pool();
|
||||||
|
// Ensure that descriptor.proto has been registered in the generated pool.
|
||||||
|
DescriptorProto::descriptor();
|
||||||
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
95
src/google/protobuf/generated_enum_util.cc
Executable file
95
src/google/protobuf/generated_enum_util.cc
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include <google/protobuf/generated_enum_util.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <google/protobuf/generated_message_util.h>
|
||||||
|
|
||||||
|
namespace google {
|
||||||
|
namespace protobuf {
|
||||||
|
namespace internal {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool EnumCompareByName(const EnumEntry& a, const EnumEntry& b) {
|
||||||
|
return StringPiece(a.name) < StringPiece(b.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the numeric value of the EnumEntry at the given index, but returns a
|
||||||
|
// special value for the index -1. This gives a way to use std::lower_bound on a
|
||||||
|
// sorted array of indices while searching for value that we associate with -1.
|
||||||
|
int GetValue(const EnumEntry* enums, int i, int target) {
|
||||||
|
if (i == -1) {
|
||||||
|
return target;
|
||||||
|
} else {
|
||||||
|
return enums[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool LookUpEnumValue(const EnumEntry* enums, size_t size,
|
||||||
|
StringPiece name, int* value) {
|
||||||
|
EnumEntry target{name, 0};
|
||||||
|
auto it = std::lower_bound(enums, enums + size, target, EnumCompareByName);
|
||||||
|
if (it != enums + size && it->name == name) {
|
||||||
|
*value = it->value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LookUpEnumName(const EnumEntry* enums, const int* sorted_indices,
|
||||||
|
size_t size, int value) {
|
||||||
|
auto comparator = [enums, value](int a, int b) {
|
||||||
|
return GetValue(enums, a, value) < GetValue(enums, b, value);
|
||||||
|
};
|
||||||
|
auto it =
|
||||||
|
std::lower_bound(sorted_indices, sorted_indices + size, -1, comparator);
|
||||||
|
if (it != sorted_indices + size && enums[*it].value == value) {
|
||||||
|
return it - sorted_indices;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InitializeEnumStrings(
|
||||||
|
const EnumEntry* enums, const int* sorted_indices, size_t size,
|
||||||
|
internal::ExplicitlyConstructed<std::string>* enum_strings) {
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
enum_strings[i].Construct(enums[sorted_indices[i]].name);
|
||||||
|
internal::OnShutdownDestroyString(enum_strings[i].get_mutable());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -33,6 +33,11 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <google/protobuf/message_lite.h>
|
||||||
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/port_def.inc>
|
||||||
|
|
||||||
#ifdef SWIG
|
#ifdef SWIG
|
||||||
#error "You cannot SWIG proto headers"
|
#error "You cannot SWIG proto headers"
|
||||||
#endif
|
#endif
|
||||||
@ -45,7 +50,34 @@ namespace protobuf {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_proto_enum : ::std::false_type {};
|
struct is_proto_enum : ::std::false_type {};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// The table entry format for storing enum name-to-value mapping used with lite
|
||||||
|
// protos. This struct and the following related functions should only be used
|
||||||
|
// by protobuf generated code.
|
||||||
|
struct EnumEntry {
|
||||||
|
StringPiece name;
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Looks up a numeric enum value given the string name.
|
||||||
|
PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size,
|
||||||
|
StringPiece name, int* value);
|
||||||
|
|
||||||
|
// Looks up an enum name given the numeric value.
|
||||||
|
PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums,
|
||||||
|
const int* sorted_indices, size_t size,
|
||||||
|
int value);
|
||||||
|
|
||||||
|
// Initializes the list of enum names in std::string form.
|
||||||
|
PROTOBUF_EXPORT bool InitializeEnumStrings(
|
||||||
|
const EnumEntry* enums, const int* sorted_indices, size_t size,
|
||||||
|
internal::ExplicitlyConstructed<std::string>* enum_strings);
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
||||||
} // namespace google
|
} // namespace google
|
||||||
|
|
||||||
|
#include <google/protobuf/port_undef.inc>
|
||||||
|
|
||||||
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||||
|
@ -203,8 +203,8 @@ GeneratedMessageReflection::GeneratedMessageReflection(
|
|||||||
const DescriptorPool* pool, MessageFactory* factory)
|
const DescriptorPool* pool, MessageFactory* factory)
|
||||||
: descriptor_(descriptor),
|
: descriptor_(descriptor),
|
||||||
schema_(schema),
|
schema_(schema),
|
||||||
descriptor_pool_((pool == NULL) ? DescriptorPool::generated_pool()
|
descriptor_pool_(
|
||||||
: pool),
|
(pool == nullptr) ? DescriptorPool::internal_generated_pool() : pool),
|
||||||
message_factory_(factory),
|
message_factory_(factory),
|
||||||
last_non_weak_field_index_(-1) {
|
last_non_weak_field_index_(-1) {
|
||||||
last_non_weak_field_index_ = descriptor_->field_count() - 1;
|
last_non_weak_field_index_ = descriptor_->field_count() - 1;
|
||||||
@ -2250,7 +2250,7 @@ class AssignDescriptorsHelper {
|
|||||||
descriptor,
|
descriptor,
|
||||||
MigrationToReflectionSchema(default_instance_data_, offsets_,
|
MigrationToReflectionSchema(default_instance_data_, offsets_,
|
||||||
*schemas_),
|
*schemas_),
|
||||||
DescriptorPool::generated_pool(), factory_);
|
DescriptorPool::internal_generated_pool(), factory_);
|
||||||
for (int i = 0; i < descriptor->enum_type_count(); i++) {
|
for (int i = 0; i < descriptor->enum_type_count(); i++) {
|
||||||
AssignEnumDescriptor(descriptor->enum_type(i));
|
AssignEnumDescriptor(descriptor->enum_type(i));
|
||||||
}
|
}
|
||||||
@ -2317,7 +2317,8 @@ void AssignDescriptorsImpl(const DescriptorTable* table) {
|
|||||||
}
|
}
|
||||||
// Fill the arrays with pointers to descriptors and reflection classes.
|
// Fill the arrays with pointers to descriptors and reflection classes.
|
||||||
const FileDescriptor* file =
|
const FileDescriptor* file =
|
||||||
DescriptorPool::generated_pool()->FindFileByName(table->filename);
|
DescriptorPool::internal_generated_pool()->FindFileByName(
|
||||||
|
table->filename);
|
||||||
GOOGLE_CHECK(file != NULL);
|
GOOGLE_CHECK(file != NULL);
|
||||||
|
|
||||||
MessageFactory* factory = MessageFactory::generated_factory();
|
MessageFactory* factory = MessageFactory::generated_factory();
|
||||||
|
@ -1097,5 +1097,99 @@ TEST(Lite, DebugString) {
|
|||||||
EXPECT_NE(message1.DebugString(), message2.DebugString());
|
EXPECT_NE(message1.DebugString(), message2.DebugString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Lite, EnumValueToName) {
|
||||||
|
EXPECT_EQ("FOREIGN_LITE_FOO", protobuf_unittest::ForeignEnumLite_Name(
|
||||||
|
protobuf_unittest::FOREIGN_LITE_FOO));
|
||||||
|
EXPECT_EQ("FOREIGN_LITE_BAR", protobuf_unittest::ForeignEnumLite_Name(
|
||||||
|
protobuf_unittest::FOREIGN_LITE_BAR));
|
||||||
|
EXPECT_EQ("FOREIGN_LITE_BAZ", protobuf_unittest::ForeignEnumLite_Name(
|
||||||
|
protobuf_unittest::FOREIGN_LITE_BAZ));
|
||||||
|
EXPECT_EQ("", protobuf_unittest::ForeignEnumLite_Name(0));
|
||||||
|
EXPECT_EQ("", protobuf_unittest::ForeignEnumLite_Name(999));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Lite, NestedEnumValueToName) {
|
||||||
|
EXPECT_EQ("FOO", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(
|
||||||
|
protobuf_unittest::TestAllTypesLite::FOO));
|
||||||
|
EXPECT_EQ("BAR", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(
|
||||||
|
protobuf_unittest::TestAllTypesLite::BAR));
|
||||||
|
EXPECT_EQ("BAZ", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(
|
||||||
|
protobuf_unittest::TestAllTypesLite::BAZ));
|
||||||
|
EXPECT_EQ("", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(0));
|
||||||
|
EXPECT_EQ("", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(999));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Lite, EnumNameToValue) {
|
||||||
|
protobuf_unittest::ForeignEnumLite value;
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_FOO", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::FOREIGN_LITE_FOO, value);
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_BAR", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::FOREIGN_LITE_BAR, value);
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_BAZ", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::FOREIGN_LITE_BAZ, value);
|
||||||
|
|
||||||
|
// Non-existent values
|
||||||
|
EXPECT_FALSE(protobuf_unittest::ForeignEnumLite_Parse("E", &value));
|
||||||
|
EXPECT_FALSE(
|
||||||
|
protobuf_unittest::ForeignEnumLite_Parse("FOREIGN_LITE_C", &value));
|
||||||
|
EXPECT_FALSE(protobuf_unittest::ForeignEnumLite_Parse("G", &value));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Lite, NestedEnumNameToValue) {
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum value;
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("FOO", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::TestAllTypesLite::FOO, value);
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("BAR", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::TestAllTypesLite::BAR, value);
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("BAZ", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::TestAllTypesLite::BAZ, value);
|
||||||
|
|
||||||
|
// Non-existent values
|
||||||
|
EXPECT_FALSE(
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("A", &value));
|
||||||
|
EXPECT_FALSE(
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("C", &value));
|
||||||
|
EXPECT_FALSE(
|
||||||
|
protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("G", &value));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Lite, AliasedEnum) {
|
||||||
|
// Enums with allow_alias = true can have multiple entries with the same
|
||||||
|
// value.
|
||||||
|
EXPECT_EQ("FOO1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(
|
||||||
|
protobuf_unittest::DupEnum::FOO1));
|
||||||
|
EXPECT_EQ("FOO1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(
|
||||||
|
protobuf_unittest::DupEnum::FOO2));
|
||||||
|
EXPECT_EQ("BAR1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(
|
||||||
|
protobuf_unittest::DupEnum::BAR1));
|
||||||
|
EXPECT_EQ("BAR1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(
|
||||||
|
protobuf_unittest::DupEnum::BAR2));
|
||||||
|
EXPECT_EQ("BAZ", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(
|
||||||
|
protobuf_unittest::DupEnum::BAZ));
|
||||||
|
EXPECT_EQ("", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(999));
|
||||||
|
|
||||||
|
protobuf_unittest::DupEnum::TestEnumWithDupValueLite value;
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Parse("FOO1", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::DupEnum::FOO1, value);
|
||||||
|
|
||||||
|
value = static_cast<protobuf_unittest::DupEnum::TestEnumWithDupValueLite>(0);
|
||||||
|
ASSERT_TRUE(
|
||||||
|
protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Parse("FOO2", &value));
|
||||||
|
EXPECT_EQ(protobuf_unittest::DupEnum::FOO2, value);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace protobuf
|
} // namespace protobuf
|
||||||
} // namespace google
|
} // namespace google
|
||||||
|
@ -937,7 +937,8 @@ class Map {
|
|||||||
// Return a randomish value.
|
// Return a randomish value.
|
||||||
size_type Seed() const {
|
size_type Seed() const {
|
||||||
size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this));
|
size_type s = static_cast<size_type>(reinterpret_cast<uintptr_t>(this));
|
||||||
#if defined(__x86_64__) && defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_NO_RDTSC)
|
#if defined(__x86_64__) && defined(__GNUC__) && \
|
||||||
|
!defined(GOOGLE_PROTOBUF_NO_RDTSC)
|
||||||
uint32 hi, lo;
|
uint32 hi, lo;
|
||||||
asm("rdtsc" : "=a"(lo), "=d"(hi));
|
asm("rdtsc" : "=a"(lo), "=d"(hi));
|
||||||
s += ((static_cast<uint64>(hi) << 32) | lo);
|
s += ((static_cast<uint64>(hi) << 32) | lo);
|
||||||
|
@ -101,6 +101,51 @@ struct MoveHelper<false, false, true, T> { // strings and similar
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Functions for operating on a map entry. Does not contain any representation
|
||||||
|
// (this class is not intended to be instantiated).
|
||||||
|
template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
|
||||||
|
WireFormatLite::FieldType kValueFieldType>
|
||||||
|
struct MapEntryFuncs {
|
||||||
|
typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
|
||||||
|
typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
|
||||||
|
static const int kKeyFieldNumber = 1;
|
||||||
|
static const int kValueFieldNumber = 2;
|
||||||
|
|
||||||
|
static void SerializeToCodedStream(int field_number, const Key& key,
|
||||||
|
const Value& value,
|
||||||
|
io::CodedOutputStream* output) {
|
||||||
|
WireFormatLite::WriteTag(field_number,
|
||||||
|
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
|
||||||
|
output->WriteVarint32(GetCachedSize(key, value));
|
||||||
|
KeyTypeHandler::Write(kKeyFieldNumber, key, output);
|
||||||
|
ValueTypeHandler::Write(kValueFieldNumber, value, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ::google::protobuf::uint8* SerializeToArray(int field_number, const Key& key,
|
||||||
|
const Value& value, ::google::protobuf::uint8* output) {
|
||||||
|
output = WireFormatLite::WriteTagToArray(
|
||||||
|
field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
|
||||||
|
output = io::CodedOutputStream::WriteVarint32ToArray(
|
||||||
|
static_cast<uint32>(GetCachedSize(key, value)), output);
|
||||||
|
output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key, output);
|
||||||
|
output = ValueTypeHandler::WriteToArray(kValueFieldNumber, value, output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ByteSizeLong(const Key& key, const Value& value) {
|
||||||
|
// Tags for key and value will both be one byte (field numbers 1 and 2).
|
||||||
|
size_t inner_length =
|
||||||
|
2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value);
|
||||||
|
return inner_length + io::CodedOutputStream::VarintSize32(inner_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetCachedSize(const Key& key, const Value& value) {
|
||||||
|
// Tags for key and value will both be one byte (field numbers 1 and 2).
|
||||||
|
return 2 + KeyTypeHandler::GetCachedSize(key) +
|
||||||
|
ValueTypeHandler::GetCachedSize(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// MapEntryImpl is used to implement parsing and serialization of map entries.
|
// MapEntryImpl is used to implement parsing and serialization of map entries.
|
||||||
// It uses Curious Recursive Template Pattern (CRTP) to provide the type of
|
// It uses Curious Recursive Template Pattern (CRTP) to provide the type of
|
||||||
// the eventual code to the template code.
|
// the eventual code to the template code.
|
||||||
@ -108,6 +153,9 @@ template <typename Derived, typename Base, typename Key, typename Value,
|
|||||||
WireFormatLite::FieldType kKeyFieldType,
|
WireFormatLite::FieldType kKeyFieldType,
|
||||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||||
class MapEntryImpl : public Base {
|
class MapEntryImpl : public Base {
|
||||||
|
public:
|
||||||
|
typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Provide utilities to parse/serialize key/value. Provide utilities to
|
// Provide utilities to parse/serialize key/value. Provide utilities to
|
||||||
// manipulate internal stored type.
|
// manipulate internal stored type.
|
||||||
@ -350,20 +398,6 @@ class MapEntryImpl : public Base {
|
|||||||
|
|
||||||
Arena* GetArena() const override { return GetArenaNoVirtual(); }
|
Arena* GetArena() const override { return GetArenaNoVirtual(); }
|
||||||
|
|
||||||
// Create a MapEntryImpl for given key and value from Map in
|
|
||||||
// serialization. This function is only called when value is enum. Enum is
|
|
||||||
// treated differently because its type in MapEntry is int and its type in
|
|
||||||
// Map is enum. We cannot create a reference to int from an enum.
|
|
||||||
static Derived* EnumWrap(const Key& key, const Value value, Arena* arena) {
|
|
||||||
return Arena::CreateMessage<MapEnumEntryWrapper>(arena, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Like above, but for all the other types. This avoids value copy to create
|
|
||||||
// MapEntryImpl from Map in serialization.
|
|
||||||
static Derived* Wrap(const Key& key, const Value& value, Arena* arena) {
|
|
||||||
return Arena::CreateMessage<MapEntryWrapper>(arena, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parsing using MergePartialFromCodedStream, above, is not as
|
// Parsing using MergePartialFromCodedStream, above, is not as
|
||||||
// efficient as it could be. This helper class provides a speedier way.
|
// efficient as it could be. This helper class provides a speedier way.
|
||||||
template <typename MapField, typename Map>
|
template <typename MapField, typename Map>
|
||||||
@ -535,71 +569,6 @@ class MapEntryImpl : public Base {
|
|||||||
void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
|
void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Serializing a generated message containing map field involves serializing
|
|
||||||
// key-value pairs from Map. The wire format of each key-value pair
|
|
||||||
// after serialization should be the same as that of a MapEntry message
|
|
||||||
// containing the same key and value inside it. However, Map doesn't
|
|
||||||
// store key and value as MapEntry message, which disables us to use existing
|
|
||||||
// code to serialize message. In order to use existing code to serialize
|
|
||||||
// message, we need to construct a MapEntry from key-value pair. But it
|
|
||||||
// involves copy of key and value to construct a MapEntry. In order to avoid
|
|
||||||
// this copy in constructing a MapEntry, we need the following class which
|
|
||||||
// only takes references of given key and value.
|
|
||||||
class MapEntryWrapper : public Derived {
|
|
||||||
typedef Derived BaseClass;
|
|
||||||
typedef typename BaseClass::KeyMapEntryAccessorType KeyMapEntryAccessorType;
|
|
||||||
typedef
|
|
||||||
typename BaseClass::ValueMapEntryAccessorType ValueMapEntryAccessorType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MapEntryWrapper(Arena* arena, const Key& key, const Value& value)
|
|
||||||
: Derived(arena), key_(key), value_(value) {
|
|
||||||
BaseClass::set_has_key();
|
|
||||||
BaseClass::set_has_value();
|
|
||||||
}
|
|
||||||
inline const KeyMapEntryAccessorType& key() const override { return key_; }
|
|
||||||
inline const ValueMapEntryAccessorType& value() const override {
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const Key& key_;
|
|
||||||
const Value& value_;
|
|
||||||
|
|
||||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
|
||||||
typedef void InternalArenaConstructable_;
|
|
||||||
typedef void DestructorSkippable_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Like above, but for enum value only, which stores value instead of
|
|
||||||
// reference of value field inside. This is needed because the type of value
|
|
||||||
// field in constructor is an enum, while we need to store it as an int. If we
|
|
||||||
// initialize a reference to int with a reference to enum, compiler will
|
|
||||||
// generate a temporary int from enum and initialize the reference to int with
|
|
||||||
// the temporary.
|
|
||||||
class MapEnumEntryWrapper : public Derived {
|
|
||||||
typedef Derived BaseClass;
|
|
||||||
typedef typename BaseClass::KeyMapEntryAccessorType KeyMapEntryAccessorType;
|
|
||||||
typedef
|
|
||||||
typename BaseClass::ValueMapEntryAccessorType ValueMapEntryAccessorType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MapEnumEntryWrapper(Arena* arena, const Key& key, const Value& value)
|
|
||||||
: Derived(arena), key_(key), value_(value) {
|
|
||||||
BaseClass::set_has_key();
|
|
||||||
BaseClass::set_has_value();
|
|
||||||
}
|
|
||||||
inline const KeyMapEntryAccessorType& key() const { return key_; }
|
|
||||||
inline const ValueMapEntryAccessorType& value() const { return value_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const KeyMapEntryAccessorType& key_;
|
|
||||||
const ValueMapEntryAccessorType value_;
|
|
||||||
|
|
||||||
friend class ::PROTOBUF_NAMESPACE_ID::Arena;
|
|
||||||
typedef void DestructorSkippable_;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Arena* GetArenaNoVirtual() const { return arena_; }
|
inline Arena* GetArenaNoVirtual() const { return arena_; }
|
||||||
|
|
||||||
public: // Needed for constructing tables
|
public: // Needed for constructing tables
|
||||||
|
@ -225,9 +225,6 @@ class MapField : public TypeDefinedMapFieldBase<Key, T> {
|
|||||||
|
|
||||||
// Define message type for internal repeated field.
|
// Define message type for internal repeated field.
|
||||||
typedef Derived EntryType;
|
typedef Derived EntryType;
|
||||||
typedef MapEntryLite<Derived, Key, T, kKeyFieldType, kValueFieldType,
|
|
||||||
default_enum_value>
|
|
||||||
EntryLiteType;
|
|
||||||
|
|
||||||
// Define abbreviation for parent MapFieldLite
|
// Define abbreviation for parent MapFieldLite
|
||||||
typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType,
|
typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType,
|
||||||
|
@ -143,26 +143,6 @@ bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Message::ParseFromFileDescriptor(int file_descriptor) {
|
|
||||||
io::FileInputStream input(file_descriptor);
|
|
||||||
return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Message::ParsePartialFromFileDescriptor(int file_descriptor) {
|
|
||||||
io::FileInputStream input(file_descriptor);
|
|
||||||
return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Message::ParseFromIstream(std::istream* input) {
|
|
||||||
io::IstreamInputStream zero_copy_input(input);
|
|
||||||
return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Message::ParsePartialFromIstream(std::istream* input) {
|
|
||||||
io::IstreamInputStream zero_copy_input(input);
|
|
||||||
return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
|
#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@ -547,7 +527,6 @@ const char* Message::_InternalParse(const char* ptr,
|
|||||||
}
|
}
|
||||||
#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
|
#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
|
||||||
|
|
||||||
|
|
||||||
void Message::SerializeWithCachedSizes(io::CodedOutputStream* output) const {
|
void Message::SerializeWithCachedSizes(io::CodedOutputStream* output) const {
|
||||||
const internal::SerializationTable* table =
|
const internal::SerializationTable* table =
|
||||||
static_cast<const internal::SerializationTable*>(InternalGetTable());
|
static_cast<const internal::SerializationTable*>(InternalGetTable());
|
||||||
@ -574,30 +553,6 @@ size_t Message::SpaceUsedLong() const {
|
|||||||
return GetReflection()->SpaceUsedLong(*this);
|
return GetReflection()->SpaceUsedLong(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Message::SerializeToFileDescriptor(int file_descriptor) const {
|
|
||||||
io::FileOutputStream output(file_descriptor);
|
|
||||||
return SerializeToZeroCopyStream(&output) && output.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Message::SerializePartialToFileDescriptor(int file_descriptor) const {
|
|
||||||
io::FileOutputStream output(file_descriptor);
|
|
||||||
return SerializePartialToZeroCopyStream(&output) && output.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Message::SerializeToOstream(std::ostream* output) const {
|
|
||||||
{
|
|
||||||
io::OstreamOutputStream zero_copy_output(output);
|
|
||||||
if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
|
|
||||||
}
|
|
||||||
return output->good();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Message::SerializePartialToOstream(std::ostream* output) const {
|
|
||||||
io::OstreamOutputStream zero_copy_output(output);
|
|
||||||
return SerializePartialToZeroCopyStream(&zero_copy_output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Reflection and associated Template Specializations
|
// Reflection and associated Template Specializations
|
||||||
|
|
||||||
|
@ -285,35 +285,6 @@ class PROTOBUF_EXPORT Message : public MessageLite {
|
|||||||
// Convenience function useful in GDB. Prints DebugString() to stdout.
|
// Convenience function useful in GDB. Prints DebugString() to stdout.
|
||||||
void PrintDebugString() const;
|
void PrintDebugString() const;
|
||||||
|
|
||||||
// Heavy I/O -------------------------------------------------------
|
|
||||||
// Additional parsing and serialization methods not implemented by
|
|
||||||
// MessageLite because they are not supported by the lite library.
|
|
||||||
|
|
||||||
// Parse a protocol buffer from a file descriptor. If successful, the entire
|
|
||||||
// input will be consumed.
|
|
||||||
bool ParseFromFileDescriptor(int file_descriptor);
|
|
||||||
// Like ParseFromFileDescriptor(), but accepts messages that are missing
|
|
||||||
// required fields.
|
|
||||||
bool ParsePartialFromFileDescriptor(int file_descriptor);
|
|
||||||
// Parse a protocol buffer from a C++ istream. If successful, the entire
|
|
||||||
// input will be consumed.
|
|
||||||
bool ParseFromIstream(std::istream* input);
|
|
||||||
// Like ParseFromIstream(), but accepts messages that are missing
|
|
||||||
// required fields.
|
|
||||||
bool ParsePartialFromIstream(std::istream* input);
|
|
||||||
|
|
||||||
// Serialize the message and write it to the given file descriptor. All
|
|
||||||
// required fields must be set.
|
|
||||||
bool SerializeToFileDescriptor(int file_descriptor) const;
|
|
||||||
// Like SerializeToFileDescriptor(), but allows missing required fields.
|
|
||||||
bool SerializePartialToFileDescriptor(int file_descriptor) const;
|
|
||||||
// Serialize the message and write it to the given C++ ostream. All
|
|
||||||
// required fields must be set.
|
|
||||||
bool SerializeToOstream(std::ostream* output) const;
|
|
||||||
// Like SerializeToOstream(), but allows missing required fields.
|
|
||||||
bool SerializePartialToOstream(std::ostream* output) const;
|
|
||||||
|
|
||||||
|
|
||||||
// Reflection-based methods ----------------------------------------
|
// Reflection-based methods ----------------------------------------
|
||||||
// These methods are pure-virtual in MessageLite, but Message provides
|
// These methods are pure-virtual in MessageLite, but Message provides
|
||||||
// reflection-based default implementations.
|
// reflection-based default implementations.
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
// Based on original Protocol Buffers design by
|
// Based on original Protocol Buffers design by
|
||||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#include <google/protobuf/message_lite.h>
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -43,11 +45,11 @@
|
|||||||
#include <google/protobuf/parse_context.h>
|
#include <google/protobuf/parse_context.h>
|
||||||
#include <google/protobuf/io/coded_stream.h>
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream.h>
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||||
#include <google/protobuf/arena.h>
|
#include <google/protobuf/arena.h>
|
||||||
#include <google/protobuf/generated_message_table_driven.h>
|
#include <google/protobuf/generated_message_table_driven.h>
|
||||||
#include <google/protobuf/generated_message_util.h>
|
#include <google/protobuf/generated_message_util.h>
|
||||||
#include <google/protobuf/message_lite.h>
|
|
||||||
#include <google/protobuf/repeated_field.h>
|
#include <google/protobuf/repeated_field.h>
|
||||||
|
|
||||||
#include <google/protobuf/stubs/strutil.h>
|
#include <google/protobuf/stubs/strutil.h>
|
||||||
@ -276,6 +278,26 @@ bool MessageLite::ParsePartialFromZeroCopyStream(
|
|||||||
return ParseFrom<kParsePartial>(input);
|
return ParseFrom<kParsePartial>(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MessageLite::ParseFromFileDescriptor(int file_descriptor) {
|
||||||
|
io::FileInputStream input(file_descriptor);
|
||||||
|
return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageLite::ParsePartialFromFileDescriptor(int file_descriptor) {
|
||||||
|
io::FileInputStream input(file_descriptor);
|
||||||
|
return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageLite::ParseFromIstream(std::istream* input) {
|
||||||
|
io::IstreamInputStream zero_copy_input(input);
|
||||||
|
return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageLite::ParsePartialFromIstream(std::istream* input) {
|
||||||
|
io::IstreamInputStream zero_copy_input(input);
|
||||||
|
return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
|
||||||
|
}
|
||||||
|
|
||||||
bool MessageLite::MergePartialFromBoundedZeroCopyStream(
|
bool MessageLite::MergePartialFromBoundedZeroCopyStream(
|
||||||
io::ZeroCopyInputStream* input, int size) {
|
io::ZeroCopyInputStream* input, int size) {
|
||||||
return ParseFrom<kMergePartial>(internal::BoundedZCIS{input, size});
|
return ParseFrom<kMergePartial>(internal::BoundedZCIS{input, size});
|
||||||
@ -394,6 +416,29 @@ bool MessageLite::SerializePartialToZeroCopyStream(
|
|||||||
return SerializePartialToCodedStream(&encoder);
|
return SerializePartialToCodedStream(&encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MessageLite::SerializeToFileDescriptor(int file_descriptor) const {
|
||||||
|
io::FileOutputStream output(file_descriptor);
|
||||||
|
return SerializeToZeroCopyStream(&output) && output.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageLite::SerializePartialToFileDescriptor(int file_descriptor) const {
|
||||||
|
io::FileOutputStream output(file_descriptor);
|
||||||
|
return SerializePartialToZeroCopyStream(&output) && output.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageLite::SerializeToOstream(std::ostream* output) const {
|
||||||
|
{
|
||||||
|
io::OstreamOutputStream zero_copy_output(output);
|
||||||
|
if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
|
||||||
|
}
|
||||||
|
return output->good();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageLite::SerializePartialToOstream(std::ostream* output) const {
|
||||||
|
io::OstreamOutputStream zero_copy_output(output);
|
||||||
|
return SerializePartialToZeroCopyStream(&zero_copy_output);
|
||||||
|
}
|
||||||
|
|
||||||
bool MessageLite::AppendToString(std::string* output) const {
|
bool MessageLite::AppendToString(std::string* output) const {
|
||||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||||
return AppendPartialToString(output);
|
return AppendPartialToString(output);
|
||||||
@ -474,6 +519,7 @@ void MessageLite::SerializeWithCachedSizes(
|
|||||||
output);
|
output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The table driven code optimizes the case that the CodedOutputStream buffer
|
// The table driven code optimizes the case that the CodedOutputStream buffer
|
||||||
// is large enough to serialize into it directly.
|
// is large enough to serialize into it directly.
|
||||||
// If the proto is optimized for speed, this method will be overridden by
|
// If the proto is optimized for speed, this method will be overridden by
|
||||||
|
@ -114,8 +114,8 @@ inline int ToIntSize(size_t size) {
|
|||||||
//
|
//
|
||||||
// Pay special attention to the initialization state of the object.
|
// Pay special attention to the initialization state of the object.
|
||||||
// 1. The object is "uninitialized" to begin with.
|
// 1. The object is "uninitialized" to begin with.
|
||||||
// 2. Call DefaultConstruct() only if the object is uninitialized.
|
// 2. Call Construct() or DefaultConstruct() only if the object is
|
||||||
// After the call, the object becomes "initialized".
|
// uninitialized. After the call, the object becomes "initialized".
|
||||||
// 3. Call get() and get_mutable() only if the object is initialized.
|
// 3. Call get() and get_mutable() only if the object is initialized.
|
||||||
// 4. Call Destruct() only if the object is initialized.
|
// 4. Call Destruct() only if the object is initialized.
|
||||||
// After the call, the object becomes uninitialized.
|
// After the call, the object becomes uninitialized.
|
||||||
@ -124,6 +124,11 @@ class ExplicitlyConstructed {
|
|||||||
public:
|
public:
|
||||||
void DefaultConstruct() { new (&union_) T(); }
|
void DefaultConstruct() { new (&union_) T(); }
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void Construct(Args&&... args) {
|
||||||
|
new (&union_) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
void Destruct() { get_mutable()->~T(); }
|
void Destruct() { get_mutable()->~T(); }
|
||||||
|
|
||||||
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
|
constexpr const T& get() const { return reinterpret_cast<const T&>(union_); }
|
||||||
@ -262,6 +267,18 @@ class PROTOBUF_EXPORT MessageLite {
|
|||||||
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
||||||
// required fields.
|
// required fields.
|
||||||
bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||||
|
// Parse a protocol buffer from a file descriptor. If successful, the entire
|
||||||
|
// input will be consumed.
|
||||||
|
bool ParseFromFileDescriptor(int file_descriptor);
|
||||||
|
// Like ParseFromFileDescriptor(), but accepts messages that are missing
|
||||||
|
// required fields.
|
||||||
|
bool ParsePartialFromFileDescriptor(int file_descriptor);
|
||||||
|
// Parse a protocol buffer from a C++ istream. If successful, the entire
|
||||||
|
// input will be consumed.
|
||||||
|
bool ParseFromIstream(std::istream* input);
|
||||||
|
// Like ParseFromIstream(), but accepts messages that are missing
|
||||||
|
// required fields.
|
||||||
|
bool ParsePartialFromIstream(std::istream* input);
|
||||||
// Read a protocol buffer from the given zero-copy input stream, expecting
|
// Read a protocol buffer from the given zero-copy input stream, expecting
|
||||||
// the message to be exactly "size" bytes long. If successful, exactly
|
// the message to be exactly "size" bytes long. If successful, exactly
|
||||||
// this many bytes will have been consumed from the input.
|
// this many bytes will have been consumed from the input.
|
||||||
@ -355,12 +372,24 @@ class PROTOBUF_EXPORT MessageLite {
|
|||||||
// Like SerializeAsString(), but allows missing required fields.
|
// Like SerializeAsString(), but allows missing required fields.
|
||||||
std::string SerializePartialAsString() const;
|
std::string SerializePartialAsString() const;
|
||||||
|
|
||||||
|
// Serialize the message and write it to the given file descriptor. All
|
||||||
|
// required fields must be set.
|
||||||
|
bool SerializeToFileDescriptor(int file_descriptor) const;
|
||||||
|
// Like SerializeToFileDescriptor(), but allows missing required fields.
|
||||||
|
bool SerializePartialToFileDescriptor(int file_descriptor) const;
|
||||||
|
// Serialize the message and write it to the given C++ ostream. All
|
||||||
|
// required fields must be set.
|
||||||
|
bool SerializeToOstream(std::ostream* output) const;
|
||||||
|
// Like SerializeToOstream(), but allows missing required fields.
|
||||||
|
bool SerializePartialToOstream(std::ostream* output) const;
|
||||||
|
|
||||||
// Like SerializeToString(), but appends to the data to the string's
|
// Like SerializeToString(), but appends to the data to the string's
|
||||||
// existing contents. All required fields must be set.
|
// existing contents. All required fields must be set.
|
||||||
bool AppendToString(std::string* output) const;
|
bool AppendToString(std::string* output) const;
|
||||||
// Like AppendToString(), but allows missing required fields.
|
// Like AppendToString(), but allows missing required fields.
|
||||||
bool AppendPartialToString(std::string* output) const;
|
bool AppendPartialToString(std::string* output) const;
|
||||||
|
|
||||||
|
|
||||||
// Computes the serialized size of the message. This recursively calls
|
// Computes the serialized size of the message. This recursively calls
|
||||||
// ByteSizeLong() on all embedded messages.
|
// ByteSizeLong() on all embedded messages.
|
||||||
//
|
//
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
#ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
|
#ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
|
||||||
#define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
|
#define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <google/protobuf/io/coded_stream.h>
|
#include <google/protobuf/io/coded_stream.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream.h>
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
@ -390,16 +390,14 @@ void Struct::SerializeWithCachedSizes(
|
|||||||
}
|
}
|
||||||
::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
|
::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
|
||||||
for (size_type i = 0; i < n; i++) {
|
for (size_type i = 0; i < n; i++) {
|
||||||
Struct_FieldsEntry_DoNotUse::MapEntryWrapper entry(nullptr, items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second);
|
Struct_FieldsEntry_DoNotUse::Funcs::SerializeToCodedStream(1, items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second, output);
|
||||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray(1, entry, output);
|
|
||||||
Utf8Check::Check(&(*items[static_cast<ptrdiff_t>(i)]));
|
Utf8Check::Check(&(*items[static_cast<ptrdiff_t>(i)]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator
|
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator
|
||||||
it = this->fields().begin();
|
it = this->fields().begin();
|
||||||
it != this->fields().end(); ++it) {
|
it != this->fields().end(); ++it) {
|
||||||
Struct_FieldsEntry_DoNotUse::MapEntryWrapper entry(nullptr, it->first, it->second);
|
Struct_FieldsEntry_DoNotUse::Funcs::SerializeToCodedStream(1, it->first, it->second, output);
|
||||||
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray(1, entry, output);
|
|
||||||
Utf8Check::Check(&(*it));
|
Utf8Check::Check(&(*it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,16 +444,14 @@ void Struct::SerializeWithCachedSizes(
|
|||||||
}
|
}
|
||||||
::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
|
::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
|
||||||
for (size_type i = 0; i < n; i++) {
|
for (size_type i = 0; i < n; i++) {
|
||||||
Struct_FieldsEntry_DoNotUse::MapEntryWrapper entry(nullptr, items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second);
|
target = Struct_FieldsEntry_DoNotUse::Funcs::SerializeToArray(1, items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second, target);
|
||||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::InternalWriteMessageNoVirtualToArray(1, entry, target);
|
|
||||||
Utf8Check::Check(&(*items[static_cast<ptrdiff_t>(i)]));
|
Utf8Check::Check(&(*items[static_cast<ptrdiff_t>(i)]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator
|
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator
|
||||||
it = this->fields().begin();
|
it = this->fields().begin();
|
||||||
it != this->fields().end(); ++it) {
|
it != this->fields().end(); ++it) {
|
||||||
Struct_FieldsEntry_DoNotUse::MapEntryWrapper entry(nullptr, it->first, it->second);
|
target = Struct_FieldsEntry_DoNotUse::Funcs::SerializeToArray(1, it->first, it->second, target);
|
||||||
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::InternalWriteMessageNoVirtualToArray(1, entry, target);
|
|
||||||
Utf8Check::Check(&(*it));
|
Utf8Check::Check(&(*it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,9 +484,7 @@ size_t Struct::ByteSizeLong() const {
|
|||||||
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator
|
for (::PROTOBUF_NAMESPACE_ID::Map< std::string, PROTOBUF_NAMESPACE_ID::Value >::const_iterator
|
||||||
it = this->fields().begin();
|
it = this->fields().begin();
|
||||||
it != this->fields().end(); ++it) {
|
it != this->fields().end(); ++it) {
|
||||||
Struct_FieldsEntry_DoNotUse::MapEntryWrapper entry(nullptr, it->first, it->second);
|
total_size += Struct_FieldsEntry_DoNotUse::Funcs::ByteSizeLong(it->first, it->second);
|
||||||
total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
|
|
||||||
MessageSizeNoVirtual(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
|
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
|
||||||
|
@ -174,8 +174,8 @@ message ForeignMessageLite {
|
|||||||
|
|
||||||
enum ForeignEnumLite {
|
enum ForeignEnumLite {
|
||||||
FOREIGN_LITE_FOO = 4;
|
FOREIGN_LITE_FOO = 4;
|
||||||
FOREIGN_LITE_BAR = 5;
|
|
||||||
FOREIGN_LITE_BAZ = 6;
|
FOREIGN_LITE_BAZ = 6;
|
||||||
|
FOREIGN_LITE_BAR = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TestPackedTypesLite {
|
message TestPackedTypesLite {
|
||||||
@ -473,3 +473,16 @@ message PackedFixed32 {
|
|||||||
message NonPackedFixed32 {
|
message NonPackedFixed32 {
|
||||||
repeated fixed32 repeated_fixed32 = 2048;
|
repeated fixed32 repeated_fixed32 = 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test an enum that has multiple values with the same number.
|
||||||
|
message DupEnum {
|
||||||
|
enum TestEnumWithDupValueLite {
|
||||||
|
option allow_alias = true;
|
||||||
|
|
||||||
|
FOO1 = 1;
|
||||||
|
BAR1 = 2;
|
||||||
|
BAZ = 3;
|
||||||
|
FOO2 = 1;
|
||||||
|
BAR2 = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user