Merge branch 'sync-piper' into sync-integrate

pull/7361/head
Joshua Haberman 5 years ago
commit 4692661ee4
  1. 3
      conformance/conformance_python.py
  2. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  3. 31
      python/google/protobuf/internal/json_format_test.py
  4. 13
      python/google/protobuf/internal/type_checkers.py
  5. 35
      python/google/protobuf/json_format.py
  6. 20
      src/google/protobuf/arena.h
  7. 17
      src/google/protobuf/compiler/cpp/cpp_helpers.h
  8. 167
      src/google/protobuf/compiler/cpp/cpp_message.cc
  9. 30
      src/google/protobuf/compiler/zip_writer.cc
  10. 30
      src/google/protobuf/compiler/zip_writer.h
  11. 89
      src/google/protobuf/descriptor.pb.cc
  12. 15
      src/google/protobuf/descriptor.pb.h
  13. 134
      src/google/protobuf/map.h
  14. 412
      src/google/protobuf/map_field.h
  15. 30
      src/google/protobuf/test_messages_proto2.proto
  16. 30
      src/google/protobuf/test_messages_proto3.proto
  17. 36
      src/google/protobuf/util/internal/expecting_objectwriter.h
  18. 20
      src/google/protobuf/util/internal/mock_error_listener.h

@ -157,8 +157,7 @@ def do_test(request):
elif request.requested_output_format == conformance_pb2.JSON: elif request.requested_output_format == conformance_pb2.JSON:
try: try:
response.json_payload = json_format.MessageToJson( response.json_payload = json_format.MessageToJson(test_message)
test_message, float_precision=None)
except Exception as e: except Exception as e:
response.serialize_error = str(e) response.serialize_error = str(e)
return response return response

@ -36,6 +36,7 @@ __author__ = 'jieluo@google.com (Jie Luo)'
import json import json
import math import math
import struct
import sys import sys
try: try:
@ -821,15 +822,41 @@ class JsonFormatTest(JsonFormatBase):
def testFloatPrecision(self): def testFloatPrecision(self):
message = json_format_proto3_pb2.TestMessage() message = json_format_proto3_pb2.TestMessage()
message.float_value = 1.123456789 message.float_value = 1.123456789
# Default to 8 valid digits. # Set to 8 valid digits.
text = '{\n "floatValue": 1.1234568\n}' text = '{\n "floatValue": 1.1234568\n}'
self.assertEqual( self.assertEqual(
json_format.MessageToJson(message), text) json_format.MessageToJson(message, float_precision=8), text)
# Set to 7 valid digits. # Set to 7 valid digits.
text = '{\n "floatValue": 1.123457\n}' text = '{\n "floatValue": 1.123457\n}'
self.assertEqual( self.assertEqual(
json_format.MessageToJson(message, float_precision=7), text) json_format.MessageToJson(message, float_precision=7), text)
# Default float_precision will automatic print shortest float.
message.float_value = 1.1000000011
text = '{\n "floatValue": 1.1\n}'
self.assertEqual(
json_format.MessageToJson(message), text)
message.float_value = 1.00000075e-36
text = '{\n "floatValue": 1.00000075e-36\n}'
self.assertEqual(
json_format.MessageToJson(message), text)
message.float_value = 12345678912345e+11
text = '{\n "floatValue": 1.234568e+24\n}'
self.assertEqual(
json_format.MessageToJson(message), text)
# Test a bunch of data and check json encode/decode do not
# lose precision
value_list = [0x00, 0xD8, 0x6E, 0x00]
msg2 = json_format_proto3_pb2.TestMessage()
for a in range(0, 256):
value_list[3] = a
for b in range(0, 256):
value_list[0] = b
byte_array = bytearray(value_list)
message.float_value = struct.unpack('<f', byte_array)[0]
self.CheckParseBack(message, msg2)
def testParseEmptyText(self): def testParseEmptyText(self):
self.CheckError('', self.CheckError('',
r'Failed to load JSON: (Expecting value)|(No JSON).') r'Failed to load JSON: (Expecting value)|(No JSON).')

@ -64,6 +64,14 @@ from google.protobuf import descriptor
_FieldDescriptor = descriptor.FieldDescriptor _FieldDescriptor = descriptor.FieldDescriptor
def TruncateToFourByteFloat(original):
if ctypes:
return ctypes.c_float(original).value
else:
return struct.unpack('<f', struct.pack('<f', original))[0]
def SupportsOpenEnums(field_descriptor): def SupportsOpenEnums(field_descriptor):
return field_descriptor.containing_type.syntax == "proto3" return field_descriptor.containing_type.syntax == "proto3"
@ -262,10 +270,7 @@ class FloatValueChecker(object):
if converted_value < _FLOAT_MIN: if converted_value < _FLOAT_MIN:
return _NEG_INF return _NEG_INF
if ctypes: return TruncateToFourByteFloat(converted_value)
return ctypes.c_float(converted_value).value
else:
return struct.unpack('<f', struct.pack('<f', converted_value))[0]
def DefaultValue(self): def DefaultValue(self):
return 0.0 return 0.0

@ -60,6 +60,7 @@ import sys
import six import six
from google.protobuf.internal import type_checkers
from google.protobuf import descriptor from google.protobuf import descriptor
from google.protobuf import symbol_database from google.protobuf import symbol_database
@ -104,7 +105,7 @@ def MessageToJson(
sort_keys=False, sort_keys=False,
use_integers_for_enums=False, use_integers_for_enums=False,
descriptor_pool=None, descriptor_pool=None,
float_precision=8): float_precision=None):
"""Converts protobuf message to JSON format. """Converts protobuf message to JSON format.
Args: Args:
@ -123,7 +124,6 @@ def MessageToJson(
descriptor_pool: A Descriptor Pool for resolving types. If None use the descriptor_pool: A Descriptor Pool for resolving types. If None use the
default. default.
float_precision: If set, use this to specify float field valid digits. float_precision: If set, use this to specify float field valid digits.
Otherwise, 8 valid digits is used (default '.8g').
Returns: Returns:
A string containing the JSON formatted protocol buffer message. A string containing the JSON formatted protocol buffer message.
@ -143,7 +143,7 @@ def MessageToDict(
preserving_proto_field_name=False, preserving_proto_field_name=False,
use_integers_for_enums=False, use_integers_for_enums=False,
descriptor_pool=None, descriptor_pool=None,
float_precision=8): float_precision=None):
"""Converts protobuf message to a dictionary. """Converts protobuf message to a dictionary.
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec. When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
@ -161,7 +161,6 @@ def MessageToDict(
descriptor_pool: A Descriptor Pool for resolving types. If None use the descriptor_pool: A Descriptor Pool for resolving types. If None use the
default. default.
float_precision: If set, use this to specify float field valid digits. float_precision: If set, use this to specify float field valid digits.
Otherwise, 8 valid digits is used (default '.8g').
Returns: Returns:
A dict representation of the protocol buffer message. A dict representation of the protocol buffer message.
@ -284,6 +283,25 @@ class _Printer(object):
def _FieldToJsonObject(self, field, value): def _FieldToJsonObject(self, field, value):
"""Converts field value according to Proto3 JSON Specification.""" """Converts field value according to Proto3 JSON Specification."""
def _ToShortestFloat(original):
"""Returns the shortest float that has same value in wire."""
# Return the original value if it is not truncated. This may happen
# if someone mixes this code with an old protobuf runtime.
if type_checkers.TruncateToFourByteFloat(original) != original:
return original
# All 4 byte floats have between 6 and 9 significant digits, so we
# start with 6 as the lower bound.
# It has to be iterative because use '.9g' directly can not get rid
# of the noises for most values. For example if set a float_field=0.9
# use '.9g' will print 0.899999976.
precision = 6
rounded = float('{0:.{1}g}'.format(original, precision))
while type_checkers.TruncateToFourByteFloat(rounded) != original:
precision += 1
rounded = float('{0:.{1}g}'.format(original, precision))
return rounded
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
return self._MessageToJsonObject(value) return self._MessageToJsonObject(value)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
@ -315,9 +333,12 @@ class _Printer(object):
return _INFINITY return _INFINITY
if math.isnan(value): if math.isnan(value):
return _NAN return _NAN
if (self.float_format and if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT): if self.float_format:
return float(format(value, self.float_format)) return float(format(value, self.float_format))
else:
return _ToShortestFloat(value)
return value return value
def _AnyMessageToJsonObject(self, message): def _AnyMessageToJsonObject(self, message):

@ -219,14 +219,15 @@ struct ArenaOptions {
// any special requirements on the type T, and will invoke the object's // any special requirements on the type T, and will invoke the object's
// destructor when the arena is destroyed. // destructor when the arena is destroyed.
// //
// The arena message allocation protocol, required by CreateMessage<T>, is as // The arena message allocation protocol, required by
// follows: // CreateMessage<T>(Arena* arena, Args&&... args), is as follows:
// //
// - The type T must have (at least) two constructors: a constructor with no // - The type T must have (at least) two constructors: a constructor callable
// arguments, called when a T is allocated on the heap; and a constructor with // with `args` (without `arena`), called when a T is allocated on the heap;
// a Arena* argument, called when a T is allocated on an arena. If the // and a constructor callable with `Arena* arena, Args&&... args`, called when
// second constructor is called with a NULL arena pointer, it must be // a T is allocated on an arena. If the second constructor is called with a
// equivalent to invoking the first (no-argument) constructor. // NULL arena pointer, it must be equivalent to invoking the first
// (`args`-only) constructor.
// //
// - The type T must have a particular type trait: a nested type // - The type T must have a particular type trait: a nested type
// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no // |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
@ -239,11 +240,6 @@ struct ArenaOptions {
// present on the type, then its destructor is always called when the // present on the type, then its destructor is always called when the
// containing arena is destroyed. // containing arena is destroyed.
// //
// - One- and two-user-argument forms of CreateMessage<T>() also exist that
// forward these constructor arguments to T's constructor: for example,
// CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
// arg1, arg2).
//
// This protocol is implemented by all arena-enabled proto2 message classes as // This protocol is implemented by all arena-enabled proto2 message classes as
// well as protobuf container types like RepeatedPtrField and Map. The protocol // well as protobuf container types like RepeatedPtrField and Map. The protocol
// is internal to protobuf and is not guaranteed to be stable. Non-proto types // is internal to protobuf and is not guaranteed to be stable. Non-proto types

@ -429,9 +429,22 @@ inline bool HasFieldPresence(const FileDescriptor* file) {
} }
inline bool HasHasbit(const FieldDescriptor* field) { inline bool HasHasbit(const FieldDescriptor* field) {
// TODO(haberman): remove, and give some proto3 fields hasbits. // TODO(haberman): remove, so proto3 optional fields have hasbits.
if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) return false; if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) return false;
return field->is_singular_with_presence();
// This predicate includes proto3 message fields only if they have "optional".
// Foo submsg1 = 1; // HasHasbit() == false
// optional Foo submsg2 = 2; // HasHasbit() == true
// This is slightly odd, as adding "optional" to a singular proto3 field does
// not change the semantics or API. However whenever any field in a message
// has a hasbit, it forces reflection to include hasbit offsets for *all*
// fields, even if almost all of them are set to -1 (no hasbit). So to avoid
// causing a sudden size regression for ~all proto3 messages, we give proto3
// message fields a hasbit only if "optional" is present. If the user is
// explicitly writing "optional", it is likely they are writing it on
// primitive fields also.
return (field->has_optional_keyword() || field->is_required()) &&
!field->options().weak();
} }
// Returns true if 'enum' semantics are such that unknown values are preserved // Returns true if 'enum' semantics are such that unknown values are preserved

