diff --git a/Makefile.am b/Makefile.am index 0b58adb8e7..8054f98669 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1236,7 +1236,7 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ python/release/wheel/Dockerfile \ python/release/wheel/protobuf_optimized_pip.sh \ python/release/wheel/README.md \ - six.BUILD \ + third_party/six.BUILD \ third_party/zlib.BUILD \ util/python/BUILD diff --git a/WORKSPACE b/WORKSPACE index 750079d231..35ef1d583c 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -16,13 +16,6 @@ load("//:protobuf_deps.bzl", "protobuf_deps") # Load common dependencies. protobuf_deps() -http_archive( - name = "six", - build_file = "@//:six.BUILD", - sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", - urls = ["https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55"], -) - bind( name = "python_headers", actual = "//util/python:python_headers", diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt index eaa1b612d9..e25629deeb 100644 --- a/conformance/failure_list_php_c.txt +++ b/conformance/failure_list_php_c.txt @@ -58,8 +58,6 @@ Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput Required.Proto3.JsonInput.FloatFieldNan.JsonOutput Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput Required.Proto3.JsonInput.OneofFieldDuplicate -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput -Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput Required.Proto3.JsonInput.RejectTopLevelNull Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c index cc5a54ab84..3484b74779 100644 --- a/php/ext/google/protobuf/upb.c +++ b/php/ext/google/protobuf/upb.c @@ -9964,7 +9964,8 @@ static bool start_any_stringval(upb_json_parser *p) { static bool start_stringval(upb_json_parser *p) { if (is_top_level(p)) { - if (is_string_wrapper_object(p)) { + if (is_string_wrapper_object(p) || + is_number_wrapper_object(p)) { start_wrapper_object(p); } else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) { start_fieldmask_object(p); @@ -9977,7 +9978,8 @@ static bool start_stringval(upb_json_parser *p) { } else { return false; } - } else if (does_string_wrapper_start(p)) { + } else if (does_string_wrapper_start(p) || + does_number_wrapper_start(p)) { if (!start_subobject(p)) { return false; } @@ -10183,7 +10185,8 @@ static bool end_stringval(upb_json_parser *p) { return false; } - if (does_string_wrapper_end(p)) { + if (does_string_wrapper_end(p) || + does_number_wrapper_end(p)) { end_wrapper_object(p); if (!is_top_level(p)) { end_subobject(p); diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php index 5b373bb07e..f2a50180c6 100644 --- a/php/tests/encode_decode_test.php +++ b/php/tests/encode_decode_test.php @@ -118,12 +118,19 @@ class EncodeDecodeTest extends TestBase $this->assertEquals(1, $m->getValue()); } - # public function testEncodeTopLevelInt64Value() - # { - # $m = new Int64Value(); - # $m->setValue(1); - # $this->assertSame("\"1\"", $m->serializeToJsonString()); - # } + public function testDecodeTopLevelInt64ValueAsString() + { + $m = new Int64Value(); + $m->mergeFromJsonString("\"1\""); + $this->assertEquals(1, $m->getValue()); + } + + public function testEncodeTopLevelInt64Value() + { + $m = new Int64Value(); + $m->setValue(1); + $this->assertSame("\"1\"", $m->serializeToJsonString()); + } public function testDecodeTopLevelUInt64Value() { @@ -132,12 +139,19 @@ class EncodeDecodeTest extends TestBase $this->assertEquals(1, $m->getValue()); } - # public function testEncodeTopLevelUInt64Value() - # { - # $m = new UInt64Value(); - # $m->setValue(1); - # $this->assertSame("\"1\"", $m->serializeToJsonString()); - # } + public function testDecodeTopLevelUInt64ValueAsString() + { + $m = new UInt64Value(); + $m->mergeFromJsonString("\"1\""); + $this->assertEquals(1, $m->getValue()); + } + + public function testEncodeTopLevelUInt64Value() + { + $m = new UInt64Value(); + $m->setValue(1); + $this->assertSame("\"1\"", $m->serializeToJsonString()); + } public function testDecodeTopLevelStringValue() { diff --git a/protobuf_deps.bzl b/protobuf_deps.bzl index d7a3a9754a..e5117d167d 100644 --- a/protobuf_deps.bzl +++ b/protobuf_deps.bzl @@ -25,9 +25,9 @@ def protobuf_deps(): if not native.existing_rule("six"): http_archive( name = "six", - build_file = "@//:six.BUILD", - sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", - urls = ["https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55"], + build_file = "@com_google_protobuf//:third_party/six.BUILD", + sha256 = "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73", + urls = ["https://pypi.python.org/packages/source/s/six/six-1.12.0.tar.gz"], ) if not native.existing_rule("rules_cc"): diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index 63dac7fe1f..dd1c2d8317 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -2231,6 +2231,27 @@ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) { VALUE args[3] = { c_only_cookie, _descriptor_pool, key }; def = rb_class_new_instance(3, args, klass); rb_hash_aset(descriptor_pool->def_to_descriptor, key, def); + + // For message defs, we now eagerly get/create descriptors for all + // submessages. We will need these anyway to parse or serialize this + // message type. But more importantly, we must do this now so that + // add_handlers_for_message() (which calls get_msgdef_obj()) does *not* + // need to create a Ruby object or insert into a Ruby Hash. We need to + // avoid triggering GC, which can switch Ruby threads and re-enter our + // C extension from a different thread. This wreaks havoc on our state + // if we were in the middle of building handlers. + if (klass == cDescriptor) { + const upb_msgdef *m = ptr; + upb_msg_field_iter it; + for (upb_msg_field_begin(&it, m); + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + if (upb_fielddef_issubmsg(f)) { + get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f)); + } + } + } } return def; diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 3bf6b924d9..6eb01f7c30 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -155,6 +155,9 @@ static const void *newoneofhandlerdata(upb_handlers *h, // create a separate ID space. In addition, using the field tag number here // lets us easily look up the field in the oneof accessor. hd->oneof_case_num = upb_fielddef_number(f); + if (is_value_field(f)) { + hd->oneof_case_num |= ONEOF_CASE_MASK; + } hd->subklass = field_type_class(desc->layout, f); upb_handlers_addcleanup(h, hd, xfree); return hd; @@ -706,12 +709,13 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) { !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); + const upb_oneofdef *oneof = upb_fielddef_containingoneof(f); size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader); - if (upb_fielddef_containingoneof(f)) { + if (oneof) { size_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset + + desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset + sizeof(MessageHeader); add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc); } else if (is_map_field(f)) { @@ -1256,19 +1260,18 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); + const upb_oneofdef *oneof = upb_fielddef_containingoneof(f); bool is_matching_oneof = false; uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader); - if (upb_fielddef_containingoneof(f)) { - uint32_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset + - sizeof(MessageHeader); + if (oneof) { + uint32_t oneof_case = + slot_read_oneof_case(desc->layout, Message_data(msg), oneof); // For a oneof, check that this field is actually present -- skip all the // below if not. - if (DEREF(msg, oneof_case_offset, uint32_t) != - upb_fielddef_number(f)) { + if (oneof_case != upb_fielddef_number(f)) { continue; } // Otherwise, fall through to the appropriate singular-field handler @@ -1464,18 +1467,17 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { upb_fielddef *f = upb_msg_iter_field(&it); + const upb_oneofdef *oneof = upb_fielddef_containingoneof(f); uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader); - if (upb_fielddef_containingoneof(f)) { - uint32_t oneof_case_offset = - desc->layout->fields[upb_fielddef_index(f)].case_offset + - sizeof(MessageHeader); + if (oneof) { + uint32_t oneof_case = + slot_read_oneof_case(desc->layout, Message_data(msg), oneof); // For a oneof, check that this field is actually present -- skip all the // below if not. - if (DEREF(msg, oneof_case_offset, uint32_t) != - upb_fielddef_number(f)) { + if (oneof_case != upb_fielddef_number(f)) { continue; } // Otherwise, fall through to the appropriate singular-field handler diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index 5b64374cdb..2ba7b2fe47 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -86,27 +86,11 @@ VALUE Message_alloc(VALUE klass) { } static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) { - upb_oneof_iter it; - size_t case_ofs; uint32_t oneof_case; - const upb_fielddef* first_field; const upb_fielddef* f; - // If no fields in the oneof, always nil. - if (upb_oneofdef_numfields(o) == 0) { - return NULL; - } - // Grab the first field in the oneof so we can get its layout info to find the - // oneof_case field. - upb_oneof_begin(&it, o); - assert(!upb_oneof_done(&it)); - first_field = upb_oneof_iter_field(&it); - assert(upb_fielddef_containingoneof(first_field) != NULL); - - case_ofs = - self->descriptor->layout-> - fields[upb_fielddef_index(first_field)].case_offset; - oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs)); + oneof_case = + slot_read_oneof_case(self->descriptor->layout, Message_data(self), o); if (oneof_case == ONEOF_CASE_NONE) { return NULL; diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index 84e9e7fd2f..5176d59f0c 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -59,6 +59,7 @@ typedef struct OneofDescriptor OneofDescriptor; typedef struct EnumDescriptor EnumDescriptor; typedef struct MessageLayout MessageLayout; typedef struct MessageField MessageField; +typedef struct MessageOneof MessageOneof; typedef struct MessageHeader MessageHeader; typedef struct MessageBuilderContext MessageBuilderContext; typedef struct OneofBuilderContext OneofBuilderContext; @@ -367,6 +368,9 @@ bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2); VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value); void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value); +uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage, + const upb_oneofdef* oneof); +bool is_value_field(const upb_fielddef* f); extern rb_encoding* kRubyStringUtf8Encoding; extern rb_encoding* kRubyStringASCIIEncoding; @@ -496,13 +500,16 @@ VALUE Map_iter_value(Map_iter* iter); // Message layout / storage. // ----------------------------------------------------------------------------- -#define MESSAGE_FIELD_NO_CASE ((size_t)-1) -#define MESSAGE_FIELD_NO_HASBIT ((size_t)-1) +#define MESSAGE_FIELD_NO_HASBIT ((uint32_t)-1) struct MessageField { - size_t offset; - size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE. - size_t hasbit; + uint32_t offset; + uint32_t hasbit; +}; + +struct MessageOneof { + uint32_t offset; + uint32_t case_offset; }; // MessageLayout is owned by the enclosing Descriptor, which must outlive us. @@ -511,10 +518,15 @@ struct MessageLayout { const upb_msgdef* msgdef; void* empty_template; // Can memcpy() onto a layout to clear it. MessageField* fields; - size_t size; + MessageOneof* oneofs; + uint32_t size; + uint32_t value_offset; + int value_count; }; -void create_layout(Descriptor* desc); +#define ONEOF_CASE_MASK 0x80000000 + +MessageLayout* create_layout(Descriptor* desc); void free_layout(MessageLayout* layout); bool field_contains_hasbit(MessageLayout* layout, const upb_fielddef* field); diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c index 375b939598..ad76e4f87a 100644 --- a/ruby/ext/google/protobuf_c/storage.c +++ b/ruby/ext/google/protobuf_c/storage.c @@ -473,10 +473,16 @@ static size_t align_up_to(size_t offset, size_t granularity) { return (offset + granularity - 1) & ~(granularity - 1); } -void create_layout(Descriptor* desc) { +bool is_value_field(const upb_fielddef* f) { + return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) || + upb_fielddef_isstring(f); +} + +MessageLayout* create_layout(Descriptor* desc) { const upb_msgdef *msgdef = desc->msgdef; MessageLayout* layout = ALLOC(MessageLayout); int nfields = upb_msgdef_numfields(msgdef); + int noneofs = upb_msgdef_numoneofs(msgdef); upb_msg_field_iter it; upb_msg_oneof_iter oit; size_t off = 0; @@ -487,6 +493,11 @@ void create_layout(Descriptor* desc) { desc->layout = layout; layout->fields = ALLOC_N(MessageField, nfields); + layout->oneofs = NULL; + + if (noneofs > 0) { + layout->oneofs = ALLOC_N(MessageOneof, noneofs); + } for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it); @@ -504,29 +515,41 @@ void create_layout(Descriptor* desc) { off += (hasbit + 8 - 1) / 8; } + off = align_up_to(off, sizeof(VALUE)); + layout->value_offset = off; + layout->value_count = 0; + + // Place all (non-oneof) VALUE fields first. + for (upb_msg_field_begin(&it, msgdef); + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* field = upb_msg_iter_field(&it); + if (upb_fielddef_containingoneof(field) || !is_value_field(field)) { + continue; + } + + layout->fields[upb_fielddef_index(field)].offset = off; + off += sizeof(VALUE); + layout->value_count++; + } + + // Now place all other (non-oneof) fields. for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); size_t field_size; - if (upb_fielddef_containingoneof(field)) { - // Oneofs are handled separately below. + if (upb_fielddef_containingoneof(field) || is_value_field(field)) { continue; } // Allocate |field_size| bytes for this field in the layout. - field_size = 0; - if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - field_size = sizeof(VALUE); - } else { - field_size = native_slot_size(upb_fielddef_type(field)); - } + field_size = native_slot_size(upb_fielddef_type(field)); + // Align current offset up to |size| granularity. off = align_up_to(off, field_size); layout->fields[upb_fielddef_index(field)].offset = off; - layout->fields[upb_fielddef_index(field)].case_offset = - MESSAGE_FIELD_NO_CASE; off += field_size; } @@ -560,6 +583,7 @@ void create_layout(Descriptor* desc) { upb_oneof_next(&fit)) { const upb_fielddef* field = upb_oneof_iter_field(&fit); layout->fields[upb_fielddef_index(field)].offset = off; + layout->oneofs[upb_oneofdef_index(oneof)].offset = off; } off += field_size; } @@ -569,18 +593,10 @@ void create_layout(Descriptor* desc) { !upb_msg_oneof_done(&oit); upb_msg_oneof_next(&oit)) { const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); - upb_oneof_iter fit; - size_t field_size = sizeof(uint32_t); // Align the offset. off = (off + field_size - 1) & ~(field_size - 1); - // Assign all fields in the oneof this same offset. - for (upb_oneof_begin(&fit, oneof); - !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* field = upb_oneof_iter_field(&fit); - layout->fields[upb_fielddef_index(field)].case_offset = off; - } + layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off; off += field_size; } @@ -601,6 +617,7 @@ void create_layout(Descriptor* desc) { void free_layout(MessageLayout* layout) { xfree(layout->empty_template); xfree(layout->fields); + xfree(layout->oneofs); xfree(layout); } @@ -627,9 +644,15 @@ static void* slot_memory(MessageLayout* layout, static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage, - const upb_fielddef* field) { - return (uint32_t *)(((uint8_t *)storage) + - layout->fields[upb_fielddef_index(field)].case_offset); + const upb_oneofdef* oneof) { + return (uint32_t*)(((uint8_t*)storage) + + layout->oneofs[upb_oneofdef_index(oneof)].case_offset); +} + +uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage, + const upb_oneofdef* oneof) { + uint32_t* ptr = slot_oneof_case(layout, storage, oneof); + return *ptr & ~ONEOF_CASE_MASK; } static void slot_set_hasbit(MessageLayout* layout, @@ -672,13 +695,14 @@ void layout_clear(MessageLayout* layout, const void* storage, const upb_fielddef* field) { void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); if (field_contains_hasbit(layout, field)) { slot_clear_hasbit(layout, storage, field); } - if (upb_fielddef_containingoneof(field)) { + if (oneof) { + uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof); memset(memory, 0, NATIVE_SLOT_MAX_SIZE); *oneof_case = ONEOF_CASE_NONE; } else if (is_map_field(field)) { @@ -764,8 +788,7 @@ VALUE layout_get(MessageLayout* layout, const void* storage, const upb_fielddef* field) { void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); - + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); bool field_set; if (field_contains_hasbit(layout, field)) { field_set = slot_is_hasbit_set(layout, storage, field); @@ -773,8 +796,9 @@ VALUE layout_get(MessageLayout* layout, field_set = true; } - if (upb_fielddef_containingoneof(field)) { - if (*oneof_case != upb_fielddef_number(field)) { + if (oneof) { + uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof); + if (oneof_case != upb_fielddef_number(field)) { return layout_get_default(field); } return native_slot_get(upb_fielddef_type(field), @@ -837,9 +861,10 @@ void layout_set(MessageLayout* layout, const upb_fielddef* field, VALUE val) { void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); - if (upb_fielddef_containingoneof(field)) { + if (oneof) { + uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof); if (val == Qnil) { // Assigning nil to a oneof field clears the oneof completely. *oneof_case = ONEOF_CASE_NONE; @@ -857,11 +882,14 @@ void layout_set(MessageLayout* layout, // sync with the value slot whenever the Ruby VM has been called. Thus, we // use native_slot_set_value_and_case(), which ensures that both the value // and case number are altered atomically (w.r.t. the Ruby VM). + uint32_t case_value = upb_fielddef_number(field); + if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) { + case_value |= ONEOF_CASE_MASK; + } + native_slot_set_value_and_case( - upb_fielddef_name(field), - upb_fielddef_type(field), field_type_class(layout, field), - memory, val, - oneof_case, upb_fielddef_number(field)); + upb_fielddef_name(field), upb_fielddef_type(field), + field_type_class(layout, field), memory, val, oneof_case, case_value); } } else if (is_map_field(field)) { check_map_field_type(layout, val, field); @@ -893,22 +921,19 @@ void layout_init(MessageLayout* layout, void* storage) { } void layout_mark(MessageLayout* layout, void* storage) { - upb_msg_field_iter it; - for (upb_msg_field_begin(&it, layout->msgdef); - !upb_msg_field_done(&it); - upb_msg_field_next(&it)) { - const upb_fielddef* field = upb_msg_iter_field(&it); - void* memory = slot_memory(layout, storage, field); - uint32_t* oneof_case = slot_oneof_case(layout, storage, field); + VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset); + int noneofs = upb_msgdef_numoneofs(layout->msgdef); + int i; - if (upb_fielddef_containingoneof(field)) { - if (*oneof_case == upb_fielddef_number(field)) { - native_slot_mark(upb_fielddef_type(field), memory); - } - } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { - rb_gc_mark(DEREF(memory, VALUE)); - } else { - native_slot_mark(upb_fielddef_type(field), memory); + for (i = 0; i < layout->value_count; i++) { + rb_gc_mark(values[i]); + } + + for (i = 0; i < noneofs; i++) { + MessageOneof* oneof = &layout->oneofs[i]; + uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset); + if (*case_ptr & ONEOF_CASE_MASK) { + rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE)); } } } @@ -919,14 +944,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); void* to_memory = slot_memory(layout, to, field); - uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); void* from_memory = slot_memory(layout, from, field); - uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); - if (upb_fielddef_containingoneof(field)) { - if (*from_oneof_case == upb_fielddef_number(field)) { + if (oneof) { + uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof); + uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof); + if (slot_read_oneof_case(layout, from, oneof) == + upb_fielddef_number(field)) { *to_oneof_case = *from_oneof_case; native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); } @@ -951,14 +978,16 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); void* to_memory = slot_memory(layout, to, field); - uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); void* from_memory = slot_memory(layout, from, field); - uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); - if (upb_fielddef_containingoneof(field)) { - if (*from_oneof_case == upb_fielddef_number(field)) { + if (oneof) { + uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof); + uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof); + if (slot_read_oneof_case(layout, from, oneof) == + upb_fielddef_number(field)) { *to_oneof_case = *from_oneof_case; native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); } @@ -985,17 +1014,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); + const upb_oneofdef* oneof = upb_fielddef_containingoneof(field); void* msg1_memory = slot_memory(layout, msg1, field); - uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field); void* msg2_memory = slot_memory(layout, msg2, field); - uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field); - if (upb_fielddef_containingoneof(field)) { + if (oneof) { + uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof); + uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof); if (*msg1_oneof_case != *msg2_oneof_case || - (*msg1_oneof_case == upb_fielddef_number(field) && - !native_slot_eq(upb_fielddef_type(field), - msg1_memory, + (slot_read_oneof_case(layout, msg1, oneof) == + upb_fielddef_number(field) && + !native_slot_eq(upb_fielddef_type(field), msg1_memory, msg2_memory))) { return Qfalse; } @@ -1011,9 +1041,8 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { } } else { if (slot_is_hasbit_set(layout, msg1, field) != - slot_is_hasbit_set(layout, msg2, field) || - !native_slot_eq(upb_fielddef_type(field), - msg1_memory, msg2_memory)) { + slot_is_hasbit_set(layout, msg2, field) || + !native_slot_eq(upb_fielddef_type(field), msg1_memory, msg2_memory)) { return Qfalse; } } diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 620e187b60..4a678d5e66 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -75,6 +75,8 @@ namespace protobuf { class Arena; // defined below class Message; // defined in message.h class MessageLite; +template +class Map; namespace arena_metrics { diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index f0684a6f7f..50c2c9766d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -297,7 +297,7 @@ uint GetGroupEndTag(const Descriptor* descriptor) { std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { std::string result = GetFileNamespace(file); - if (result != "") { + if (!result.empty()) { result += '.'; } string classname; diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc index c481f1400c..ec816a7584 100644 --- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc @@ -261,6 +261,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript // Fields if (descriptor->field_count() > 0) { std::vector fields; + fields.reserve(descriptor->field_count()); for (int i = 0; i < descriptor->field_count(); i++) { fields.push_back(GetPropertyName(descriptor->field(i))); } @@ -273,6 +274,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript // Oneofs if (descriptor->oneof_decl_count() > 0) { std::vector oneofs; + oneofs.reserve(descriptor->oneof_decl_count()); for (int i = 0; i < descriptor->oneof_decl_count(); i++) { oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); } @@ -285,6 +287,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript // Nested enums if (descriptor->enum_type_count() > 0) { std::vector enums; + enums.reserve(descriptor->enum_type_count()); for (int i = 0; i < descriptor->enum_type_count(); i++) { enums.push_back(GetClassName(descriptor->enum_type(i))); } diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 4a1403f94f..29a5ac2642 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -88,7 +88,6 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file, std::string LabelForField(FieldDescriptor* field); std::string TypeName(FieldDescriptor* field); std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter); -std::string EscapeDollor(const string& to_escape); std::string BinaryToHex(const string& binary); void Indent(io::Printer* printer); void Outdent(io::Printer* printer); @@ -153,7 +152,7 @@ template std::string ClassNamePrefix(const string& classname, const DescriptorType* desc) { const string& prefix = (desc->file()->options()).php_class_prefix(); - if (prefix != "") { + if (!prefix.empty()) { return prefix; } @@ -244,13 +243,13 @@ template std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) { if (desc->file()->options().has_php_namespace()) { const string& php_namespace = desc->file()->options().php_namespace(); - if (php_namespace != "") { + if (!php_namespace.empty()) { return php_namespace; } return ""; } - if (desc->file()->package() != "") { + if (!desc->file()->package().empty()) { return PhpName(desc->file()->package(), is_descriptor); } return ""; @@ -260,7 +259,7 @@ template std::string FullClassName(const DescriptorType* desc, bool is_descriptor) { string classname = GeneratedClassNameImpl(desc); string php_namespace = RootPhpNamespace(desc, is_descriptor); - if (php_namespace != "") { + if (!php_namespace.empty()) { return php_namespace + "\\" + classname; } return classname; @@ -270,7 +269,7 @@ template std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) { string classname = LegacyGeneratedClassName(desc); string php_namespace = RootPhpNamespace(desc, is_descriptor); - if (php_namespace != "") { + if (!php_namespace.empty()) { return php_namespace + "\\" + classname; } return classname; @@ -352,7 +351,7 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file, if (file->options().has_php_metadata_namespace()) { const string& php_metadata_namespace = file->options().php_metadata_namespace(); - if (php_metadata_namespace != "" && php_metadata_namespace != "\\") { + if (!php_metadata_namespace.empty() && php_metadata_namespace != "\\") { result += php_metadata_namespace; std::replace(result.begin(), result.end(), '\\', '/'); if (result.at(result.size() - 1) != '/') { @@ -552,45 +551,41 @@ std::string EnumOrMessageSuffix( // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -std::string UnderscoresToCamelCase(const string& input, bool cap_first_letter) { +std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter) { std::string result; - for (int i = 0; i < input.size(); i++) { - if ('a' <= input[i] && input[i] <= 'z') { + for (int i = 0; i < name.size(); i++) { + if ('a' <= name[i] && name[i] <= 'z') { if (cap_first_letter) { - result += input[i] + ('A' - 'a'); + result += name[i] + ('A' - 'a'); } else { - result += input[i]; + result += name[i]; } cap_first_letter = false; - } else if ('A' <= input[i] && input[i] <= 'Z') { + } else if ('A' <= name[i] && name[i] <= 'Z') { if (i == 0 && !cap_first_letter) { // Force first letter to lower-case unless explicitly told to // capitalize it. - result += input[i] + ('a' - 'A'); + result += name[i] + ('a' - 'A'); } else { // Capital letters after the first are left as-is. - result += input[i]; + result += name[i]; } cap_first_letter = false; - } else if ('0' <= input[i] && input[i] <= '9') { - result += input[i]; + } else if ('0' <= name[i] && name[i] <= '9') { + result += name[i]; cap_first_letter = true; } else { cap_first_letter = true; } } // Add a trailing "_" if the name should be altered. - if (input[input.size() - 1] == '#') { + if (name[name.size() - 1] == '#') { result += '_'; } return result; } -std::string EscapeDollor(const string& to_escape) { - return StringReplace(to_escape, "$", "\\$", true); -} - -std::string BinaryToHex(const string& src) { +std::string BinaryToHex(const string& binary) { string dest; size_t i; unsigned char symbol[16] = { @@ -600,12 +595,12 @@ std::string BinaryToHex(const string& src) { 'c', 'd', 'e', 'f', }; - dest.resize(src.size() * 2); + dest.resize(binary.size() * 2); char* append_ptr = &dest[0]; - for (i = 0; i < src.size(); i++) { - *append_ptr++ = symbol[(src[i] & 0xf0) >> 4]; - *append_ptr++ = symbol[src[i] & 0x0f]; + for (i = 0; i < binary.size(); i++) { + *append_ptr++ = symbol[(binary[i] & 0xf0) >> 4]; + *append_ptr++ = symbol[binary[i] & 0x0f]; } return dest; @@ -1103,7 +1098,7 @@ void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* d GenerateHead(file, &printer); std::string php_namespace = RootPhpNamespace(desc, is_descriptor); - if (php_namespace != "") { + if (!php_namespace.empty()) { printer.Print( "namespace ^name^;\n\n", "name", php_namespace); diff --git a/six.BUILD b/third_party/six.BUILD similarity index 64% rename from six.BUILD rename to third_party/six.BUILD index fb0b3604cd..88c75520de 100644 --- a/six.BUILD +++ b/third_party/six.BUILD @@ -1,13 +1,13 @@ genrule( name = "copy_six", - srcs = ["six-1.10.0/six.py"], - outs = ["six.py"], + srcs = ["six-1.12.0/six.py"], + outs = ["__init__.py"], cmd = "cp $< $(@)", ) py_library( name = "six", - srcs = ["six.py"], + srcs = ["__init__.py"], srcs_version = "PY2AND3", visibility = ["//visibility:public"], )