@ -69,6 +69,8 @@ using internal::WireFormatLite;
namespace { namespace {
static constexpr int kNoHasbit = -1;
// Create an expression that evaluates to // Create an expression that evaluates to
// "for all i, (_has_bits_[i] & masks[i]) == masks[i]" // "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
// masks is allowed to be shorter than _has_bits_, but at least one element of // masks is allowed to be shorter than _has_bits_, but at least one element of
@ -239,7 +241,8 @@ bool HasHasMethod(const FieldDescriptor* field) {
} }
// For message types without true field presence, only fields with a message // For message types without true field presence, only fields with a message
// type have a has_$name$() method. // type have a has_$name$() method.
return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
field->has_optional_keyword();
} }
// Collects map entry message type information. // Collects map entry message type information.
@ -329,10 +332,16 @@ bool TableDrivenParsingEnabled(const Descriptor* descriptor,
// Consider table-driven parsing. We only do this if: // Consider table-driven parsing. We only do this if:
// - We have has_bits for fields. This avoids a check on every field we set // - We have has_bits for fields. This avoids a check on every field we set
// when are present (the common case). // when are present (the common case).
if (!HasFieldPresence(descriptor->file())) { bool has_hasbit = false;
return false; for (int i = 0; i < descriptor->field_count(); i++) {
if (HasHasbit(descriptor->field(i))) {
has_hasbit = true;
break;
}
} }
if (!has_hasbit) return false;
const double table_sparseness = 0.5; const double table_sparseness = 0.5;
int max_field_number = 0; int max_field_number = 0;
for (auto field : FieldRange(descriptor)) { for (auto field : FieldRange(descriptor)) {
@ -488,7 +497,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index,
const std::string& from, const std::string& from,
io::Printer* printer) { io::Printer* printer) {
Formatter format(printer, variables_); Formatter format(printer, variables_);
if (!access_info_map_ || has_bit_indices_.empty()) { if (!access_info_map_) {
return; return;
} else if (chunk < limit_chunk_) { } else if (chunk < limit_chunk_) {
// We are already inside a run of cold chunks. // We are already inside a run of cold chunks.
@ -595,17 +604,18 @@ MessageGenerator::MessageGenerator(
message_layout_helper_->OptimizeLayout(&optimized_order_, options_); message_layout_helper_->OptimizeLayout(&optimized_order_, options_);
if (HasFieldPresence(descriptor_->file())) { // This message has hasbits iff one or more fields need one.
// We use -1 as a sentinel. for (auto field : optimized_order_) {
has_bit_indices_.resize(descriptor_->field_count(), -1); if (HasHasbit(field)) {
for (auto field : optimized_order_) { if (has_bit_indices_.empty()) {
// Skip fields that do not have has bits. has_bit_indices_.resize(descriptor_->field_count(), kNoHasbit);
if (field->is_repeated()) {
continue;
} }
has_bit_indices_[field->index()] = max_has_bit_index_++; has_bit_indices_[field->index()] = max_has_bit_index_++;
} }
}
if (!has_bit_indices_.empty()) {
field_generators_.SetHasBitIndices(has_bit_indices_); field_generators_.SetHasBitIndices(has_bit_indices_);
} }
@ -635,17 +645,18 @@ size_t MessageGenerator::HasBitsSize() const {
} }
int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const { int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const {
return has_bit_indices_.empty() ? -1 : has_bit_indices_[field->index()]; return has_bit_indices_.empty() ? kNoHasbit
: has_bit_indices_[field->index()];
} }
int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const { int MessageGenerator::HasByteIndex(const FieldDescriptor* field) const {
int hasbit = HasBitIndex(field); int hasbit = HasBitIndex(field);
return hasbit == -1 ? -1 : hasbit / 8; return hasbit == kNoHasbit ? kNoHasbit : hasbit / 8;
} }
int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const { int MessageGenerator::HasWordIndex(const FieldDescriptor* field) const {
int hasbit = HasBitIndex(field); int hasbit = HasBitIndex(field);
return hasbit == -1 ? -1 : hasbit / 32; return hasbit == kNoHasbit ? kNoHasbit : hasbit / 32;
} }
void MessageGenerator::AddGenerators( void MessageGenerator::AddGenerators(
@ -784,11 +795,9 @@ void MessageGenerator::GenerateSingularFieldHasBits(
"}\n"); "}\n");
return; return;
} }
if (HasFieldPresence(descriptor_->file())) { if (HasHasbit(field)) {
// N.B.: without field presence, we do not use has-bits or generate int has_bit_index = HasBitIndex(field);
// has_$name$() methods. GOOGLE_CHECK_NE(has_bit_index, kNoHasbit);
int has_bit_index = has_bit_indices_[field->index()];
GOOGLE_CHECK_GE(has_bit_index, 0);
format.Set("has_array_index", has_bit_index / 32); format.Set("has_array_index", has_bit_index / 32);
format.Set("has_mask", format.Set("has_mask",
@ -813,27 +822,25 @@ void MessageGenerator::GenerateSingularFieldHasBits(
"$annotate_accessor$" "$annotate_accessor$"
" return _internal_has_$name$();\n" " return _internal_has_$name$();\n"
"}\n"); "}\n");
} else { } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// Message fields have a has_$name$() method. // Message fields have a has_$name$() method.
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (IsLazy(field, options_)) {
if (IsLazy(field, options_)) { format(
format( "inline bool $classname$::_internal_has_$name$() const {\n"
"inline bool $classname$::_internal_has_$name$() const {\n" " return !$name$_.IsCleared();\n"
" return !$name$_.IsCleared();\n" "}\n");
"}\n"); } else {
} else {
format(
"inline bool $classname$::_internal_has_$name$() const {\n"
" return this != internal_default_instance() "
"&& $name$_ != nullptr;\n"
"}\n");
}
format( format(
"inline bool $classname$::has_$name$() const {\n" "inline bool $classname$::_internal_has_$name$() const {\n"
"$annotate_accessor$" " return this != internal_default_instance() "
" return _internal_has_$name$();\n" "&& $name$_ != nullptr;\n"
"}\n"); "}\n");
} }
format(
"inline bool $classname$::has_$name$() const {\n"
"$annotate_accessor$"
" return _internal_has_$name$();\n"
"}\n");
} }
} }
@ -926,16 +933,12 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
format("}\n"); format("}\n");
} else { } else {
field_generators_.get(field).GenerateClearingCode(format.printer()); field_generators_.get(field).GenerateClearingCode(format.printer());
if (HasFieldPresence(descriptor_->file())) { if (HasHasbit(field)) {
if (!field->is_repeated() && !field->options().weak()) { int has_bit_index = HasBitIndex(field);
int has_bit_index = has_bit_indices_[field->index()]; format.Set("has_array_index", has_bit_index / 32);
GOOGLE_CHECK_GE(has_bit_index, 0); format.Set("has_mask",
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
format.Set("has_array_index", has_bit_index / 32); format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
format.Set("has_mask",
strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
}
} }
} }
@ -1540,7 +1543,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
"typedef void DestructorSkippable_;\n"); "typedef void DestructorSkippable_;\n");
} }
if (HasFieldPresence(descriptor_->file())) { if (!has_bit_indices_.empty()) {
// _has_bits_ is frequently accessed, so to reduce code size and improve // _has_bits_ is frequently accessed, so to reduce code size and improve
// speed, it should be close to the start of the object. Placing // speed, it should be close to the start of the object. Placing
// _cached_size_ together with _has_bits_ improves cache locality despite // _cached_size_ together with _has_bits_ improves cache locality despite
@ -1686,8 +1689,8 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
"$3$,\n", "$3$,\n",
offset, aux_offset, max_field_number); offset, aux_offset, max_field_number);
if (!HasFieldPresence(descriptor_->file())) { if (has_bit_indices_.empty()) {
// If we don't have field presence, then _has_bits_ does not exist. // If no fields have hasbits, then _has_bits_ does not exist.
format("-1,\n"); format("-1,\n");
} else { } else {
format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n"); format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
@ -1725,10 +1728,9 @@ bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
void MessageGenerator::GenerateSchema(io::Printer* printer, int offset, void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
int has_offset) { int has_offset) {
Formatter format(printer, variables_); Formatter format(printer, variables_);
has_offset = has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)
HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_) ? offset + has_offset
? offset + has_offset : -1;
: -1;
format("{ $1$, $2$, sizeof($classtype$)},\n", offset, has_offset); format("{ $1$, $2$, sizeof($classtype$)},\n", offset, has_offset);
} }
@ -1763,13 +1765,12 @@ uint32 CalcFieldNum(const FieldGenerator& generator,
} else if (field->is_repeated()) { } else if (field->is_repeated()) {
return internal::FieldMetadata::CalculateType( return internal::FieldMetadata::CalculateType(
type, internal::FieldMetadata::kRepeated); type, internal::FieldMetadata::kRepeated);
} else if (!HasFieldPresence(field->file()) && } else if (HasHasbit(field) || field->containing_oneof() || is_a_map) {
field->containing_oneof() == NULL && !is_a_map) {
return internal::FieldMetadata::CalculateType( return internal::FieldMetadata::CalculateType(
type, internal::FieldMetadata::kNoPresence); type, internal::FieldMetadata::kPresence);
} else { } else {
return internal::FieldMetadata::CalculateType( return internal::FieldMetadata::CalculateType(
type, internal::FieldMetadata::kPresence); type, internal::FieldMetadata::kNoPresence);
} }
} }
@ -1897,8 +1898,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
"::internal::LazyFieldSerializer"; "::internal::LazyFieldSerializer";
if (field->containing_oneof()) { if (field->containing_oneof()) {
ptr += "OneOf"; ptr += "OneOf";
} else if (!HasFieldPresence(descriptor_->file()) || } else if (!HasHasbit(field)) {
has_bit_indices_[field->index()] == -1) {
ptr += "NoPresence"; ptr += "NoPresence";
} }
ptr += ")"; ptr += ")";
@ -1921,8 +1921,7 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
" PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + " " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
"$oneofoffset$, $2$, $3$},\n", "$oneofoffset$, $2$, $3$},\n",
tag, type, ptr); tag, type, ptr);
} else if (HasFieldPresence(descriptor_->file()) && } else if (HasHasbit(field)) {
has_bit_indices_[field->index()] != -1) {
format.Set("hasbitsoffset", has_bit_indices_[field->index()]); format.Set("hasbitsoffset", has_bit_indices_[field->index()]);
format( format(
"{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), " "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
@ -2073,7 +2072,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
"class $classname$::_Internal {\n" "class $classname$::_Internal {\n"
" public:\n"); " public:\n");
format.Indent(); format.Indent();
if (HasFieldPresence(descriptor_->file()) && HasBitsSize() != 0) { if (!has_bit_indices_.empty()) {
format( format(
"using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n"); "using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n");
} }
@ -2082,10 +2081,8 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
if (!IsFieldUsed(field, options_)) { if (!IsFieldUsed(field, options_)) {
continue; continue;
} }
if (HasFieldPresence(descriptor_->file()) && !field->is_repeated() && if (HasHasbit(field)) {
!field->options().weak() && !field->containing_oneof()) { int has_bit_index = HasBitIndex(field);
int has_bit_index = has_bit_indices_[field->index()];
GOOGLE_CHECK_GE(has_bit_index, 0);
format( format(
"static void set_has_$1$(HasBits* has_bits) {\n" "static void set_has_$1$(HasBits* has_bits) {\n"
" (*has_bits)[$2$] |= $3$u;\n" " (*has_bits)[$2$] |= $3$u;\n"
@ -2093,7 +2090,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32))); FieldName(field), has_bit_index / 32, (1u << (has_bit_index % 32)));
} }
} }
if (num_required_fields_ > 0 && HasFieldPresence(descriptor_->file())) { if (num_required_fields_ > 0) {
const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(); const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
format( format(
"static bool MissingRequiredFields(const HasBits& has_bits) " "static bool MissingRequiredFields(const HasBits& has_bits) "
@ -2392,7 +2389,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
io::Printer* printer) { io::Printer* printer) {
Formatter format(printer, variables_); Formatter format(printer, variables_);
if (HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)) { if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)) {
format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n"); format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
} else { } else {
format("~0u, // no _has_bits_\n"); format("~0u, // no _has_bits_\n");
@ -2451,7 +2448,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
format( format(
"0,\n" "0,\n"
"1,\n"); "1,\n");
} else if (HasFieldPresence(descriptor_->file())) { } else if (!has_bit_indices_.empty()) {
entries += has_bit_indices_.size() - num_stripped; entries += has_bit_indices_.size() - num_stripped;
for (int i = 0; i < has_bit_indices_.size(); i++) { for (int i = 0; i < has_bit_indices_.size(); i++) {
if (!IsFieldUsed(descriptor_->field(i), options_)) { if (!IsFieldUsed(descriptor_->field(i), options_)) {
@ -2723,10 +2720,8 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) {
format.Indent(); format.Indent();
format.Indent(); format.Indent();
if (HasFieldPresence(descriptor_->file())) { if (!has_bit_indices_.empty()) {
if (!IsProto2MessageSet(descriptor_, options_)) { format(",\n_has_bits_(from._has_bits_)");
format(",\n_has_bits_(from._has_bits_)");
}
} }
std::vector<bool> processed(optimized_order_.size(), false); std::vector<bool> processed(optimized_order_.size(), false);
@ -2916,7 +2911,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
// We can omit the if() for chunk size 1, or if our fields do not have // We can omit the if() for chunk size 1, or if our fields do not have
// hasbits. I don't understand the rationale for the last part of the // hasbits. I don't understand the rationale for the last part of the
// condition, but it matches the old logic. // condition, but it matches the old logic.
const bool have_outer_if = HasBitIndex(chunk.front()) != -1 && const bool have_outer_if = HasBitIndex(chunk.front()) != kNoHasbit &&
chunk.size() > 1 && chunk.size() > 1 &&
(memset_end != chunk.back() || merge_zero_init); (memset_end != chunk.back() || merge_zero_init);
@ -2962,7 +2957,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
// //
// TODO(kenton): Let the CppFieldGenerator decide this somehow. // TODO(kenton): Let the CppFieldGenerator decide this somehow.
bool have_enclosing_if = bool have_enclosing_if =
HasBitIndex(field) != -1 && HasBitIndex(field) != kNoHasbit &&
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
@ -2999,7 +2994,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
format("_weak_field_map_.ClearAll();\n"); format("_weak_field_map_.ClearAll();\n");
} }
if (HasFieldPresence(descriptor_->file())) { if (!has_bit_indices_.empty()) {
// Step 5: Everything else. // Step 5: Everything else.
format("_has_bits_.Clear();\n"); format("_has_bits_.Clear();\n");
} }
@ -3075,7 +3070,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) {
"_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_" "_internal_metadata_.Swap<$unknown_fields_type$>(&other->_internal_"
"metadata_);\n"); "metadata_);\n");
if (HasFieldPresence(descriptor_->file())) { if (!has_bit_indices_.empty()) {
for (int i = 0; i < HasBitsSize() / 4; ++i) { for (int i = 0; i < HasBitsSize() / 4; ++i) {
format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i); format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i);
} }
@ -3218,7 +3213,8 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) {
for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
bool have_outer_if = chunk.size() > 1 && HasByteIndex(chunk.front()) != -1; bool have_outer_if =
chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit;
cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.", cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.",
printer); printer);
@ -3466,9 +3462,9 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
bool have_enclosing_if = false; bool have_enclosing_if = false;
if (field->options().weak()) { if (field->options().weak()) {
} else if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { } else if (HasHasbit(field)) {
// Attempt to use the state of cached_has_bits, if possible. // Attempt to use the state of cached_has_bits, if possible.
int has_bit_index = has_bit_indices_[field->index()]; int has_bit_index = HasBitIndex(field);
if (cached_has_bits_index == has_bit_index / 32) { if (cached_has_bits_index == has_bit_index / 32) {
const std::string mask = const std::string mask =
StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
@ -3480,7 +3476,7 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
format.Indent(); format.Indent();
have_enclosing_if = true; have_enclosing_if = true;
} else if (!HasFieldPresence(descriptor_->file())) { } else if (field->is_optional() && !HasHasbit(field)) {
have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field); have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
} }
@ -3561,7 +3557,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(
: mg_(mg), : mg_(mg),
format_(printer), format_(printer),
eager_(!HasFieldPresence(mg->descriptor_->file())), eager_(!HasFieldPresence(mg->descriptor_->file())),
cached_has_bit_index_(-1) {} cached_has_bit_index_(kNoHasbit) {}
~LazySerializerEmitter() { Flush(); } ~LazySerializerEmitter() { Flush(); }
@ -3841,7 +3837,8 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) {
for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
const bool have_outer_if = chunk.size() > 1 && HasWordIndex(chunk[0]) != -1; const bool have_outer_if =
chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit;
cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer); cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
if (have_outer_if) { if (have_outer_if) {
@ -3983,7 +3980,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
"}\n\n"); "}\n\n");
} }
if (num_required_fields_ > 0 && HasFieldPresence(descriptor_->file())) { if (num_required_fields_ > 0) {
format( format(
"if (_Internal::MissingRequiredFields(_has_bits_))" "if (_Internal::MissingRequiredFields(_has_bits_))"
" return false;\n"); " return false;\n");

@ -28,36 +28,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 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.
// Author: ambrose@google.com (Ambrose Feinstein), // Author: ambrose@google.com (Ambrose Feinstein),
// kenton@google.com (Kenton Varda) // kenton@google.com (Kenton Varda)
// //

@ -28,36 +28,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 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.
// Author: kenton@google.com (Kenton Varda) // Author: kenton@google.com (Kenton Varda)
#include <vector> #include <vector>

@ -567,13 +567,12 @@ static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptor
static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr; static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _has_bits_), ~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
~0u, // no _oneof_case_ ~0u, // no _oneof_case_
~0u, // no _weak_field_map_ ~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, file_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorSet, file_),
~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _has_bits_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _has_bits_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
@ -648,13 +647,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
1, 1,
~0u, ~0u,
~0u, ~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _has_bits_), ~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _extensions_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _extensions_),
~0u, // no _oneof_case_ ~0u, // no _oneof_case_
~0u, // no _weak_field_map_ ~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, uninterpreted_option_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, uninterpreted_option_),
~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _has_bits_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _has_bits_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
@ -835,13 +833,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
3, 3,
4, 4,
~0u, ~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _has_bits_), ~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _extensions_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, _extensions_),
~0u, // no _oneof_case_ ~0u, // no _oneof_case_
~0u, // no _weak_field_map_ ~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, uninterpreted_option_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::OneofOptions, uninterpreted_option_),
~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _has_bits_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _has_bits_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _extensions_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::EnumOptions, _extensions_),
@ -925,13 +922,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
0, 0,
1, 1,
~0u, ~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _has_bits_), ~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
~0u, // no _oneof_case_ ~0u, // no _oneof_case_
~0u, // no _weak_field_map_ ~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, location_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::SourceCodeInfo, location_),
~0u,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _has_bits_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _has_bits_),
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
@ -945,42 +941,41 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fdescriptor
0, 0,
1, 1,
2, 2,
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _has_bits_), ~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
~0u, // no _oneof_case_ ~0u, // no _oneof_case_
~0u, // no _weak_field_map_ ~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, annotation_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, annotation_),
~0u,
}; };
static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
{ 0, 6, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorSet)}, { 0, -1, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorSet)},
{ 7, 24, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorProto)}, { 6, 23, sizeof(PROTOBUF_NAMESPACE_ID::FileDescriptorProto)},
{ 36, 44, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)}, { 35, 43, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)},
{ 47, 54, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)}, { 46, 53, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)},
{ 56, 71, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto)}, { 55, 70, sizeof(PROTOBUF_NAMESPACE_ID::DescriptorProto)},
{ 81, 87, sizeof(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)}, { 80, -1, sizeof(PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)},
{ 88, 104, sizeof(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)}, { 86, 102, sizeof(PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)},
{ 115, 122, sizeof(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)}, { 113, 120, sizeof(PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)},
{ 124, 131, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)}, { 122, 129, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)},
{ 133, 143, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)}, { 131, 141, sizeof(PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)},
{ 148, 156, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)}, { 146, 154, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)},
{ 159, 167, sizeof(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)}, { 157, 165, sizeof(PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)},
{ 170, 181, sizeof(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)}, { 168, 179, sizeof(PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)},
{ 187, 213, sizeof(PROTOBUF_NAMESPACE_ID::FileOptions)}, { 185, 211, sizeof(PROTOBUF_NAMESPACE_ID::FileOptions)},
{ 234, 244, sizeof(PROTOBUF_NAMESPACE_ID::MessageOptions)}, { 232, 242, sizeof(PROTOBUF_NAMESPACE_ID::MessageOptions)},
{ 249, 261, sizeof(PROTOBUF_NAMESPACE_ID::FieldOptions)}, { 247, 259, sizeof(PROTOBUF_NAMESPACE_ID::FieldOptions)},
{ 268, 274, sizeof(PROTOBUF_NAMESPACE_ID::OneofOptions)}, { 266, -1, sizeof(PROTOBUF_NAMESPACE_ID::OneofOptions)},
{ 275, 283, sizeof(PROTOBUF_NAMESPACE_ID::EnumOptions)}, { 272, 280, sizeof(PROTOBUF_NAMESPACE_ID::EnumOptions)},
{ 286, 293, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueOptions)}, { 283, 290, sizeof(PROTOBUF_NAMESPACE_ID::EnumValueOptions)},
{ 295, 302, sizeof(PROTOBUF_NAMESPACE_ID::ServiceOptions)}, { 292, 299, sizeof(PROTOBUF_NAMESPACE_ID::ServiceOptions)},
{ 304, 312, sizeof(PROTOBUF_NAMESPACE_ID::MethodOptions)}, { 301, 309, sizeof(PROTOBUF_NAMESPACE_ID::MethodOptions)},
{ 315, 322, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)}, { 312, 319, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)},
{ 324, 336, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption)}, { 321, 333, sizeof(PROTOBUF_NAMESPACE_ID::UninterpretedOption)},
{ 343, 353, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)}, { 340, 350, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)},
{ 358, 364, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo)}, { 355, -1, sizeof(PROTOBUF_NAMESPACE_ID::SourceCodeInfo)},
{ 365, 374, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)}, { 361, 370, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)},
{ 378, 384, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)}, { 374, -1, sizeof(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)},
}; };
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
@ -1384,7 +1379,6 @@ void FileDescriptorSet::InitAsDefaultInstance() {
} }
class FileDescriptorSet::_Internal { class FileDescriptorSet::_Internal {
public: public:
using HasBits = decltype(std::declval<FileDescriptorSet>()._has_bits_);
}; };
FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena) FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@ -1396,7 +1390,6 @@ FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena)
} }
FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
: ::PROTOBUF_NAMESPACE_ID::Message(), : ::PROTOBUF_NAMESPACE_ID::Message(),
_has_bits_(from._has_bits_),
file_(from.file_) { file_(from.file_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
// @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet) // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet)
@ -1438,7 +1431,6 @@ void FileDescriptorSet::Clear() {
(void) cached_has_bits; (void) cached_has_bits;
file_.Clear(); file_.Clear();
_has_bits_.Clear();
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
} }
@ -1577,7 +1569,6 @@ bool FileDescriptorSet::IsInitialized() const {
void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
using std::swap; using std::swap;
_internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
file_.InternalSwap(&other->file_); file_.InternalSwap(&other->file_);
} }
@ -3369,7 +3360,6 @@ void ExtensionRangeOptions::InitAsDefaultInstance() {
} }
class ExtensionRangeOptions::_Internal { class ExtensionRangeOptions::_Internal {
public: public:
using HasBits = decltype(std::declval<ExtensionRangeOptions>()._has_bits_);
}; };
ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@ -3382,7 +3372,6 @@ ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* are
} }
ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from) ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from)
: ::PROTOBUF_NAMESPACE_ID::Message(), : ::PROTOBUF_NAMESPACE_ID::Message(),
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) { uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_); _extensions_.MergeFrom(from._extensions_);
@ -3426,7 +3415,6 @@ void ExtensionRangeOptions::Clear() {
_extensions_.Clear(); _extensions_.Clear();
uninterpreted_option_.Clear(); uninterpreted_option_.Clear();
_has_bits_.Clear();
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
} }
@ -3583,7 +3571,6 @@ void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) {
using std::swap; using std::swap;
_extensions_.Swap(&other->_extensions_); _extensions_.Swap(&other->_extensions_);
_internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
} }
@ -7985,7 +7972,6 @@ void OneofOptions::InitAsDefaultInstance() {
} }
class OneofOptions::_Internal { class OneofOptions::_Internal {
public: public:
using HasBits = decltype(std::declval<OneofOptions>()._has_bits_);
}; };
OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena) OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@ -7998,7 +7984,6 @@ OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena)
} }
OneofOptions::OneofOptions(const OneofOptions& from) OneofOptions::OneofOptions(const OneofOptions& from)
: ::PROTOBUF_NAMESPACE_ID::Message(), : ::PROTOBUF_NAMESPACE_ID::Message(),
_has_bits_(from._has_bits_),
uninterpreted_option_(from.uninterpreted_option_) { uninterpreted_option_(from.uninterpreted_option_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
_extensions_.MergeFrom(from._extensions_); _extensions_.MergeFrom(from._extensions_);
@ -8042,7 +8027,6 @@ void OneofOptions::Clear() {
_extensions_.Clear(); _extensions_.Clear();
uninterpreted_option_.Clear(); uninterpreted_option_.Clear();
_has_bits_.Clear();
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
} }
@ -8199,7 +8183,6 @@ void OneofOptions::InternalSwap(OneofOptions* other) {
using std::swap; using std::swap;
_extensions_.Swap(&other->_extensions_); _extensions_.Swap(&other->_extensions_);
_internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
uninterpreted_option_.InternalSwap(&other->uninterpreted_option_); uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
} }
@ -10473,7 +10456,6 @@ void SourceCodeInfo::InitAsDefaultInstance() {
} }
class SourceCodeInfo::_Internal { class SourceCodeInfo::_Internal {
public: public:
using HasBits = decltype(std::declval<SourceCodeInfo>()._has_bits_);
}; };
SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena) SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@ -10485,7 +10467,6 @@ SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
} }
SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
: ::PROTOBUF_NAMESPACE_ID::Message(), : ::PROTOBUF_NAMESPACE_ID::Message(),
_has_bits_(from._has_bits_),
location_(from.location_) { location_(from.location_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
// @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo) // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
@ -10527,7 +10508,6 @@ void SourceCodeInfo::Clear() {
(void) cached_has_bits; (void) cached_has_bits;
location_.Clear(); location_.Clear();
_has_bits_.Clear();
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
} }
@ -10665,7 +10645,6 @@ bool SourceCodeInfo::IsInitialized() const {
void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
using std::swap; using std::swap;
_internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
location_.InternalSwap(&other->location_); location_.InternalSwap(&other->location_);
} }
@ -11021,7 +11000,6 @@ void GeneratedCodeInfo::InitAsDefaultInstance() {
} }
class GeneratedCodeInfo::_Internal { class GeneratedCodeInfo::_Internal {
public: public:
using HasBits = decltype(std::declval<GeneratedCodeInfo>()._has_bits_);
}; };
GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena) GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
@ -11033,7 +11011,6 @@ GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena)
} }
GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from) GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from)
: ::PROTOBUF_NAMESPACE_ID::Message(), : ::PROTOBUF_NAMESPACE_ID::Message(),
_has_bits_(from._has_bits_),
annotation_(from.annotation_) { annotation_(from.annotation_) {
_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
// @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo) // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo)
@ -11075,7 +11052,6 @@ void GeneratedCodeInfo::Clear() {
(void) cached_has_bits; (void) cached_has_bits;
annotation_.Clear(); annotation_.Clear();
_has_bits_.Clear();
_internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
} }
@ -11213,7 +11189,6 @@ bool GeneratedCodeInfo::IsInitialized() const {
void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) { void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
using std::swap; using std::swap;
_internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
swap(_has_bits_[0], other->_has_bits_[0]);
annotation_.InternalSwap(&other->annotation_); annotation_.InternalSwap(&other->annotation_);
} }

@ -477,9 +477,8 @@ class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL :
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
typedef void InternalArenaConstructable_; typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_; typedef void DestructorSkippable_;
::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto > file_; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::FileDescriptorProto > file_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -1757,9 +1756,8 @@ class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL :
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
typedef void InternalArenaConstructable_; typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_; typedef void DestructorSkippable_;
::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -4853,9 +4851,8 @@ class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL :
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
typedef void InternalArenaConstructable_; typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_; typedef void DestructorSkippable_;
::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -6508,9 +6505,8 @@ class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL :
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
typedef void InternalArenaConstructable_; typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_; typedef void DestructorSkippable_;
::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location > location_; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location > location_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -6884,9 +6880,8 @@ class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL :
template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
typedef void InternalArenaConstructable_; typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_; typedef void DestructorSkippable_;
::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation > annotation_; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation > annotation_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
}; };
// =================================================================== // ===================================================================

@ -41,6 +41,7 @@
#include <iterator> #include <iterator>
#include <limits> // To support Visual Studio 2008 #include <limits> // To support Visual Studio 2008
#include <set> #include <set>
#include <type_traits>
#include <utility> #include <utility>
#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/common.h>
@ -184,6 +185,35 @@ struct DerefCompare {
bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; } bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
}; };
// This class is used to get trivially destructible views of std::string and
// MapKey, which are the only non-trivially destructible allowed key types.
template <typename Key>
class KeyView {
public:
KeyView(const Key& key) : key_(&key) {} // NOLINT(runtime/explicit)
const Key& get() const { return *key_; }
// Allows implicit conversions to `const Key&`, which allows us to use the
// hasher defined for Key.
operator const Key&() const { return get(); } // NOLINT(runtime/explicit)
bool operator==(const KeyView& other) const { return get() == other.get(); }
bool operator==(const Key& other) const { return get() == other; }
bool operator<(const KeyView& other) const { return get() < other.get(); }
bool operator<(const Key& other) const { return get() < other; }
private:
const Key* key_;
};
// Allows the InnerMap type to support skippable destruction.
template <typename Key>
struct GetTrivialKey {
using type =
typename std::conditional<std::is_trivially_destructible<Key>::value, Key,
KeyView<Key>>::type;
};
} // namespace internal } // namespace internal
// This is the class for Map's internal value_type. Instead of using // This is the class for Map's internal value_type. Instead of using
@ -282,26 +312,27 @@ class Map {
} }
private: private:
void Init() { void Init() { elements_ = Arena::CreateMessage<InnerMap>(arena_, 0u); }
elements_ =
Arena::Create<InnerMap>(arena_, 0u, hasher(), Allocator(arena_)); // InnerMap's key type is TrivialKey and its value type is value_type*. We
} // use a custom class here and for Node, below, to ensure that k_ is at offset
// 0, allowing safe conversion from pointer to Node to pointer to TrivialKey,
// InnerMap's key type is Key and its value type is value_type*. We use a // and vice versa when appropriate. We use GetTrivialKey to adapt Key to
// custom class here and for Node, below, to ensure that k_ is at offset 0, // be a trivially destructible view if Key is not already trivially
// allowing safe conversion from pointer to Node to pointer to Key, and vice // destructible. This view points into the Key inside v_ once it's
// versa when appropriate. // initialized.
using TrivialKey = typename internal::GetTrivialKey<Key>::type;
class KeyValuePair { class KeyValuePair {
public: public:
KeyValuePair(const Key& k, value_type* v) : k_(k), v_(v) {} KeyValuePair(const TrivialKey& k, value_type* v) : k_(k), v_(v) {}
const Key& key() const { return k_; } const TrivialKey& key() const { return k_; }
Key& key() { return k_; } TrivialKey& key() { return k_; }
value_type* value() const { return v_; } value_type* value() const { return v_; }
value_type*& value() { return v_; } value_type*& value() { return v_; }
private: private:
Key k_; TrivialKey k_;
value_type* v_; value_type* v_;
}; };
@ -336,19 +367,28 @@ class Map {
// 8. Mutations to a map do not invalidate the map's iterators, pointers to // 8. Mutations to a map do not invalidate the map's iterators, pointers to
// elements, or references to elements. // elements, or references to elements.
// 9. Except for erase(iterator), any non-const method can reorder iterators. // 9. Except for erase(iterator), any non-const method can reorder iterators.
// 10. InnerMap's key is TrivialKey, which is either Key, if Key is trivially
// destructible, or a trivially destructible view of Key otherwise. This
// allows InnerMap's destructor to be skipped when InnerMap is
// arena-allocated.
class InnerMap : private hasher { class InnerMap : private hasher {
public: public:
using Value = value_type*; using Value = value_type*;
InnerMap(size_type n, hasher h, Allocator alloc) explicit InnerMap(size_type n) : InnerMap(nullptr, n) {}
: hasher(h), InnerMap(Arena* arena, size_type n)
: hasher(),
num_elements_(0), num_elements_(0),
seed_(Seed()), seed_(Seed()),
table_(nullptr), table_(nullptr),
alloc_(alloc) { alloc_(arena) {
n = TableSize(n); n = TableSize(n);
table_ = CreateEmptyTable(n); table_ = CreateEmptyTable(n);
num_buckets_ = index_of_first_non_null_ = n; num_buckets_ = index_of_first_non_null_ = n;
static_assert(
std::is_trivially_destructible<KeyValuePair>::value,
"We require KeyValuePair to be trivially destructible so that we can "
"skip InnerMap's destructor when it's arena allocated.");
} }
~InnerMap() { ~InnerMap() {
@ -369,17 +409,19 @@ class Map {
// This is safe only if the given pointer is known to point to a Key that is // This is safe only if the given pointer is known to point to a Key that is
// part of a Node. // part of a Node.
static Node* NodePtrFromKeyPtr(Key* k) { static Node* NodePtrFromKeyPtr(TrivialKey* k) {
return reinterpret_cast<Node*>(k); return reinterpret_cast<Node*>(k);
} }
static Key* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); } static TrivialKey* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
// Trees. The payload type is pointer to Key, so that we can query the tree // Trees. The payload type is pointer to Key, so that we can query the tree
// with Keys that are not in any particular data structure. When we insert, // with Keys that are not in any particular data structure. When we insert,
// though, the pointer is always pointing to a Key that is inside a Node. // though, the pointer is always pointing to a Key that is inside a Node.
using KeyPtrAllocator = typename Allocator::template rebind<Key*>::other; using KeyPtrAllocator =
using Tree = std::set<Key*, internal::DerefCompare<Key>, KeyPtrAllocator>; typename Allocator::template rebind<TrivialKey*>::other;
using Tree = std::set<TrivialKey*, internal::DerefCompare<TrivialKey>,
KeyPtrAllocator>;
using TreeIterator = typename Tree::iterator; using TreeIterator = typename Tree::iterator;
// iterator and const_iterator are instantiations of iterator_base. // iterator and const_iterator are instantiations of iterator_base.
@ -499,7 +541,7 @@ class Map {
// Well, bucket_index_ still might be correct, but probably // Well, bucket_index_ still might be correct, but probably
// not. Revalidate just to be sure. This case is rare enough that we // not. Revalidate just to be sure. This case is rare enough that we
// don't worry about potential optimizations, such as having a custom // don't worry about potential optimizations, such as having a custom
// find-like method that compares Node* instead of const Key&. // find-like method that compares Node* instead of TrivialKey.
iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it)); iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it));
bucket_index_ = i.bucket_index_; bucket_index_ = i.bucket_index_;
return m_->TableEntryIsList(bucket_index_); return m_->TableEntryIsList(bucket_index_);
@ -558,9 +600,9 @@ class Map {
size_type size() const { return num_elements_; } size_type size() const { return num_elements_; }
bool empty() const { return size() == 0; } bool empty() const { return size() == 0; }
iterator find(const Key& k) { return iterator(FindHelper(k).first); } iterator find(const TrivialKey& k) { return iterator(FindHelper(k).first); }
const_iterator find(const Key& k) const { return find(k, nullptr); } const_iterator find(const TrivialKey& k) const { return find(k, nullptr); }
bool contains(const Key& k) const { return find(k) != end(); } bool contains(const TrivialKey& k) const { return find(k) != end(); }
// In traditional C++ style, this performs "insert if not present." // In traditional C++ style, this performs "insert if not present."
std::pair<iterator, bool> insert(const KeyValuePair& kv) { std::pair<iterator, bool> insert(const KeyValuePair& kv) {
@ -582,7 +624,7 @@ class Map {
// The same, but if an insertion is necessary then the value portion of the // The same, but if an insertion is necessary then the value portion of the
// inserted key-value pair is left uninitialized. // inserted key-value pair is left uninitialized.
std::pair<iterator, bool> insert(const Key& k) { std::pair<iterator, bool> insert(const TrivialKey& k) {
std::pair<const_iterator, size_type> p = FindHelper(k); std::pair<const_iterator, size_type> p = FindHelper(k);
// Case 1: key was already present. // Case 1: key was already present.
if (p.first.node_ != nullptr) if (p.first.node_ != nullptr)
@ -593,16 +635,19 @@ class Map {
} }
const size_type b = p.second; // bucket number const size_type b = p.second; // bucket number
Node* node = Alloc<Node>(1); Node* node = Alloc<Node>(1);
using KeyAllocator = typename Allocator::template rebind<Key>::other; using KeyAllocator =
typename Allocator::template rebind<TrivialKey>::other;
KeyAllocator(alloc_).construct(&node->kv.key(), k); KeyAllocator(alloc_).construct(&node->kv.key(), k);
iterator result = InsertUnique(b, node); iterator result = InsertUnique(b, node);
++num_elements_; ++num_elements_;
return std::make_pair(result, true); return std::make_pair(result, true);
} }
Value& operator[](const Key& k) { // Returns iterator so that outer map can update the TrivialKey to point to
// the Key inside value_type in case TrivialKey is a view type.
iterator operator[](const TrivialKey& k) {
KeyValuePair kv(k, Value()); KeyValuePair kv(k, Value());
return insert(kv).first->value(); return insert(kv).first;
} }
void erase(iterator it) { void erase(iterator it) {
@ -639,13 +684,13 @@ class Map {
} }
private: private:
const_iterator find(const Key& k, TreeIterator* it) const { const_iterator find(const TrivialKey& k, TreeIterator* it) const {
return FindHelper(k, it).first; return FindHelper(k, it).first;
} }
std::pair<const_iterator, size_type> FindHelper(const Key& k) const { std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k) const {
return FindHelper(k, nullptr); return FindHelper(k, nullptr);
} }
std::pair<const_iterator, size_type> FindHelper(const Key& k, std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k,
TreeIterator* it) const { TreeIterator* it) const {
size_type b = BucketNumber(k); size_type b = BucketNumber(k);
if (TableEntryIsNonEmptyList(b)) { if (TableEntryIsNonEmptyList(b)) {
@ -661,7 +706,7 @@ class Map {
GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
b &= ~static_cast<size_t>(1); b &= ~static_cast<size_t>(1);
Tree* tree = static_cast<Tree*>(table_[b]); Tree* tree = static_cast<Tree*>(table_[b]);
Key* key = const_cast<Key*>(&k); TrivialKey* key = const_cast<TrivialKey*>(&k);
typename Tree::iterator tree_it = tree->find(key); typename Tree::iterator tree_it = tree->find(key);
if (tree_it != tree->end()) { if (tree_it != tree->end()) {
if (it != nullptr) *it = tree_it; if (it != nullptr) *it = tree_it;
@ -886,14 +931,13 @@ class Map {
return count >= kMaxLength; return count >= kMaxLength;
} }
size_type BucketNumber(const Key& k) const { size_type BucketNumber(const TrivialKey& k) const {
// We inherit from hasher, so one-arg operator() provides a hash function. size_type h = hash_function()(k);
size_type h = (*const_cast<InnerMap*>(this))(k);
return (h + seed_) & (num_buckets_ - 1); return (h + seed_) & (num_buckets_ - 1);
} }
bool IsMatch(const Key& k0, const Key& k1) const { bool IsMatch(const TrivialKey& k0, const TrivialKey& k1) const {
return std::equal_to<Key>()(k0, k1); return k0 == k1;
} }
// Return a power of two no less than max(kMinTableSize, n). // Return a power of two no less than max(kMinTableSize, n).
@ -949,6 +993,10 @@ class Map {
return s; return s;
} }
friend class Arena;
using InternalArenaConstructable_ = void;
using DestructorSkippable_ = void;
size_type num_elements_; size_type num_elements_;
size_type num_buckets_; size_type num_buckets_;
size_type seed_; size_type seed_;
@ -1050,9 +1098,12 @@ class Map {
// Element access // Element access
T& operator[](const key_type& key) { T& operator[](const key_type& key) {
value_type** value = &(*elements_)[key]; typename InnerMap::iterator it = (*elements_)[key];
value_type** value = &it->value();
if (*value == nullptr) { if (*value == nullptr) {
*value = CreateValueTypeInternal(key); *value = CreateValueTypeInternal(key);
// We need to update the key in case it's a view type.
it->key() = (*value)->first;
internal::MapValueInitializer<is_proto_enum<T>::value, T>::Initialize( internal::MapValueInitializer<is_proto_enum<T>::value, T>::Initialize(
(*value)->second, default_enum_value_); (*value)->second, default_enum_value_);
} }
@ -1106,6 +1157,8 @@ class Map {
elements_->insert(value.first); elements_->insert(value.first);
if (p.second) { if (p.second) {
p.first->value() = CreateValueTypeInternal(value); p.first->value() = CreateValueTypeInternal(value);
// We need to update the key in case it's a view type.
p.first->key() = p.first->value()->first;
} }
return std::pair<iterator, bool>(iterator(p.first), p.second); return std::pair<iterator, bool>(iterator(p.first), p.second);
} }
@ -1133,9 +1186,12 @@ class Map {
} }
} }
iterator erase(iterator pos) { iterator erase(iterator pos) {
if (arena_ == nullptr) delete pos.operator->(); value_type* value = pos.operator->();
iterator i = pos++; iterator i = pos++;
elements_->erase(i.it_); elements_->erase(i.it_);
// Note: we need to delete the value after erasing from the inner map
// because the inner map's key may be a view of the value's key.
if (arena_ == nullptr) delete value;
return pos; return pos;
} }
void erase(iterator first, iterator last) { void erase(iterator first, iterator last) {

@ -56,8 +56,213 @@
namespace google { namespace google {
namespace protobuf { namespace protobuf {
class DynamicMessage; class DynamicMessage;
class MapKey;
class MapIterator; class MapIterator;
#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
if (type() != EXPECTEDTYPE) { \
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" \
<< METHOD << " type does not match\n" \
<< " Expected : " \
<< FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
<< " Actual : " << FieldDescriptor::CppTypeName(type()); \
}
// MapKey is an union type for representing any possible
// map key.
class PROTOBUF_EXPORT MapKey {
public:
MapKey() : type_(0) {}
MapKey(const MapKey& other) : type_(0) { CopyFrom(other); }
MapKey& operator=(const MapKey& other) {
CopyFrom(other);
return *this;
}
~MapKey() {
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
val_.string_value_.Destruct();
}
}
FieldDescriptor::CppType type() const {
if (type_ == 0) {
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
<< "MapKey::type MapKey is not initialized. "
<< "Call set methods to initialize MapKey.";
}
return (FieldDescriptor::CppType)type_;
}
void SetInt64Value(int64 value) {
SetType(FieldDescriptor::CPPTYPE_INT64);
val_.int64_value_ = value;
}
void SetUInt64Value(uint64 value) {
SetType(FieldDescriptor::CPPTYPE_UINT64);
val_.uint64_value_ = value;
}
void SetInt32Value(int32 value) {
SetType(FieldDescriptor::CPPTYPE_INT32);
val_.int32_value_ = value;
}
void SetUInt32Value(uint32 value) {
SetType(FieldDescriptor::CPPTYPE_UINT32);
val_.uint32_value_ = value;
}
void SetBoolValue(bool value) {
SetType(FieldDescriptor::CPPTYPE_BOOL);
val_.bool_value_ = value;
}
void SetStringValue(std::string val) {
SetType(FieldDescriptor::CPPTYPE_STRING);
*val_.string_value_.get_mutable() = std::move(val);
}
int64 GetInt64Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
return val_.int64_value_;
}
uint64 GetUInt64Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
return val_.uint64_value_;
}
int32 GetInt32Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
return val_.int32_value_;
}
uint32 GetUInt32Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
return val_.uint32_value_;
}
bool GetBoolValue() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
return val_.bool_value_;
}
const std::string& GetStringValue() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
return val_.string_value_.get();
}
bool operator<(const MapKey& other) const {
if (type_ != other.type_) {
// We could define a total order that handles this case, but
// there currently no need. So, for now, fail.
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
}
switch (type()) {
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_MESSAGE:
GOOGLE_LOG(FATAL) << "Unsupported";
return false;
case FieldDescriptor::CPPTYPE_STRING:
return val_.string_value_.get() < other.val_.string_value_.get();
case FieldDescriptor::CPPTYPE_INT64:
return val_.int64_value_ < other.val_.int64_value_;
case FieldDescriptor::CPPTYPE_INT32:
return val_.int32_value_ < other.val_.int32_value_;
case FieldDescriptor::CPPTYPE_UINT64:
return val_.uint64_value_ < other.val_.uint64_value_;
case FieldDescriptor::CPPTYPE_UINT32:
return val_.uint32_value_ < other.val_.uint32_value_;
case FieldDescriptor::CPPTYPE_BOOL:
return val_.bool_value_ < other.val_.bool_value_;
}
return false;
}
bool operator==(const MapKey& other) const {
if (type_ != other.type_) {
// To be consistent with operator<, we don't allow this either.
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
}
switch (type()) {
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_MESSAGE:
GOOGLE_LOG(FATAL) << "Unsupported";
break;
case FieldDescriptor::CPPTYPE_STRING:
return val_.string_value_.get() == other.val_.string_value_.get();
case FieldDescriptor::CPPTYPE_INT64:
return val_.int64_value_ == other.val_.int64_value_;
case FieldDescriptor::CPPTYPE_INT32:
return val_.int32_value_ == other.val_.int32_value_;
case FieldDescriptor::CPPTYPE_UINT64:
return val_.uint64_value_ == other.val_.uint64_value_;
case FieldDescriptor::CPPTYPE_UINT32:
return val_.uint32_value_ == other.val_.uint32_value_;
case FieldDescriptor::CPPTYPE_BOOL:
return val_.bool_value_ == other.val_.bool_value_;
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
void CopyFrom(const MapKey& other) {
SetType(other.type());
switch (type_) {
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_MESSAGE:
GOOGLE_LOG(FATAL) << "Unsupported";
break;
case FieldDescriptor::CPPTYPE_STRING:
*val_.string_value_.get_mutable() = other.val_.string_value_.get();
break;
case FieldDescriptor::CPPTYPE_INT64:
val_.int64_value_ = other.val_.int64_value_;
break;
case FieldDescriptor::CPPTYPE_INT32:
val_.int32_value_ = other.val_.int32_value_;
break;
case FieldDescriptor::CPPTYPE_UINT64:
val_.uint64_value_ = other.val_.uint64_value_;
break;
case FieldDescriptor::CPPTYPE_UINT32:
val_.uint32_value_ = other.val_.uint32_value_;
break;
case FieldDescriptor::CPPTYPE_BOOL:
val_.bool_value_ = other.val_.bool_value_;
break;
}
}
private:
template <typename K, typename V>
friend class internal::TypeDefinedMapFieldBase;
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
friend class internal::DynamicMapField;
union KeyValue {
KeyValue() {}
internal::ExplicitlyConstructed<std::string> string_value_;
int64 int64_value_;
int32 int32_value_;
uint64 uint64_value_;
uint32 uint32_value_;
bool bool_value_;
} val_;
void SetType(FieldDescriptor::CppType type) {
if (type_ == type) return;
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
val_.string_value_.Destruct();
}
type_ = type;
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
val_.string_value_.DefaultConstruct();
}
}
// type_ is 0 or a valid FieldDescriptor::CppType.
int type_;
};
namespace internal { namespace internal {
class ContendedMapCleanTest; class ContendedMapCleanTest;
@ -374,211 +579,6 @@ class PROTOBUF_EXPORT DynamicMapField
} // namespace internal } // namespace internal
#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
if (type() != EXPECTEDTYPE) { \
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" \
<< METHOD << " type does not match\n" \
<< " Expected : " \
<< FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
<< " Actual : " << FieldDescriptor::CppTypeName(type()); \
}
// MapKey is an union type for representing any possible
// map key.
class PROTOBUF_EXPORT MapKey {
public:
MapKey() : type_(0) {}
MapKey(const MapKey& other) : type_(0) { CopyFrom(other); }
MapKey& operator=(const MapKey& other) {
CopyFrom(other);
return *this;
}
~MapKey() {
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
val_.string_value_.Destruct();
}
}
FieldDescriptor::CppType type() const {
if (type_ == 0) {
GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n"
<< "MapKey::type MapKey is not initialized. "
<< "Call set methods to initialize MapKey.";
}
return (FieldDescriptor::CppType)type_;
}
void SetInt64Value(int64 value) {
SetType(FieldDescriptor::CPPTYPE_INT64);
val_.int64_value_ = value;
}
void SetUInt64Value(uint64 value) {
SetType(FieldDescriptor::CPPTYPE_UINT64);
val_.uint64_value_ = value;
}
void SetInt32Value(int32 value) {
SetType(FieldDescriptor::CPPTYPE_INT32);
val_.int32_value_ = value;
}
void SetUInt32Value(uint32 value) {
SetType(FieldDescriptor::CPPTYPE_UINT32);
val_.uint32_value_ = value;
}
void SetBoolValue(bool value) {
SetType(FieldDescriptor::CPPTYPE_BOOL);
val_.bool_value_ = value;
}
void SetStringValue(std::string val) {
SetType(FieldDescriptor::CPPTYPE_STRING);
*val_.string_value_.get_mutable() = std::move(val);
}
int64 GetInt64Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
return val_.int64_value_;
}
uint64 GetUInt64Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
return val_.uint64_value_;
}
int32 GetInt32Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
return val_.int32_value_;
}
uint32 GetUInt32Value() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
return val_.uint32_value_;
}
bool GetBoolValue() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
return val_.bool_value_;
}
const std::string& GetStringValue() const {
TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
return val_.string_value_.get();
}
bool operator<(const MapKey& other) const {
if (type_ != other.type_) {
// We could define a total order that handles this case, but
// there currently no need. So, for now, fail.
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
}
switch (type()) {
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_MESSAGE:
GOOGLE_LOG(FATAL) << "Unsupported";
return false;
case FieldDescriptor::CPPTYPE_STRING:
return val_.string_value_.get() < other.val_.string_value_.get();
case FieldDescriptor::CPPTYPE_INT64:
return val_.int64_value_ < other.val_.int64_value_;
case FieldDescriptor::CPPTYPE_INT32:
return val_.int32_value_ < other.val_.int32_value_;
case FieldDescriptor::CPPTYPE_UINT64:
return val_.uint64_value_ < other.val_.uint64_value_;
case FieldDescriptor::CPPTYPE_UINT32:
return val_.uint32_value_ < other.val_.uint32_value_;
case FieldDescriptor::CPPTYPE_BOOL:
return val_.bool_value_ < other.val_.bool_value_;
}
return false;
}
bool operator==(const MapKey& other) const {
if (type_ != other.type_) {
// To be consistent with operator<, we don't allow this either.
GOOGLE_LOG(FATAL) << "Unsupported: type mismatch";
}
switch (type()) {
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_MESSAGE:
GOOGLE_LOG(FATAL) << "Unsupported";
break;
case FieldDescriptor::CPPTYPE_STRING:
return val_.string_value_.get() == other.val_.string_value_.get();
case FieldDescriptor::CPPTYPE_INT64:
return val_.int64_value_ == other.val_.int64_value_;
case FieldDescriptor::CPPTYPE_INT32:
return val_.int32_value_ == other.val_.int32_value_;
case FieldDescriptor::CPPTYPE_UINT64:
return val_.uint64_value_ == other.val_.uint64_value_;
case FieldDescriptor::CPPTYPE_UINT32:
return val_.uint32_value_ == other.val_.uint32_value_;
case FieldDescriptor::CPPTYPE_BOOL:
return val_.bool_value_ == other.val_.bool_value_;
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return false;
}
void CopyFrom(const MapKey& other) {
SetType(other.type());
switch (type_) {
case FieldDescriptor::CPPTYPE_DOUBLE:
case FieldDescriptor::CPPTYPE_FLOAT:
case FieldDescriptor::CPPTYPE_ENUM:
case FieldDescriptor::CPPTYPE_MESSAGE:
GOOGLE_LOG(FATAL) << "Unsupported";
break;
case FieldDescriptor::CPPTYPE_STRING:
*val_.string_value_.get_mutable() = other.val_.string_value_.get();
break;
case FieldDescriptor::CPPTYPE_INT64:
val_.int64_value_ = other.val_.int64_value_;
break;
case FieldDescriptor::CPPTYPE_INT32:
val_.int32_value_ = other.val_.int32_value_;
break;
case FieldDescriptor::CPPTYPE_UINT64:
val_.uint64_value_ = other.val_.uint64_value_;
break;
case FieldDescriptor::CPPTYPE_UINT32:
val_.uint32_value_ = other.val_.uint32_value_;
break;
case FieldDescriptor::CPPTYPE_BOOL:
val_.bool_value_ = other.val_.bool_value_;
break;
}
}
private:
template <typename K, typename V>
friend class internal::TypeDefinedMapFieldBase;
friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
friend class internal::DynamicMapField;
union KeyValue {
KeyValue() {}
internal::ExplicitlyConstructed<std::string> string_value_;
int64 int64_value_;
int32 int32_value_;
uint64 uint64_value_;
uint32 uint32_value_;
bool bool_value_;
} val_;
void SetType(FieldDescriptor::CppType type) {
if (type_ == type) return;
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
val_.string_value_.Destruct();
}
type_ = type;
if (type_ == FieldDescriptor::CPPTYPE_STRING) {
val_.string_value_.DefaultConstruct();
}
}
// type_ is 0 or a valid FieldDescriptor::CppType.
int type_;
};
// MapValueRef points to a map value. // MapValueRef points to a map value.
class PROTOBUF_EXPORT MapValueRef { class PROTOBUF_EXPORT MapValueRef {
public: public:

@ -1,33 +1,3 @@
// 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.
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved. // Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/ // https://developers.google.com/protocol-buffers/

@ -1,33 +1,3 @@
// 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.
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved. // Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/ // https://developers.google.com/protocol-buffers/

@ -71,21 +71,27 @@ class MockObjectWriter : public ObjectWriter {
public: public:
MockObjectWriter() {} MockObjectWriter() {}
MOCK_METHOD1(StartObject, ObjectWriter*(StringPiece)); MOCK_METHOD(ObjectWriter*, StartObject, (StringPiece), (override));
MOCK_METHOD0(EndObject, ObjectWriter*()); MOCK_METHOD(ObjectWriter*, EndObject, (), (override));
MOCK_METHOD1(StartList, ObjectWriter*(StringPiece)); MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override));
MOCK_METHOD0(EndList, ObjectWriter*()); MOCK_METHOD(ObjectWriter*, EndList, (), (override));
MOCK_METHOD2(RenderBool, ObjectWriter*(StringPiece, bool)); MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override));
MOCK_METHOD2(RenderInt32, ObjectWriter*(StringPiece, int32)); MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32),
MOCK_METHOD2(RenderUint32, ObjectWriter*(StringPiece, uint32)); (override));
MOCK_METHOD2(RenderInt64, ObjectWriter*(StringPiece, int64)); MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32),
MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, uint64)); (override));
MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, double)); MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64),
MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, float)); (override));
MOCK_METHOD2(RenderString, MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64),
ObjectWriter*(StringPiece, StringPiece)); (override));
MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece)); MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double),
MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece)); (override));
MOCK_METHOD(ObjectWriter*, RenderFloat, (StringPiece, float),
(override));
MOCK_METHOD(ObjectWriter*, RenderString,
(StringPiece, StringPiece), (override));
MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece));
MOCK_METHOD(ObjectWriter*, RenderNull, (StringPiece), (override));
}; };
class ExpectingObjectWriter : public ObjectWriter { class ExpectingObjectWriter : public ObjectWriter {

@ -46,14 +46,18 @@ class MockErrorListener : public ErrorListener {
MockErrorListener() {} MockErrorListener() {}
virtual ~MockErrorListener() {} virtual ~MockErrorListener() {}
MOCK_METHOD3(InvalidName, MOCK_METHOD(void, InvalidName,
void(const LocationTrackerInterface& loc, (const LocationTrackerInterface& loc,
StringPiece unknown_name, StringPiece message)); StringPiece unknown_name, StringPiece message),
MOCK_METHOD3(InvalidValue, (override));
void(const LocationTrackerInterface& loc, MOCK_METHOD(void, InvalidValue,
StringPiece type_name, StringPiece value)); (const LocationTrackerInterface& loc, StringPiece type_name,
MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc, StringPiece value),
StringPiece missing_name)); (override));
MOCK_METHOD(void, MissingField,
(const LocationTrackerInterface& loc,
StringPiece missing_name),
(override));
}; };
} // namespace converter } // namespace converter

Loading…
Cancel
Save