diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | bindings/lua/upb.c | 2 | ||||
-rw-r--r-- | tests/test_decoder.cc | 135 | ||||
-rw-r--r-- | tests/test_vs_proto2.cc | 3 | ||||
-rwxr-xr-x | upb/descriptor/descriptor.upb.c | 80 | ||||
-rwxr-xr-x | upb/descriptor/descriptor.upb.h | 122 | ||||
-rw-r--r-- | upb/descriptor/reader.c | 166 | ||||
-rw-r--r-- | upb/descriptor/reader.h | 4 | ||||
-rw-r--r-- | upb/google/proto1.cc | 147 | ||||
-rw-r--r-- | upb/google/proto2.cc | 249 | ||||
-rw-r--r-- | upb/handlers-inl.h | 470 | ||||
-rw-r--r-- | upb/handlers.c | 563 | ||||
-rw-r--r-- | upb/handlers.h | 1007 | ||||
-rw-r--r-- | upb/pb/decoder.c | 54 | ||||
-rw-r--r-- | upb/pb/decoder.h | 4 | ||||
-rw-r--r-- | upb/pb/decoder_x64.dasc | 201 | ||||
-rw-r--r-- | upb/pb/glue.c | 4 | ||||
-rw-r--r-- | upb/pb/textprinter.c | 51 | ||||
-rw-r--r-- | upb/shim/shim.c | 69 | ||||
-rw-r--r-- | upb/shim/shim.h | 74 | ||||
-rw-r--r-- | upb/sink.c | 179 | ||||
-rw-r--r-- | upb/sink.h | 172 | ||||
-rw-r--r-- | upb/table.h | 1 | ||||
-rw-r--r-- | upb/upb.h | 35 |
24 files changed, 1937 insertions, 1856 deletions
@@ -90,6 +90,7 @@ CORE= \ upb/google/proto2.cc \ upb/handlers.c \ upb/refcounted.c \ + upb/shim/shim.c \ upb/sink.c \ upb/symtab.c \ upb/table.c \ diff --git a/bindings/lua/upb.c b/bindings/lua/upb.c index 29de9f0..6768aee 100644 --- a/bindings/lua/upb.c +++ b/bindings/lua/upb.c @@ -486,7 +486,7 @@ static int lupb_fielddef_default(lua_State *L) { static int lupb_fielddef_getsel(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); upb_selector_t sel; - if (upb_getselector(f, luaL_checknumber(L, 2), &sel)) { + if (upb_handlers_getselector(f, luaL_checknumber(L, 2), &sel)) { lua_pushnumber(L, sel); return 1; } else { diff --git a/tests/test_decoder.cc b/tests/test_decoder.cc index 1f0e87e..8b62e29 100644 --- a/tests/test_decoder.cc +++ b/tests/test_decoder.cc @@ -188,10 +188,8 @@ void indentbuf(buffer *buf, int depth) { } #define NUMERIC_VALUE_HANDLER(member, ctype, fmt) \ - bool value_ ## member(const upb::SinkFrame *frame, ctype val) { \ - int *depth = (int*)frame->userdata(); \ + bool value_ ## member(int* depth, const uint32_t* num, ctype val) { \ indentbuf(&output, *depth); \ - uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); \ output.appendf("%" PRIu32 ":%" fmt "\n", *num, val); \ return true; \ } @@ -203,74 +201,68 @@ NUMERIC_VALUE_HANDLER(int64, int64_t, PRId64) NUMERIC_VALUE_HANDLER(float, float, "g") NUMERIC_VALUE_HANDLER(double, double, "g") -bool value_bool(const upb::SinkFrame *frame, bool val) { - int *depth = (int*)frame->userdata(); +bool value_bool(int* depth, const uint32_t* num, bool val) { indentbuf(&output, *depth); - uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":%s\n", *num, val ? "true" : "false"); return true; } -void* startstr(const upb::SinkFrame* frame, size_t size_hint) { - int *depth = (int*)frame->userdata(); +int* startstr(int* depth, const uint32_t* num, size_t size_hint) { indentbuf(&output, *depth); - uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":(%zu)\"", *num, size_hint); return depth + 1; } -size_t value_string(const upb::SinkFrame* frame, const char* buf, size_t n) { +size_t value_string(int* depth, const uint32_t* num, const char* buf, + size_t n) { + UPB_UNUSED(num); output.append(buf, n); return n; } -bool endstr(const upb::SinkFrame* frame) { +bool endstr(int* depth, const uint32_t* num) { + UPB_UNUSED(depth); + UPB_UNUSED(num); output.append("\"\n"); return true; } -void* startsubmsg(const upb::SinkFrame* frame) { - int *depth = (int*)frame->userdata(); +int* startsubmsg(int* depth, const uint32_t* num) { indentbuf(&output, *depth); - uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":{\n", *num); return depth + 1; } -bool endsubmsg(const upb::SinkFrame* frame) { - int *depth = (int*)frame->userdata(); +bool endsubmsg(int* depth, const uint32_t* num) { + UPB_UNUSED(num); indentbuf(&output, *depth); output.append("}\n"); return true; } -void* startseq(const upb::SinkFrame* frame) { - int *depth = (int*)frame->userdata(); +int* startseq(int* depth, const uint32_t* num) { indentbuf(&output, *depth); - uint32_t *num = static_cast<uint32_t*>(frame->handler_data()); output.appendf("%" PRIu32 ":[\n", *num); return depth + 1; } -bool endseq(const upb::SinkFrame* frame) { - int *depth = (int*)frame->userdata(); +bool endseq(int* depth, const uint32_t* num) { + UPB_UNUSED(num); indentbuf(&output, *depth); output.append("]\n"); return true; } -bool startmsg(const upb::SinkFrame* frame) { - int *depth = (int*)frame->userdata(); +bool startmsg(int* depth) { indentbuf(&output, *depth); output.append("<\n"); return true; } -void endmsg(const upb::SinkFrame* frame, upb_status* status) { - (void)status; - int *depth = (int*)frame->userdata(); +bool endmsg(int* depth, upb_status* status) { indentbuf(&output, *depth); output.append(">\n"); + return true; } void free_uint32(void *val) { @@ -278,17 +270,14 @@ void free_uint32(void *val) { delete u32; } -template<class T> -void doreg(upb_handlers *h, uint32_t num, - typename upb::Handlers::Value<T>::Handler *handler) { +template<class T, bool F(int*, const uint32_t*, T)> +void doreg(upb_handlers *h, uint32_t num) { const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); ASSERT(f); - ASSERT(h->SetValueHandler<T>(f, handler, new uint32_t(num), free_uint32)); + ASSERT(h->SetValueHandler<T>(f, UpbBindT(F, new uint32_t(num)))); if (f->IsSequence()) { - ASSERT(h->SetStartSequenceHandler( - f, &startseq, new uint32_t(num), free_uint32)); - ASSERT(h->SetEndSequenceHandler( - f, &endseq, new uint32_t(num), free_uint32)); + ASSERT(h->SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); + ASSERT(h->SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); } } @@ -301,68 +290,58 @@ uint32_t rep_fn(uint32_t fn) { #define NOP_FIELD 40 #define UNKNOWN_FIELD 666 -template <class T> -void reg(upb_handlers *h, upb_descriptortype_t type, - typename upb::Handlers::Value<T>::Handler *handler) { +template <class T, bool F(int*, const uint32_t*, T)> +void reg(upb_handlers *h, upb_descriptortype_t type) { // We register both a repeated and a non-repeated field for every type. // For the non-repeated field we make the field number the same as the // type. For the repeated field we make it a function of the type. - doreg<T>(h, type, handler); - doreg<T>(h, rep_fn(type), handler); + doreg<T, F>(h, type); + doreg<T, F>(h, rep_fn(type)); +} + +void regseq(upb::Handlers* h, const upb::FieldDef* f, uint32_t num) { + ASSERT(h->SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); + ASSERT(h->SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); } void reg_subm(upb_handlers *h, uint32_t num) { const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); ASSERT(f); - if (f->IsSequence()) { - ASSERT(h->SetStartSequenceHandler( - f, &startseq, new uint32_t(num), free_uint32)); - ASSERT(h->SetEndSequenceHandler( - f, &endseq, new uint32_t(num), free_uint32)); - } - ASSERT(h->SetStartSubMessageHandler( - f, &startsubmsg, new uint32_t(num), free_uint32)); - ASSERT(h->SetEndSubMessageHandler( - f, &endsubmsg, new uint32_t(num), free_uint32)); + if (f->IsSequence()) regseq(h, f, num); + ASSERT( + h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, new uint32_t(num)))); + ASSERT(h->SetEndSubMessageHandler(f, UpbBind(endsubmsg, new uint32_t(num)))); ASSERT(upb_handlers_setsubhandlers(h, f, h)); } void reg_str(upb_handlers *h, uint32_t num) { const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); ASSERT(f); - if (f->IsSequence()) { - ASSERT(h->SetStartSequenceHandler( - f, &startseq, new uint32_t(num), free_uint32)); - ASSERT(h->SetEndSequenceHandler( - f, &endseq, new uint32_t(num), free_uint32)); - } - ASSERT(h->SetStartStringHandler( - f, &startstr, new uint32_t(num), free_uint32)); - ASSERT(h->SetEndStringHandler( - f, &endstr, new uint32_t(num), free_uint32)); - ASSERT(h->SetStringHandler( - f, &value_string, new uint32_t(num), free_uint32)); + if (f->IsSequence()) regseq(h, f, num); + ASSERT(h->SetStartStringHandler(f, UpbBind(startstr, new uint32_t(num)))); + ASSERT(h->SetEndStringHandler(f, UpbBind(endstr, new uint32_t(num)))); + ASSERT(h->SetStringHandler(f, UpbBind(value_string, new uint32_t(num)))); } void reghandlers(upb_handlers *h) { - upb_handlers_setstartmsg(h, &startmsg); - upb_handlers_setendmsg(h, &endmsg); + h->SetStartMessageHandler<int, startmsg>(); + h->SetEndMessageHandler<int, endmsg>(); // Register handlers for each type. - reg<double> (h, UPB_DESCRIPTOR_TYPE_DOUBLE, &value_double); - reg<float> (h, UPB_DESCRIPTOR_TYPE_FLOAT, &value_float); - reg<int64_t> (h, UPB_DESCRIPTOR_TYPE_INT64, &value_int64); - reg<uint64_t>(h, UPB_DESCRIPTOR_TYPE_UINT64, &value_uint64); - reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_INT32 , &value_int32); - reg<uint64_t>(h, UPB_DESCRIPTOR_TYPE_FIXED64, &value_uint64); - reg<uint32_t>(h, UPB_DESCRIPTOR_TYPE_FIXED32, &value_uint32); - reg<bool> (h, UPB_DESCRIPTOR_TYPE_BOOL, &value_bool); - reg<uint32_t>(h, UPB_DESCRIPTOR_TYPE_UINT32, &value_uint32); - reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_ENUM, &value_int32); - reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_SFIXED32, &value_int32); - reg<int64_t> (h, UPB_DESCRIPTOR_TYPE_SFIXED64, &value_int64); - reg<int32_t> (h, UPB_DESCRIPTOR_TYPE_SINT32, &value_int32); - reg<int64_t> (h, UPB_DESCRIPTOR_TYPE_SINT64, &value_int64); + reg<double, value_double>(h, UPB_DESCRIPTOR_TYPE_DOUBLE); + reg<float, value_float> (h, UPB_DESCRIPTOR_TYPE_FLOAT); + reg<int64_t, value_int64> (h, UPB_DESCRIPTOR_TYPE_INT64); + reg<uint64_t, value_uint64>(h, UPB_DESCRIPTOR_TYPE_UINT64); + reg<int32_t, value_int32> (h, UPB_DESCRIPTOR_TYPE_INT32); + reg<uint64_t, value_uint64>(h, UPB_DESCRIPTOR_TYPE_FIXED64); + reg<uint32_t, value_uint32>(h, UPB_DESCRIPTOR_TYPE_FIXED32); + reg<bool, value_bool> (h, UPB_DESCRIPTOR_TYPE_BOOL); + reg<uint32_t, value_uint32>(h, UPB_DESCRIPTOR_TYPE_UINT32); + reg<int32_t, value_int32> (h, UPB_DESCRIPTOR_TYPE_ENUM); + reg<int32_t, value_int32> (h, UPB_DESCRIPTOR_TYPE_SFIXED32); + reg<int64_t, value_int64> (h, UPB_DESCRIPTOR_TYPE_SFIXED64); + reg<int32_t, value_int32> (h, UPB_DESCRIPTOR_TYPE_SINT32); + reg<int64_t, value_int64> (h, UPB_DESCRIPTOR_TYPE_SINT64); reg_str(h, UPB_DESCRIPTOR_TYPE_STRING); reg_str(h, UPB_DESCRIPTOR_TYPE_BYTES); @@ -417,7 +396,7 @@ void run_decoder(const buffer& proto, const buffer* expected_output) { upb::Pipeline pipeline(NULL, 0, upb_realloc, NULL); upb::Sink* sink = pipeline.NewSink(handlers); upb::Sink* decoder_sink = pipeline.NewSink(plan); - upb::pb::Decoder* d = decoder_sink->base()->GetUserdata<upb::pb::Decoder>(); + upb::pb::Decoder* d = decoder_sink->GetObject<upb::pb::Decoder>(); upb::pb::ResetDecoderSink(d, sink); for (size_t i = 0; i < proto.len(); i++) { for (size_t j = i; j < UPB_MIN(proto.len(), i + 5); j++) { diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc index b1a6053..bc6df46 100644 --- a/tests/test_vs_proto2.cc +++ b/tests/test_vs_proto2.cc @@ -60,8 +60,7 @@ void parse_and_compare(google::protobuf::Message *msg1, upb::Sink* decoder_sink = pipeline.NewSink(decoder_handlers); protomsg_sink->Reset(msg2); - upb::pb::Decoder* decoder = - decoder_sink->base()->GetUserdata<upb::pb::Decoder>(); + upb::pb::Decoder* decoder = decoder_sink->GetObject<upb::pb::Decoder>(); upb::pb::ResetDecoderSink(decoder, protomsg_sink); msg2->Clear(); diff --git a/upb/descriptor/descriptor.upb.c b/upb/descriptor/descriptor.upb.c index 80d5f59..61a5449 100755 --- a/upb/descriptor/descriptor.upb.c +++ b/upb/descriptor/descriptor.upb.c @@ -12,53 +12,53 @@ const upb_tabent google_protobuf_intentries[66]; const _upb_value google_protobuf_arrays[97]; const upb_msgdef google_protobuf_msgs[20] = { - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[0], &google_protobuf_arrays[0], 6, 5), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[0]), 25), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[0], &google_protobuf_arrays[0], 6, 5), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[0]), 31), UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[6], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[16]), 2), - UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[10], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[20]), 9), - UPB_MSGDEF_INIT("google.protobuf.EnumOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[14], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[24]), 4), - UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[15], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[28]), 6), - UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[19], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[32]), 4), - UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[8], &google_protobuf_arrays[20], 6, 5), UPB_STRTABLE_INIT(8, 15, 9, 4, &google_protobuf_strentries[36]), 17), - UPB_MSGDEF_INIT("google.protobuf.FieldOptions", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[12], &google_protobuf_arrays[26], 5, 3), UPB_STRTABLE_INIT(5, 7, 9, 3, &google_protobuf_strentries[52]), 10), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", UPB_INTTABLE_INIT(4, 7, 9, 3, &google_protobuf_intentries[16], &google_protobuf_arrays[31], 6, 5), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[60]), 31), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[37], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[76]), 4), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", UPB_INTTABLE_INIT(8, 15, 9, 4, &google_protobuf_intentries[24], &google_protobuf_arrays[40], 6, 1), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[80]), 16), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[40], &google_protobuf_arrays[46], 4, 2), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[96]), 6), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[50], 5, 4), UPB_STRTABLE_INIT(4, 7, 9, 3, &google_protobuf_strentries[100]), 11), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[42], &google_protobuf_arrays[55], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[108]), 4), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[56], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[112]), 9), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[44], &google_protobuf_arrays[60], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[116]), 4), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[61], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[120]), 4), + UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[10], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[20]), 11), + UPB_MSGDEF_INIT("google.protobuf.EnumOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[14], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[24]), 5), + UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[15], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[28]), 7), + UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[19], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[32]), 5), + UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[8], &google_protobuf_arrays[20], 6, 5), UPB_STRTABLE_INIT(8, 15, 9, 4, &google_protobuf_strentries[36]), 18), + UPB_MSGDEF_INIT("google.protobuf.FieldOptions", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[12], &google_protobuf_arrays[26], 5, 3), UPB_STRTABLE_INIT(5, 7, 9, 3, &google_protobuf_strentries[52]), 11), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", UPB_INTTABLE_INIT(4, 7, 9, 3, &google_protobuf_intentries[16], &google_protobuf_arrays[31], 6, 5), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[60]), 37), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[37], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[76]), 5), + UPB_MSGDEF_INIT("google.protobuf.FileOptions", UPB_INTTABLE_INIT(8, 15, 9, 4, &google_protobuf_intentries[24], &google_protobuf_arrays[40], 6, 1), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[80]), 17), + UPB_MSGDEF_INIT("google.protobuf.MessageOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[40], &google_protobuf_arrays[46], 4, 2), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[96]), 7), + UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[50], 5, 4), UPB_STRTABLE_INIT(4, 7, 9, 3, &google_protobuf_strentries[100]), 12), + UPB_MSGDEF_INIT("google.protobuf.MethodOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[42], &google_protobuf_arrays[55], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[108]), 5), + UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[56], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[112]), 11), + UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[44], &google_protobuf_arrays[60], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[116]), 5), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[61], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[120]), 5), UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[64], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[124]), 6), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[46], &google_protobuf_arrays[68], 6, 4), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[128]), 16), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[46], &google_protobuf_arrays[68], 6, 4), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[128]), 17), UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[74], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[144]), 4), }; const upb_fielddef google_protobuf_fields[73] = { - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 9, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 10, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 3, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "ctype", 1, &google_protobuf_msgs[7], upb_upcast(&google_protobuf_enums[2]), 0, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 14, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 15, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 8, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 2, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 12, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 13, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "end", 2, &google_protobuf_msgs[1], NULL, 1, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[2]), 13, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[2]), 17, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[2]), 15, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[2]), 18, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 3, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 3, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[6]), 29, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 21, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[1]), 17, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[6]), 34, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 25, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[1]), 20, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "field", 2, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 5, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "file", 1, &google_protobuf_msgs[9], upb_upcast(&google_protobuf_msgs[8]), 2, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 4, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 5, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 3, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 3, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 6, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 4, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 15, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 11, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 16, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 12, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 0, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "label", 4, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_enums[0]), 7, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "location", 1, &google_protobuf_msgs[16], upb_upcast(&google_protobuf_msgs[17]), 2, UPB_VALUE_INIT_NONE), @@ -74,32 +74,32 @@ const upb_fielddef google_protobuf_fields[73] = { UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[0], NULL, 0, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[8], NULL, 0, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 0, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 8, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[0]), 9, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 9, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[0]), 10, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 1, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 2, &google_protobuf_msgs[4], NULL, 3, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 3, &google_protobuf_msgs[6], NULL, 6, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], upb_upcast(&google_protobuf_enums[3]), 14, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], upb_upcast(&google_protobuf_enums[3]), 15, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 4, &google_protobuf_msgs[12], upb_upcast(&google_protobuf_msgs[13]), 9, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], upb_upcast(&google_protobuf_msgs[15]), 7, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[10]), 19, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], upb_upcast(&google_protobuf_msgs[3]), 7, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[11]), 23, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], upb_upcast(&google_protobuf_msgs[15]), 8, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[10]), 21, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], upb_upcast(&google_protobuf_msgs[3]), 8, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[11]), 28, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_msgs[7]), 9, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[4], upb_upcast(&google_protobuf_msgs[5]), 4, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 6, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "package", 2, &google_protobuf_msgs[8], NULL, 3, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "packed", 2, &google_protobuf_msgs[7], NULL, 1, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "path", 1, &google_protobuf_msgs[17], NULL, 2, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 7, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 8, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 5, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[14]), 25, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[16]), 21, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[14]), 29, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[16]), 24, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "span", 2, &google_protobuf_msgs[17], NULL, 5, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "start", 1, &google_protobuf_msgs[1], NULL, 0, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 13, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 14, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "type", 5, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_enums[1]), 8, UPB_VALUE_INIT_NONE), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 11, UPB_VALUE_INIT_NONE), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 12, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], upb_upcast(&google_protobuf_msgs[18]), 2, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], upb_upcast(&google_protobuf_msgs[18]), 4, UPB_VALUE_INIT_NONE), UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], upb_upcast(&google_protobuf_msgs[18]), 2, UPB_VALUE_INIT_NONE), diff --git a/upb/descriptor/descriptor.upb.h b/upb/descriptor/descriptor.upb.h index 23c42a0..e3291a3 100755 --- a/upb/descriptor/descriptor.upb.h +++ b/upb/descriptor/descriptor.upb.h @@ -84,48 +84,48 @@ extern const upb_enumdef google_protobuf_enums[4]; #define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART &google_protobuf_msgs[19] // Selector definitions. -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 11 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 9 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 10 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 12 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 10 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 11 #define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 3 #define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 0 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 16 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 14 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 15 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 17 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 15 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 16 #define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 10 #define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 7 #define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 8 #define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 9 #define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 6 #define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 12 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 13 #define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 1 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 13 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 14 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 17 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 16 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 15 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 18 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 15 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 14 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 13 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 18 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 17 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 16 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 19 #define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 5 #define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 3 #define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 4 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 5 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 3 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 4 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 29 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 28 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 27 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 30 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 21 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 20 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 19 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 17 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 16 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 15 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 18 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 34 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 33 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 32 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 35 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 25 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 24 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 23 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 26 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 20 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 19 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 18 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 21 #define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 5 #define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 4 #define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 3 @@ -134,19 +134,19 @@ extern const upb_enumdef google_protobuf_enums[4]; #define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 1 #define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 0 #define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 3 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 6 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 4 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 5 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 7 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 5 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 6 #define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 5 #define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 3 #define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 4 #define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 3 #define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 6 #define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 4 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 15 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 13 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 11 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 12 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 16 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 14 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 12 +#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 13 #define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 2 #define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 0 #define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 1 @@ -192,25 +192,25 @@ extern const upb_enumdef google_protobuf_enums[4]; #define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 2 #define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 0 #define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 1 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 8 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 9 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 8 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 7 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 10 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 9 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 10 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 9 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 8 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 11 #define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 1 #define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 3 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 6 -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 14 +#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 15 #define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 9 #define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 10 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 8 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 19 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 8 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 23 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 24 +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 8 +#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 9 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 21 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 22 +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 8 +#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 9 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 28 +#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 29 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 9 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 10 #define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 4 @@ -225,25 +225,25 @@ extern const upb_enumdef google_protobuf_enums[4]; #define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 1 #define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 2 #define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 0 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 7 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 8 #define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 5 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 25 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 24 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 23 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 26 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 21 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 22 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 29 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 28 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 27 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 30 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 24 +#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 25 #define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 4 #define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 5 #define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 3 #define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 0 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 15 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 13 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 14 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 16 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 14 +#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 15 #define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 8 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 13 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 11 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 12 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 14 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 12 +#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 13 #define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 #define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 1 #define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 0 diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c index 529d5ef..5fe334f 100644 --- a/upb/descriptor/reader.c +++ b/upb/descriptor/reader.c @@ -52,13 +52,15 @@ static char *upb_join(const char *base, const char *name) { // upb_deflist is an internal-only dynamic array for storing a growing list of // upb_defs. typedef struct { + upb_pipeline *pipeline; upb_def **defs; size_t len; size_t size; bool owned; } upb_deflist; -void upb_deflist_init(upb_deflist *l) { +void upb_deflist_init(upb_deflist *l, upb_pipeline *pipeline) { + l->pipeline = pipeline; l->size = 0; l->defs = NULL; l->len = 0; @@ -68,15 +70,16 @@ void upb_deflist_init(upb_deflist *l) { void upb_deflist_uninit(upb_deflist *l) { if (l->owned) for(size_t i = 0; i < l->len; i++) - upb_def_unref(l->defs[i], &l->defs); + upb_def_unref(l->defs[i], l); } -bool upb_deflist_push(upb_deflist *l, upb_def *d, upb_pipeline *p) { +bool upb_deflist_push(upb_deflist *l, upb_def *d) { if(++l->len >= l->size) { size_t new_size = UPB_MAX(l->size, 4); new_size *= 2; l->defs = upb_pipeline_realloc( - p, l->defs, l->size * sizeof(void*), new_size * sizeof(void*)); + l->pipeline, l->defs, + l->size * sizeof(void*), new_size * sizeof(void*)); if (!l->defs) return false; l->size = new_size; } @@ -87,7 +90,7 @@ bool upb_deflist_push(upb_deflist *l, upb_def *d, upb_pipeline *p) { void upb_deflist_donaterefs(upb_deflist *l, void *owner) { assert(l->owned); for (size_t i = 0; i < l->len; i++) - upb_def_donateref(l->defs[i], &l->defs, owner); + upb_def_donateref(l->defs[i], l, owner); l->owned = false; } @@ -134,8 +137,8 @@ struct upb_descreader { upb_fielddef *f; }; -void upb_descreader_init(void *r); -void upb_descreader_uninit(void *r); +void upb_descreader_init(void *self, upb_pipeline *p); +void upb_descreader_uninit(void *self); const upb_frametype upb_descreader_frametype = { sizeof(upb_descreader), @@ -155,16 +158,16 @@ const upb_handlers *upb_descreader_gethandlers(const void *owner); /* upb_descreader ************************************************************/ -void upb_descreader_init(void *_r) { - upb_descreader *r = _r; - upb_deflist_init(&r->defs); +void upb_descreader_init(void *self, upb_pipeline *pipeline) { + upb_descreader *r = self; + upb_deflist_init(&r->defs, pipeline); r->stack_len = 0; r->name = NULL; r->default_string = NULL; } -void upb_descreader_uninit(void *_r) { - upb_descreader *r = _r; +void upb_descreader_uninit(void *self) { + upb_descreader *r = self; free(r->name); upb_deflist_uninit(&r->defs); free(r->default_string); @@ -213,37 +216,39 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) { } // Handlers for google.protobuf.FileDescriptorProto. -static bool file_startmsg(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool file_startmsg(void *r) { upb_descreader_startcontainer(r); return true; } -static void file_endmsg(const upb_sinkframe *frame, upb_status *status) { +static bool file_endmsg(void *closure, upb_status *status) { UPB_UNUSED(status); - upb_descreader *r = upb_sinkframe_userdata(frame); + upb_descreader *r = closure; upb_descreader_endcontainer(r); + return true; } -static size_t file_onpackage(const upb_sinkframe *frame, - const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static size_t file_onpackage(void *closure, const void *hd, const char *buf, + size_t n) { + UPB_UNUSED(hd); + upb_descreader *r = closure; // XXX: see comment at the top of the file. upb_descreader_setscopename(r, upb_strndup(buf, n)); return n; } // Handlers for google.protobuf.EnumValueDescriptorProto. -static bool enumval_startmsg(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool enumval_startmsg(void *closure) { + upb_descreader *r = closure; r->saw_number = false; r->saw_name = false; return true; } -static size_t enumval_onname(const upb_sinkframe *frame, - const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static size_t enumval_onname(void *closure, const void *hd, const char *buf, + size_t n) { + UPB_UNUSED(hd); + upb_descreader *r = closure; // XXX: see comment at the top of the file. free(r->name); r->name = upb_strndup(buf, n); @@ -251,18 +256,19 @@ static size_t enumval_onname(const upb_sinkframe *frame, return n; } -static bool enumval_onnumber(const upb_sinkframe *frame, int32_t val) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool enumval_onnumber(void *closure, const void *hd, int32_t val) { + UPB_UNUSED(hd); + upb_descreader *r = closure; r->number = val; r->saw_number = true; return true; } -static void enumval_endmsg(const upb_sinkframe *frame, upb_status *status) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool enumval_endmsg(void *closure, upb_status *status) { + upb_descreader *r = closure; if(!r->saw_number || !r->saw_name) { upb_status_seterrliteral(status, "Enum value missing name or number."); - return; + return false; } upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_enumdef_numvals(e) == 0) { @@ -273,33 +279,35 @@ static void enumval_endmsg(const upb_sinkframe *frame, upb_status *status) { upb_enumdef_addval(e, r->name, r->number, status); free(r->name); r->name = NULL; + return true; } // Handlers for google.protobuf.EnumDescriptorProto. -static bool enum_startmsg(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); - upb_pipeline *p = upb_sinkframe_pipeline(frame); - upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs)), p); +static bool enum_startmsg(void *closure) { + upb_descreader *r = closure; + upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs))); return true; } -static void enum_endmsg(const upb_sinkframe *frame, upb_status *status) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool enum_endmsg(void *closure, upb_status *status) { + upb_descreader *r = closure; upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_def_fullname(upb_descreader_last(r)) == NULL) { upb_status_seterrliteral(status, "Enum had no name."); - return; + return false; } if (upb_enumdef_numvals(e) == 0) { upb_status_seterrliteral(status, "Enum had no values."); - return; + return false; } + return true; } -static size_t enum_onname(const upb_sinkframe *frame, - const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static size_t enum_onname(void *closure, const void *hd, const char *buf, + size_t n) { + UPB_UNUSED(hd); + upb_descreader *r = closure; // XXX: see comment at the top of the file. char *fullname = upb_strndup(buf, n); upb_def_setfullname(upb_descreader_last(r), fullname); @@ -308,8 +316,8 @@ static size_t enum_onname(const upb_sinkframe *frame, } // Handlers for google.protobuf.FieldDescriptorProto -static bool field_startmsg(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool field_startmsg(void *closure) { + upb_descreader *r = closure; r->f = upb_fielddef_new(&r->defs); free(r->default_string); r->default_string = NULL; @@ -380,8 +388,8 @@ static bool parse_default(char *str, upb_value *d, int type) { return success; } -static void field_endmsg(const upb_sinkframe *frame, upb_status *status) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool field_endmsg(void *closure, upb_status *status) { + upb_descreader *r = closure; upb_fielddef *f = r->f; // TODO: verify that all required fields were present. assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL); @@ -390,7 +398,7 @@ static void field_endmsg(const upb_sinkframe *frame, upb_status *status) { if (r->default_string) { if (upb_fielddef_issubmsg(f)) { upb_status_seterrliteral(status, "Submessages cannot have defaults."); - return; + return false; } if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) { upb_fielddef_setdefaultcstr(f, r->default_string); @@ -401,34 +409,39 @@ static void field_endmsg(const upb_sinkframe *frame, upb_status *status) { // We don't worry too much about giving a great error message since the // compiler should have ensured this was correct. upb_status_seterrliteral(status, "Error converting default value."); - return; + return false; } upb_fielddef_setdefault(f, val); } } + return true; } -static bool field_ontype(const upb_sinkframe *frame, int32_t val) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool field_ontype(void *closure, const void *hd, int32_t val) { + UPB_UNUSED(hd); + upb_descreader *r = closure; upb_fielddef_setdescriptortype(r->f, val); return true; } -static bool field_onlabel(const upb_sinkframe *frame, int32_t val) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool field_onlabel(void *closure, const void *hd, int32_t val) { + UPB_UNUSED(hd); + upb_descreader *r = closure; upb_fielddef_setlabel(r->f, val); return true; } -static bool field_onnumber(const upb_sinkframe *frame, int32_t val) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool field_onnumber(void *closure, const void *hd, int32_t val) { + UPB_UNUSED(hd); + upb_descreader *r = closure; upb_fielddef_setnumber(r->f, val); return true; } -static size_t field_onname(const upb_sinkframe *frame, - const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static size_t field_onname(void *closure, const void *hd, const char *buf, + size_t n) { + UPB_UNUSED(hd); + upb_descreader *r = closure; // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); upb_fielddef_setname(r->f, name); @@ -436,9 +449,10 @@ static size_t field_onname(const upb_sinkframe *frame, return n; } -static size_t field_ontypename(const upb_sinkframe *frame, - const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static size_t field_ontypename(void *closure, const void *hd, const char *buf, + size_t n) { + UPB_UNUSED(hd); + upb_descreader *r = closure; // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); upb_fielddef_setsubdefname(r->f, name); @@ -446,9 +460,10 @@ static size_t field_ontypename(const upb_sinkframe *frame, return n; } -static size_t field_ondefaultval(const upb_sinkframe *frame, +static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); + UPB_UNUSED(hd); + upb_descreader *r = closure; // Have to convert from string to the correct type, but we might not know the // type yet, so we save it as a string until the end of the field. // XXX: see comment at the top of the file. @@ -458,27 +473,28 @@ static size_t field_ondefaultval(const upb_sinkframe *frame, } // Handlers for google.protobuf.DescriptorProto (representing a message). -static bool msg_startmsg(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); - upb_pipeline *p = upb_sinkframe_pipeline(frame); - upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs)), p); +static bool msg_startmsg(void *closure) { + upb_descreader *r = closure; + upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs))); upb_descreader_startcontainer(r); return true; } -static void msg_endmsg(const upb_sinkframe *frame, upb_status *status) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool msg_endmsg(void *closure, upb_status *status) { + upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); if(!upb_def_fullname(upb_upcast(m))) { upb_status_seterrliteral(status, "Encountered message with no name."); - return; + return false; } upb_descreader_endcontainer(r); + return true; } -static size_t msg_onname(const upb_sinkframe *frame, - const char *buf, size_t n) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static size_t msg_onname(void *closure, const void *hd, const char *buf, + size_t n) { + UPB_UNUSED(hd); + upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); @@ -487,16 +503,18 @@ static size_t msg_onname(const upb_sinkframe *frame, return n; } -static bool msg_onendfield(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool msg_onendfield(void *closure, const void *hd) { + UPB_UNUSED(hd); + upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); upb_msgdef_addfield(m, r->f, &r->defs); r->f = NULL; return true; } -static bool discardfield(const upb_sinkframe *frame) { - upb_descreader *r = upb_sinkframe_userdata(frame); +static bool discardfield(void *closure, const void *hd) { + UPB_UNUSED(hd); + upb_descreader *r = closure; // Discard extension field so we don't leak it. upb_fielddef_unref(r->f, &r->defs); r->f = NULL; diff --git a/upb/descriptor/reader.h b/upb/descriptor/reader.h index 87f5f86..b7c7d8b 100644 --- a/upb/descriptor/reader.h +++ b/upb/descriptor/reader.h @@ -57,10 +57,6 @@ const upb_handlers *upb_descreader_gethandlers(const void *owner); namespace upb { -template<> inline const FrameType* GetFrameType<upb::descriptor::Reader>() { - return upb_descreader_getframetype(); -} - namespace descriptor { inline upb::Def** GetDefs(Reader* r, void* owner, int* n) { return upb_descreader_getdefs(r, owner, n); diff --git a/upb/google/proto1.cc b/upb/google/proto1.cc index 3967723..51b221a 100644 --- a/upb/google/proto1.cc +++ b/upb/google/proto1.cc @@ -23,6 +23,7 @@ #include "net/proto/proto2_reflection.h" #include "upb/def.h" #include "upb/handlers.h" +#include "upb/shim/shim.h" #include "upb/sink.h" template <class T> static T* GetPointer(void* message, size_t offset) { @@ -202,14 +203,12 @@ class P2R_Handlers { const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(f->IsSequence()); - h->SetStartSequenceHandler(f, &PushOffset, new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset>); + h->SetStartSequenceHandler( + f, UpbBind(PushOffset, new FieldOffset(proto2_f, r))); } - static void* PushOffset(const upb::SinkFrame* frame) { - const FieldOffset* offset = - static_cast<FieldOffset*>(frame->handler_data()); - return offset->GetFieldPointer<void>(frame->userdata()); + static void* PushOffset(void* m, const FieldOffset* offset) { + return offset->GetFieldPointer<void>(m); } // Primitive Value (numeric, enum, bool) ///////////////////////////////////// @@ -220,18 +219,15 @@ class P2R_Handlers { const upb::FieldDef* f, upb::Handlers* h) { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetValueHandler<T>(f, &Append<T>, NULL, NULL); + h->SetValueHandler<T>(f, UpbMakeHandlerT(Append<T>)); } else { - upb::SetStoreValueHandler<T>(f, GetOffset(proto2_f, r), - GetHasbit(proto2_f, r), h); + upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r)); } } template <typename T> - static bool Append(const upb::SinkFrame* frame, T val) { + static bool Append(proto2::RepeatedField<T>* r, T val) { // Proto1's ProtoArray class derives from proto2::RepeatedField. - proto2::RepeatedField<T>* r = - static_cast<proto2::RepeatedField<T>*>(frame->userdata()); r->Add(val); return true; } @@ -241,21 +237,18 @@ class P2R_Handlers { static void SetStringHandlers(const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { - h->SetStringHandler(f, &OnStringBuf, NULL, NULL); + h->SetStringHandler(f, UpbMakeHandler(OnStringBuf)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetStartStringHandler(f, &StartRepeatedString, NULL, NULL); + h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedString)); } else { - h->SetStartStringHandler(f, &StartString, new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset>); + h->SetStartStringHandler( + f, UpbBind(StartString, new FieldOffset(proto2_f, r))); } } - static void* StartString(const upb::SinkFrame* frame, size_t size_hint) { - UPB_UNUSED(size_hint); - void* m = frame->userdata(); - const FieldOffset* info = - static_cast<const FieldOffset*>(frame->handler_data()); + static string* StartString(proto2::Message* m, const FieldOffset* info, + size_t size_hint) { info->SetHasbit(m); string* str = info->GetFieldPointer<string>(m); str->clear(); @@ -263,18 +256,13 @@ class P2R_Handlers { return str; } - static size_t OnStringBuf(const upb::SinkFrame* frame, - const char* buf, - size_t n) { - string* s = static_cast<string*>(frame->userdata()); + static size_t OnStringBuf(string* s, const char* buf, size_t n) { s->append(buf, n); return n; } - static void* StartRepeatedString(const upb::SinkFrame* frame, - size_t size_hint) { - proto2::RepeatedPtrField<string>* r = - static_cast<proto2::RepeatedPtrField<string>*>(frame->userdata()); + static string* StartRepeatedString(proto2::RepeatedPtrField<string>* r, + size_t size_hint) { string* str = r->Add(); // reserve() here appears to hurt performance rather than help. return str; @@ -287,17 +275,14 @@ class P2R_Handlers { const upb::FieldDef* f, upb::Handlers* h) { // This type is only used for non-repeated string fields. assert(!f->IsSequence()); - h->SetStartStringHandler(f, &StartOutOfLineString, - new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset>); - h->SetStringHandler(f, &OnStringBuf, NULL, NULL); + h->SetStartStringHandler( + f, UpbBind(StartOutOfLineString, new FieldOffset(proto2_f, r))); + h->SetStringHandler(f, UpbMakeHandler(OnStringBuf)); } - static void* StartOutOfLineString(const upb::SinkFrame* frame, - size_t size_hint) { - const FieldOffset* info = - static_cast<const FieldOffset*>(frame->handler_data()); - void* m = frame->userdata(); + static string* StartOutOfLineString(proto2::Message* m, + const FieldOffset* info, + size_t size_hint) { info->SetHasbit(m); string** str = info->GetFieldPointer<string*>(m); if (*str == &::proto2::internal::GetEmptyString()) @@ -312,40 +297,33 @@ class P2R_Handlers { static void SetCordHandlers(const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { - h->SetStringHandler(f, &OnCordBuf, NULL, NULL); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetStartStringHandler(f, &StartRepeatedCord, NULL, NULL); + h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord)); } else { - h->SetStartStringHandler(f, &StartCord, new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset*>); + h->SetStartStringHandler( + f, UpbBind(StartCord, new FieldOffset(proto2_f, r))); } + h->SetStringHandler(f, UpbMakeHandler(OnCordBuf)); } - static void* StartCord(const upb::SinkFrame* frame, size_t size_hint) { + static Cord* StartCord(proto2::Message* m, const FieldOffset* offset, + size_t size_hint) { UPB_UNUSED(size_hint); - void* m = frame->userdata(); - const FieldOffset* offset = - static_cast<const FieldOffset*>(frame->handler_data()); offset->SetHasbit(m); Cord* field = offset->GetFieldPointer<Cord>(m); field->Clear(); return field; } - static size_t OnCordBuf(const upb::SinkFrame* frame, - const char* buf, - size_t n) { - Cord* c = static_cast<Cord*>(frame->userdata()); + static size_t OnCordBuf(Cord* c, const char* buf, size_t n) { c->Append(StringPiece(buf, n)); return true; } - static void* StartRepeatedCord(const upb::SinkFrame* frame, + static Cord* StartRepeatedCord(proto2::RepeatedField<Cord>* r, size_t size_hint) { UPB_UNUSED(size_hint); - proto2::RepeatedField<Cord>* r = - static_cast<proto2::RepeatedField<Cord>*>(frame->userdata()); return r->Add(); } @@ -367,46 +345,39 @@ class P2R_Handlers { const proto2::Message* prototype_; }; - static void SetStartSubMessageHandler( - const proto2::FieldDescriptor* proto2_f, const proto2::Message& m, - const _pi::Proto2Reflection* r, upb::Handlers::StartFieldHandler* handler, - const upb::FieldDef* f, upb::Handlers* h) { - h->SetStartSubMessageHandler(f, handler, - new SubMessageHandlerData(m, proto2_f, r), - &upb::DeletePointer<SubMessageHandlerData>); - } - static void SetRequiredMessageHandlers( const proto2::FieldDescriptor* proto2_f, const proto2::Message& m, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h); + h->SetStartSubMessageHandler( + f, UpbBind(StartRepeatedSubMessage, + new SubMessageHandlerData(m, proto2_f, r))); } else { - h->SetStartSubMessageHandler(f, &StartRequiredSubMessage, - new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset>); + h->SetStartSubMessageHandler( + f, UpbBind(StartRequiredSubMessage, new FieldOffset(proto2_f, r))); } } - static void* StartRequiredSubMessage(const upb::SinkFrame* frame) { - const FieldOffset* offset = - static_cast<FieldOffset*>(frame->handler_data()); - void* m = frame->userdata(); + static proto2::Message* StartRequiredSubMessage(proto2::Message* m, + const FieldOffset* offset) { offset->SetHasbit(m); - return offset->GetFieldPointer<void>(m); + return offset->GetFieldPointer<proto2::Message>(m); } static void SetMessageHandlers(const proto2::FieldDescriptor* proto2_f, const proto2::Message& m, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { + scoped_ptr<SubMessageHandlerData> data( + new SubMessageHandlerData(m, proto2_f, r)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h); + h->SetStartSubMessageHandler( + f, UpbBind(StartRepeatedSubMessage, data.release())); } else { - SetStartSubMessageHandler(proto2_f, m, r, &StartSubMessage, f, h); + h->SetStartSubMessageHandler(f, UpbBind(StartSubMessage, data.release())); } } @@ -414,28 +385,26 @@ class P2R_Handlers { const proto2::Message& m, const _pi::Proto2Reflection* r, const upb::FieldDef* f, upb::Handlers* h) { + scoped_ptr<SubMessageHandlerData> data( + new SubMessageHandlerData(m, proto2_f, r)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h); + h->SetStartSubMessageHandler( + f, UpbBind(StartRepeatedSubMessage, data.release())); } else { - SetStartSubMessageHandler(proto2_f, m, r, &StartWeakSubMessage, f, h); + h->SetStartSubMessageHandler( + f, UpbBind(StartWeakSubMessage, data.release())); } } - static void* StartSubMessage(const upb::SinkFrame* frame) { - void* m = frame->userdata(); - const SubMessageHandlerData* info = - static_cast<const SubMessageHandlerData*>(frame->handler_data()); + static void* StartSubMessage(void *m, const SubMessageHandlerData* info) { info->SetHasbit(m); proto2::Message** subm = info->GetFieldPointer<proto2::Message*>(m); if (*subm == info->prototype()) *subm = (*subm)->New(); return *subm; } - static void* StartWeakSubMessage(const upb::SinkFrame* frame) { - void* m = frame->userdata(); - const SubMessageHandlerData* info = - static_cast<const SubMessageHandlerData*>(frame->handler_data()); + static void* StartWeakSubMessage(void* m, const SubMessageHandlerData* info) { info->SetHasbit(m); proto2::Message** subm = info->GetFieldPointer<proto2::Message*>(m); if (*subm == NULL) { @@ -446,7 +415,7 @@ class P2R_Handlers { class RepeatedMessageTypeHandler { public: - typedef void Type; + typedef proto2::Message Type; // AddAllocated() calls this, but only if other objects are sitting // around waiting for reuse, which we will not do. static void Delete(Type* t) { @@ -457,12 +426,10 @@ class P2R_Handlers { // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through // its base class RepeatedPtrFieldBase*. - static void* StartRepeatedSubMessage(const upb::SinkFrame* frame) { - const SubMessageHandlerData* info = - static_cast<const SubMessageHandlerData*>(frame->handler_data()); - proto2::internal::RepeatedPtrFieldBase* r = - static_cast<proto2::internal::RepeatedPtrFieldBase*>(frame->userdata()); - void* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>(); + static proto2::Message* StartRepeatedSubMessage( + proto2::internal::RepeatedPtrFieldBase* r, + const SubMessageHandlerData* info) { + proto2::Message* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>(); if (!submsg) { submsg = info->prototype()->New(); r->AddAllocated<RepeatedMessageTypeHandler>(submsg); diff --git a/upb/google/proto2.cc b/upb/google/proto2.cc index 8f9bcd8..e878a65 100644 --- a/upb/google/proto2.cc +++ b/upb/google/proto2.cc @@ -18,6 +18,7 @@ #include "upb/def.h" #include "upb/google/proto1.h" #include "upb/handlers.h" +#include "upb/shim/shim.h" #include "upb/sink.h" namespace upb { @@ -65,6 +66,7 @@ using goog::int32; using goog::int64; using goog::uint32; using goog::uint64; +using goog::scoped_ptr; #endif // ifdef UPB_GOOGLE3 @@ -260,7 +262,7 @@ case goog::FieldDescriptor::cpptype: \ int number() const { return number_; } goog::internal::FieldType type() const { return type_; } - goog::internal::ExtensionSet* GetExtensionSet(goog::Message* m) const { + goog::internal::ExtensionSet* GetExtensionSet(goog::MessageLite* m) const { return GetPointer<goog::internal::ExtensionSet>(m, offset_); } @@ -277,14 +279,13 @@ case goog::FieldDescriptor::cpptype: \ const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(f->IsSequence()); - h->SetStartSequenceHandler(f, &PushOffset, new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset>); + h->SetStartSequenceHandler( + f, UpbBind(PushOffset, new FieldOffset(proto2_f, r))); } - static void* PushOffset(const upb::SinkFrame* frame) { - const FieldOffset* offset = - static_cast<FieldOffset*>(frame->handler_data()); - return offset->GetFieldPointer<void>(frame->userdata()); + // TODO(haberman): make more type-safe? + static void* PushOffset(void* message, const FieldOffset* offset) { + return offset->GetFieldPointer<void>(message); } // Primitive Value (numeric, bool) /////////////////////////////////////////// @@ -294,37 +295,33 @@ case goog::FieldDescriptor::cpptype: \ const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { if (proto2_f->is_extension()) { - ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r); - upb::Handlers::Free* free = &upb::DeletePointer<ExtensionFieldData>; + scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r)); if (f->IsSequence()) { - h->SetValueHandler<T>(f, &AppendPrimitiveExtension<T>, data, free); + h->SetValueHandler<T>( + f, UpbBindT(AppendPrimitiveExtension<T>, data.release())); } else { - h->SetValueHandler<T>(f, &SetPrimitiveExtension<T>, data, free); + h->SetValueHandler<T>( + f, UpbBindT(SetPrimitiveExtension<T>, data.release())); } } else { if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetValueHandler<T>(f, &AppendPrimitive<T>, NULL, NULL); + h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>)); } else { - upb::SetStoreValueHandler<T>(f, GetOffset(proto2_f, r), - GetHasbit(proto2_f, r), h); + upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r)); } } } template <typename T> - static bool AppendPrimitive(const upb::SinkFrame* frame, T val) { - goog::RepeatedField<T>* r = - static_cast<goog::RepeatedField<T>*>(frame->userdata()); + static bool AppendPrimitive(goog::RepeatedField<T>* r, T val) { r->Add(val); return true; } template <typename T> - static bool AppendPrimitiveExtension(const upb::SinkFrame* frame, T val) { - goog::Message* m = frame->GetUserdata<goog::Message>(); - ExtensionFieldData* data = - static_cast<ExtensionFieldData*>(frame->handler_data()); + static bool AppendPrimitiveExtension(goog::Message* m, + const ExtensionFieldData* data, T val) { goog::internal::ExtensionSet* set = data->GetExtensionSet(m); // TODO(haberman): give an accurate value for "packed" goog::internal::RepeatedPrimitiveTypeTraits<T>::Add( @@ -333,10 +330,8 @@ case goog::FieldDescriptor::cpptype: \ } template <typename T> - static bool SetPrimitiveExtension(const upb::SinkFrame* frame, T val) { - goog::Message* m = frame->GetUserdata<goog::Message>(); - ExtensionFieldData* data = - static_cast<ExtensionFieldData*>(frame->handler_data()); + static bool SetPrimitiveExtension(goog::Message* m, + const ExtensionFieldData* data, T val) { goog::internal::ExtensionSet* set = data->GetExtensionSet(m); goog::internal::PrimitiveTypeTraits<T>::Set(data->number(), data->type(), val, set); @@ -376,20 +371,16 @@ case goog::FieldDescriptor::cpptype: \ const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(!proto2_f->is_extension()); - EnumHandlerData* data = new EnumHandlerData(proto2_f, r, f); + scoped_ptr<EnumHandlerData> data(new EnumHandlerData(proto2_f, r, f)); if (f->IsSequence()) { - h->SetInt32Handler(f, &AppendEnum, data, - &upb::DeletePointer<EnumHandlerData>); + h->SetInt32Handler(f, UpbBind(AppendEnum, data.release())); } else { - h->SetInt32Handler(f, &SetEnum, data, - &upb::DeletePointer<EnumHandlerData>); + h->SetInt32Handler(f, UpbBind(SetEnum, data.release())); } } - static bool SetEnum(const upb::SinkFrame* frame, int32_t val) { - goog::Message* m = static_cast<goog::Message*>(frame->userdata()); - const EnumHandlerData* data = - static_cast<const EnumHandlerData*>(frame->handler_data()); + static bool SetEnum(goog::Message* m, const EnumHandlerData* data, + int32_t val) { if (data->IsValidValue(val)) { int32_t* message_val = data->GetFieldPointer<int32_t>(m); *message_val = val; @@ -400,13 +391,11 @@ case goog::FieldDescriptor::cpptype: \ return true; } - static bool AppendEnum(const upb::SinkFrame* frame, int32_t val) { + static bool AppendEnum(goog::Message* m, const EnumHandlerData* data, + int32_t val) { // Closure is the enclosing message. We can't use the RepeatedField<> as // the closure because we need to go back to the message for unrecognized // enum values, which go into the unknown field set. - goog::Message* m = static_cast<goog::Message*>(frame->userdata()); - const EnumHandlerData* data = - static_cast<const EnumHandlerData*>(frame->handler_data()); if (data->IsValidValue(val)) { goog::RepeatedField<int32_t>* r = data->GetFieldPointer<goog::RepeatedField<int32_t> >(m); @@ -424,29 +413,23 @@ case goog::FieldDescriptor::cpptype: \ const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(proto2_f->is_extension()); - ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r); + scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r)); if (f->IsSequence()) { - h->SetInt32Handler(f, &AppendEnumExtension, data, - upb::DeletePointer<ExtensionFieldData>); + h->SetInt32Handler(f, UpbBind(AppendEnumExtension, data.release())); } else { - h->SetInt32Handler(f, &SetEnumExtension, data, - upb::DeletePointer<ExtensionFieldData>); + h->SetInt32Handler(f, UpbBind(SetEnumExtension, data.release())); } } - static bool SetEnumExtension(const upb::SinkFrame* frame, int32_t val) { - goog::Message* m = frame->GetUserdata<goog::Message>(); - const ExtensionFieldData* data = - static_cast<const ExtensionFieldData*>(frame->handler_data()); + static bool SetEnumExtension(goog::Message* m, const ExtensionFieldData* data, + int32_t val) { goog::internal::ExtensionSet* set = data->GetExtensionSet(m); set->SetEnum(data->number(), data->type(), val, NULL); return true; } - static bool AppendEnumExtension(const upb::SinkFrame* frame, int32_t val) { - goog::Message* m = frame->GetUserdata<goog::Message>(); - const ExtensionFieldData* data = - static_cast<const ExtensionFieldData*>(frame->handler_data()); + static bool AppendEnumExtension(goog::Message* m, + const ExtensionFieldData* data, int32_t val) { goog::internal::ExtensionSet* set = data->GetExtensionSet(m); // TODO(haberman): give an accurate value for "packed" set->AddEnum(data->number(), data->type(), true, val, NULL); @@ -480,24 +463,21 @@ case goog::FieldDescriptor::cpptype: \ const upb::FieldDef* f, upb::Handlers* h) { assert(!proto2_f->is_extension()); - h->SetStringHandler(f, &OnStringBuf<T>, NULL, NULL); + h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetStartStringHandler(f, &StartRepeatedString<T>, NULL, NULL); + h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>)); } else { - StringHandlerData<T>* data = new StringHandlerData<T>(proto2_f, r); - h->SetStartStringHandler(f, &StartString<T>, data, - &upb::DeletePointer<StringHandlerData<T> >); + h->SetStartStringHandler( + f, UpbBindT(StartString<T>, new StringHandlerData<T>(proto2_f, r))); } } // This needs to be templated because google3 string is not std::string. template <typename T> - static void* StartString(const upb::SinkFrame* frame, size_t size_hint) { + static T* StartString(goog::Message* m, const StringHandlerData<T>* data, + size_t size_hint) { UPB_UNUSED(size_hint); - goog::Message* m = static_cast<goog::Message*>(frame->userdata()); - const StringHandlerData<T>* data = - static_cast<const StringHandlerData<T>*>(frame->handler_data()); T** str = data->GetStringPointer(m); data->SetHasbit(m); // If it points to the default instance, we must create a new instance. @@ -508,19 +488,15 @@ case goog::FieldDescriptor::cpptype: \ } template <typename T> - static size_t OnStringBuf(const upb::SinkFrame* frame, - const char* buf, size_t n) { - T* str = static_cast<T*>(frame->userdata()); + static size_t OnStringBuf(T* str, const char* buf, size_t n) { str->append(buf, n); return n; } template <typename T> - static void* StartRepeatedString(const upb::SinkFrame* frame, + static T* StartRepeatedString(goog::RepeatedPtrField<T>* r, size_t size_hint) { UPB_UNUSED(size_hint); - goog::RepeatedPtrField<T>* r = - static_cast<goog::RepeatedPtrField<T>*>(frame->userdata()); T* str = r->Add(); str->clear(); // reserve() here appears to hurt performance rather than help. @@ -535,35 +511,32 @@ case goog::FieldDescriptor::cpptype: \ const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(proto2_f->is_extension()); - h->SetStringHandler(f, &OnStringBuf<T>, NULL, NULL); - ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r); + h->SetStringHandler(f, UpbMakeHandlerT(OnStringBuf<T>)); + scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r)); if (f->IsSequence()) { - h->SetStartStringHandler(f, &StartRepeatedStringExtension, data, - upb::DeletePointer<ExtensionFieldData>); + h->SetStartStringHandler( + f, UpbBindT(StartRepeatedStringExtension<T>, data.release())); } else { - h->SetStartStringHandler(f, &StartStringExtension, data, - upb::DeletePointer<ExtensionFieldData>); + h->SetStartStringHandler( + f, UpbBindT(StartStringExtension<T>, data.release())); } } - // google3 string is not std::string, but we avoid needing to template - // because we do not actually have to declare the string type. - static void* StartStringExtension(const upb::SinkFrame* frame, - size_t size_hint) { + // Templated because google3 is not std::string. + template <class T> + static T* StartStringExtension(goog::Message* m, + const ExtensionFieldData* data, + size_t size_hint) { UPB_UNUSED(size_hint); - goog::Message* m = frame->GetUserdata<goog::Message>(); - const ExtensionFieldData* data = - static_cast<const ExtensionFieldData*>(frame->handler_data()); goog::internal::ExtensionSet* set = data->GetExtensionSet(m); return set->MutableString(data->number(), data->type(), NULL); } - static void* StartRepeatedStringExtension(const upb::SinkFrame* frame, - size_t size_hint) { + template <class T> + static T* StartRepeatedStringExtension(goog::Message* m, + const ExtensionFieldData* data, + size_t size_hint) { UPB_UNUSED(size_hint); - goog::Message* m = frame->GetUserdata<goog::Message>(); - const ExtensionFieldData* data = - static_cast<const ExtensionFieldData*>(frame->handler_data()); goog::internal::ExtensionSet* set = data->GetExtensionSet(m); return set->AddString(data->number(), data->type(), NULL); } @@ -588,24 +561,21 @@ case goog::FieldDescriptor::cpptype: \ const goog::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); - SubMessageHandlerData* data = - new SubMessageHandlerData(proto2_f, r, field_prototype); - upb::Handlers::Free* free = &upb::DeletePointer<SubMessageHandlerData>; + scoped_ptr<SubMessageHandlerData> data( + new SubMessageHandlerData(proto2_f, r, field_prototype)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetStartSubMessageHandler(f, &StartRepeatedSubMessage, data, free); + h->SetStartSubMessageHandler( + f, UpbBind(StartRepeatedSubMessage, data.release())); } else { - h->SetStartSubMessageHandler(f, &StartSubMessage, data, free); + h->SetStartSubMessageHandler(f, UpbBind(StartSubMessage, data.release())); } } - static void* StartSubMessage(const upb::SinkFrame* frame) { - void* m = frame->userdata(); - const SubMessageHandlerData* data = - static_cast<const SubMessageHandlerData*>(frame->handler_data()); + static goog::Message* StartSubMessage(goog::Message* m, + const SubMessageHandlerData* data) { data->SetHasbit(m); - goog::Message** subm = - data->GetFieldPointer<goog::Message*>(frame->userdata()); + goog::Message** subm = data->GetFieldPointer<goog::Message*>(m); if (*subm == NULL || *subm == data->prototype()) { *subm = data->prototype()->New(); } @@ -614,7 +584,7 @@ case goog::FieldDescriptor::cpptype: \ class RepeatedMessageTypeHandler { public: - typedef void Type; + typedef goog::Message Type; // AddAllocated() calls this, but only if other objects are sitting // around waiting for reuse, which we will not do. static void Delete(Type* t) { @@ -625,12 +595,10 @@ case goog::FieldDescriptor::cpptype: \ // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through // its base class RepeatedPtrFieldBase*. - static void* StartRepeatedSubMessage(const upb::SinkFrame* frame) { - const SubMessageHandlerData* data = - static_cast<const SubMessageHandlerData*>(frame->handler_data()); - goog::internal::RepeatedPtrFieldBase* r = - static_cast<goog::internal::RepeatedPtrFieldBase*>(frame->userdata()); - void* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>(); + static goog::Message* StartRepeatedSubMessage( + goog::internal::RepeatedPtrFieldBase* r, + const SubMessageHandlerData* data) { + goog::Message* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>(); if (!submsg) { submsg = data->prototype()->New(); r->AddAllocated<RepeatedMessageTypeHandler>(submsg); @@ -663,32 +631,26 @@ case goog::FieldDescriptor::cpptype: \ const upb::FieldDef* f, upb::Handlers* h) { const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); - SubMessageExtensionHandlerData* data = - new SubMessageExtensionHandlerData(proto2_f, r, field_prototype); - upb::Handlers::Free* free = &upb::DeletePointer<SubMessageHandlerData>; + scoped_ptr<SubMessageExtensionHandlerData> data( + new SubMessageExtensionHandlerData(proto2_f, r, field_prototype)); if (f->IsSequence()) { - h->SetStartSubMessageHandler(f, &StartRepeatedSubMessageExtension, data, - free); + h->SetStartSubMessageHandler( + f, UpbBind(StartRepeatedSubMessageExtension, data.release())); } else { - h->SetStartSubMessageHandler(f, &StartSubMessageExtension, data, free); + h->SetStartSubMessageHandler( + f, UpbBind(StartSubMessageExtension, data.release())); } } - static void* StartRepeatedSubMessageExtension(const upb::SinkFrame* frame) { - goog::Message* m = frame->GetUserdata<goog::Message>(); - const SubMessageExtensionHandlerData* data = - static_cast<const SubMessageExtensionHandlerData*>( - frame->handler_data()); + static goog::MessageLite* StartRepeatedSubMessageExtension( + goog::MessageLite* m, const SubMessageExtensionHandlerData* data) { goog::internal::ExtensionSet* set = data->GetExtensionSet(m); return set->AddMessage(data->number(), data->type(), *data->prototype(), NULL); } - static void* StartSubMessageExtension(const upb::SinkFrame* frame) { - goog::Message* m = frame->GetUserdata<goog::Message>(); - const SubMessageExtensionHandlerData* data = - static_cast<const SubMessageExtensionHandlerData*>( - frame->handler_data()); + static goog::MessageLite* StartSubMessageExtension( + goog::MessageLite* m, const SubMessageExtensionHandlerData* data) { goog::internal::ExtensionSet* set = data->GetExtensionSet(m); return set->MutableMessage(data->number(), data->type(), *data->prototype(), NULL); @@ -708,39 +670,33 @@ case goog::FieldDescriptor::cpptype: \ const proto2::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(!proto2_f->is_extension()); - h->SetStringHandler(f, &OnCordBuf, NULL, NULL); + h->SetStringHandler(f, UpbMakeHandler(&OnCordBuf)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetStartStringHandler(f, &StartRepeatedCord, NULL, NULL); + h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord)); } else { - h->SetStartStringHandler(f, &StartCord, new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset*>); + h->SetStartStringHandler( + f, UpbBind(StartCord, new FieldOffset(proto2_f, r))); } } - static void* StartCord(const upb::SinkFrame* frame, size_t size_hint) { + static Cord* StartCord(goog::Message* m, const FieldOffset* offset, + size_t size_hint) { UPB_UNUSED(size_hint); - void* m = frame->userdata(); - const FieldOffset* offset = - static_cast<const FieldOffset*>(frame->handler_data()); offset->SetHasbit(m); Cord* field = offset->GetFieldPointer<Cord>(m); field->Clear(); return field; } - static size_t OnCordBuf(const upb::SinkFrame* frame, - const char* buf, size_t n) { - Cord* c = static_cast<Cord*>(frame->userdata()); + static size_t OnCordBuf(Cord* c, const char* buf, size_t n) { c->Append(StringPiece(buf, n)); return n; } - static void* StartRepeatedCord(const upb::SinkFrame* frame, + static Cord* StartRepeatedCord(proto2::RepeatedField<Cord>* r, size_t size_hint) { UPB_UNUSED(size_hint); - proto2::RepeatedField<Cord>* r = - static_cast<proto2::RepeatedField<Cord>*>(frame->userdata()); return r->Add(); } @@ -751,24 +707,21 @@ case goog::FieldDescriptor::cpptype: \ const proto2::internal::GeneratedMessageReflection* r, const upb::FieldDef* f, upb::Handlers* h) { assert(!proto2_f->is_extension()); - h->SetStringHandler(f, &OnStringPieceBuf, NULL, NULL); + h->SetStringHandler(f, UpbMakeHandler(OnStringPieceBuf)); if (f->IsSequence()) { SetStartSequenceHandler(proto2_f, r, f, h); - h->SetStartStringHandler(f, &StartRepeatedStringPiece, NULL, NULL); + h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedStringPiece)); } else { - h->SetStartStringHandler(f, &StartStringPiece, - new FieldOffset(proto2_f, r), - &upb::DeletePointer<FieldOffset*>); + h->SetStartStringHandler( + f, UpbBind(StartStringPiece, new FieldOffset(proto2_f, r))); } } - static size_t OnStringPieceBuf(const upb::SinkFrame* frame, + static size_t OnStringPieceBuf(proto2::internal::StringPieceField* field, const char* buf, size_t len) { // TODO(haberman): alias if possible and enabled on the input stream. // TODO(haberman): add a method to StringPieceField that lets us avoid // this copy/malloc/free. - proto2::internal::StringPieceField* field = - static_cast<proto2::internal::StringPieceField*>(frame->userdata()); size_t new_len = field->size() + len; char* data = new char[new_len]; memcpy(data, field->data(), field->size()); @@ -778,12 +731,9 @@ case goog::FieldDescriptor::cpptype: \ return len; } - static void* StartStringPiece(const upb::SinkFrame* frame, - size_t size_hint) { + static proto2::internal::StringPieceField* StartStringPiece( + goog::Message* m, const FieldOffset* offset, size_t size_hint) { UPB_UNUSED(size_hint); - void* m = frame->userdata(); - const FieldOffset* offset = - static_cast<const FieldOffset*>(frame->handler_data()); offset->SetHasbit(m); proto2::internal::StringPieceField* field = offset->GetFieldPointer<proto2::internal::StringPieceField>(m); @@ -791,13 +741,10 @@ case goog::FieldDescriptor::cpptype: \ return field; } - static void* StartRepeatedStringPiece(const upb::SinkFrame* frame, - size_t size_hint) { + static proto2::internal::StringPieceField* StartRepeatedStringPiece( + proto2::RepeatedPtrField<proto2::internal::StringPieceField>* r, + size_t size_hint) { UPB_UNUSED(size_hint); - typedef proto2::RepeatedPtrField< - proto2::internal::StringPieceField> RepeatedStringPiece; - RepeatedStringPiece* r = - static_cast<RepeatedStringPiece*>(frame->userdata()); proto2::internal::StringPieceField* field = r->Add(); field->Clear(); return field; diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h new file mode 100644 index 0000000..4a2800c --- /dev/null +++ b/upb/handlers-inl.h @@ -0,0 +1,470 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2011-2012 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * Inline definitions for handlers.h, which are particularly long and a bit + * tricky. + */ + +#ifndef UPB_HANDLERS_INL_H_ +#define UPB_HANDLERS_INL_H_ + +#ifdef __cplusplus + +namespace upb { + +// Deleter: class for constructing a function that deletes a pointer type. +template <class T> struct Deleter { + static void Delete(void* p) { delete static_cast<T*>(p); } +}; + +template <class T> Deleter<T> MatchDeleter(T* data) { + UPB_UNUSED(data); + return Deleter<T>(); +} + +// Template magic for creating type-safe wrappers around the user's actual +// function. These convert between the void*'s of the C API and the C++ +// user's types. These also handle conversion between multiple types with +// the same witdh; ie "long long" and "long" are both 64 bits on LP64. + +// ValueHandler +template <class C, class T1, class T2 = typename CanonicalType<T1>::Type> +struct ValueHandlerWrapper2 { + template <bool F(C *, T1)> + inline static bool Wrapper(void *closure, const void *hd, T2 val) { + UPB_UNUSED(hd); + return F(static_cast<C *>(closure), val); + } +}; + +template <class C, class D, class T1, + class T2 = typename CanonicalType<T1>::Type> +struct ValueHandlerWrapper3 { + template <bool F(C *, const D *, T1)> + inline static bool Wrapper(void *closure, const void *hd, T2 val) { + return F(static_cast<C *>(closure), static_cast<const D *>(hd), val); + } +}; + +template <class C, class T> +inline ValueHandlerWrapper2<C, T> MatchWrapper(bool (*f)(C *, T)) { + UPB_UNUSED(f); + return ValueHandlerWrapper2<C, T>(); +} + +template <class C, class D, class T> +inline ValueHandlerWrapper3<C, D, T> MatchWrapper(bool (*f)(C *, const D *, + T)) { + UPB_UNUSED(f); + return ValueHandlerWrapper3<C, D, T>(); +} + +template <class T> +inline typename ValueHandler<T>::H MakeHandler(bool (*wrapper)(void *, + const void *, + T)) { + return ValueHandler<T>::H::Make(wrapper, NULL, NULL); +} + +template <class C, class D, class T1, class T2> +inline typename ValueHandler<T1>::H BindHandler( + bool (*wrapper)(void *, const void *, T1), bool (*h)(C *, const D *, T2), + D *data) { + UPB_UNUSED(h); // Only for making sure function matches "D". + return ValueHandler<T1>::H::Make(wrapper, data, MatchDeleter(data).Delete); +} + +// StartFieldHandler +template <class R, class C> struct StartFieldHandlerWrapper2 { + template <R *F(C *)> static void *Wrapper(void *closure, const void *hd) { + UPB_UNUSED(hd); + return F(static_cast<C *>(closure)); + } +}; + +template <class R, class C, class D> struct StartFieldHandlerWrapper3 { + template <R *F(C *, const D *)> + inline static void *Wrapper(void *closure, const void *hd) { + return F(static_cast<C *>(closure), static_cast<const D *>(hd)); + } +}; + +template <class R, class C> +inline StartFieldHandlerWrapper2<R, C> MatchWrapper(R *(*f)(C *)) { + UPB_UNUSED(f); + return StartFieldHandlerWrapper2<R, C>(); +} + +template <class R, class C, class D> +inline StartFieldHandlerWrapper3<R, C, D> MatchWrapper(R *(*f)(C *, + const D *)) { + UPB_UNUSED(f); + return StartFieldHandlerWrapper3<R, C, D>(); +} + +inline StartFieldHandler MakeHandler(void *(*wrapper)(void *, const void *)) { + return StartFieldHandler::Make(wrapper, NULL, NULL); +} + +template <class R, class C, class D> +inline StartFieldHandler BindHandler(void *(*wrapper)(void *, const void *), + R *(*h)(C *, const D *), D *data) { + UPB_UNUSED(h); // Only for making sure function matches "D". + return StartFieldHandler::Make(wrapper, data, MatchDeleter(data).Delete); +} + +// EndFieldHandler +template <class C> struct EndFieldHandlerWrapper2 { + template <bool F(C *)> + inline static bool Wrapper(void *closure, const void *hd) { + UPB_UNUSED(hd); + return F(static_cast<C *>(closure)); + } +}; + +template <class C, class D> struct EndFieldHandlerWrapper3 { + template <bool F(C *, const D *)> + inline static bool Wrapper(void *closure, const void *hd) { + return F(static_cast<C *>(closure), static_cast<const D *>(hd)); + } +}; + +template <class C> +inline EndFieldHandlerWrapper2<C> MatchWrapper(bool (*f)(C *)) { + UPB_UNUSED(f); + return EndFieldHandlerWrapper2<C>(); +} + +template <class C, class D> +inline EndFieldHandlerWrapper3<C, D> MatchWrapper(bool (*f)(C *, const D *)) { + UPB_UNUSED(f); + return EndFieldHandlerWrapper3<C, D>(); +} + +inline EndFieldHandler MakeHandler(bool (*wrapper)(void *, const void *)) { + return EndFieldHandler::Make(wrapper, NULL, NULL); +} + +template <class C, class D> +inline EndFieldHandler BindHandler(bool (*wrapper)(void *, const void *), + bool (*h)(C *, const D *), D *data) { + UPB_UNUSED(h); // Only for making sure function matches "D". + return EndFieldHandler::Make(wrapper, data, MatchDeleter(data).Delete); +} + +// StartStringHandler +template <class R, class C> struct StartStringHandlerWrapper2 { + template <R *F(C *, size_t)> + inline static void *Wrapper(void *closure, const void *hd, size_t hint) { + UPB_UNUSED(hd); + return F(static_cast<C *>(closure), hint); + } +}; + +template <class R, class C, class D> struct StartStringHandlerWrapper3 { + template <R *F(C *, const D *, size_t)> + inline static void *Wrapper(void *closure, const void *hd, size_t hint) { + return F(static_cast<C *>(closure), static_cast<const D *>(hd), hint); + } +}; + +template <class R, class C> +inline StartStringHandlerWrapper2<R, C> MatchWrapper(R *(*f)(C *, size_t)) { + UPB_UNUSED(f); + return StartStringHandlerWrapper2<R, C>(); +} + +template <class R, class C, class D> +inline StartStringHandlerWrapper3<R, C, D> MatchWrapper(R *(*f)(C *, const D *, + size_t)) { + UPB_UNUSED(f); + return StartStringHandlerWrapper3<R, C, D>(); +} + +inline StartStringHandler MakeHandler(void *(*wrapper)(void *, const void *, + size_t)) { + return StartStringHandler::Make(wrapper, NULL, NULL); +} + +template <class R, class C, class D> +inline StartStringHandler BindHandler(void *(*wrapper)(void *, const void *, + size_t), + R *(*h)(C *, const D *, size_t), + D *data) { + UPB_UNUSED(h); // Only for making sure function matches "D". + return StartStringHandler::Make(wrapper, data, MatchDeleter(data).Delete); +} + +// StringHandler +template <class C> struct StringHandlerWrapper2 { + template <size_t F(C *, const char *buf, size_t len)> + inline static size_t Wrapper(void *closure, const void *hd, const char *buf, + size_t len) { + UPB_UNUSED(hd); + return F(static_cast<C *>(closure), buf, len); + } +}; + +template <class C, class D> struct StringHandlerWrapper3 { + template <size_t F(C *, const D *, const char *buf, size_t len)> + inline static size_t Wrapper(void *closure, const void *hd, const char *buf, + size_t len) { + return F(static_cast<C *>(closure), static_cast<const D *>(hd), buf, len); + } +}; + +template <class C> +inline StringHandlerWrapper2<C> MatchWrapper(size_t (*f)(C *, const char *, + size_t)) { + UPB_UNUSED(f); + return StringHandlerWrapper2<C>(); +} + +template <class C, class D> +inline StringHandlerWrapper3<C, D> MatchWrapper(size_t (*f)(C *, const D *, + const char *, + size_t)) { + UPB_UNUSED(f); + return StringHandlerWrapper3<C, D>(); +} + +inline StringHandler MakeHandler(size_t (*wrapper)(void *, const void *, + const char *, size_t)) { + return StringHandler::Make(wrapper, NULL, NULL); +} + +template <class C, class D> +inline StringHandler BindHandler( + size_t (*wrapper)(void *, const void *, const char *, size_t), + size_t (*h)(C *, const D *, const char *, size_t), D *data) { + UPB_UNUSED(h); // Only for making sure function matches "D". + return StringHandler::Make(wrapper, data, MatchDeleter(data).Delete); +} + +// utype/ltype are upper/lower-case, ctype is canonical C type, vtype is +// variant C type. +#define TYPE_METHODS(utype, ltype, ctype, vtype) \ + template <> struct CanonicalType<vtype> { \ + typedef ctype Type; \ + }; \ + template <> \ + inline bool Handlers::SetValueHandler<vtype>( \ + const FieldDef *f, \ + const typename ValueHandler<typename CanonicalType<vtype>::Type>::H & \ + handler) { \ + handler.registered_ = true; \ + return upb_handlers_set##ltype(this, f, handler.handler_, handler.data_, \ + handler.cleanup_); \ + } \ + template <> \ + inline bool Handlers::SetValueHandler<vtype>( \ + const char *f, const typename ValueHandler< \ + typename CanonicalType<vtype>::Type>::H &handler) { \ + handler.registered_ = true; \ + return upb_handlers_set##ltype##_n(this, f, handler.handler_, \ + handler.data_, handler.cleanup_); \ + } + +TYPE_METHODS(Double, double, double, double); +TYPE_METHODS(Float, float, float, float); +TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64_t); +TYPE_METHODS(UInt32, uint32, uint32_t, upb_uint32_t); +TYPE_METHODS(Int64, int64, int64_t, upb_int64_t); +TYPE_METHODS(Int32, int32, int32_t, upb_int32_t); +TYPE_METHODS(Bool, bool, bool, bool); + +#ifdef UPB_TWO_32BIT_TYPES +TYPE_METHODS(Int32, int32, int32_t, upb_int32alt_t); +TYPE_METHODS(Uint32, uint32, uint32_t, upb_uint32alt_t); +#endif + +#ifdef UPB_TWO_64BIT_TYPES +TYPE_METHODS(Int64, int64, int64_t, upb_int64alt_t); +TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64alt_t); +#endif +#undef TYPE_METHODS + +// Type methods that are only one-per-canonical-type and not one-per-cvariant. + +#define TYPE_METHODS(utype, ctype) \ + inline bool Handlers::Set##utype##Handler(const FieldDef *f, \ + const utype##Handler &h) { \ + return SetValueHandler<ctype>(f, h); \ + } \ + inline bool Handlers::Set##utype##Handler(const char *f, \ + const utype##Handler &h) { \ + return SetValueHandler<ctype>(f, h); \ + } + +TYPE_METHODS(Double, double); +TYPE_METHODS(Float, float); +TYPE_METHODS(UInt64, uint64_t); +TYPE_METHODS(UInt32, uint32_t); +TYPE_METHODS(Int64, int64_t); +TYPE_METHODS(Int32, int32_t); +TYPE_METHODS(Bool, bool); +#undef TYPE_METHODS + +template <class T1, bool F(T1*)> bool Wrapper1(void *p1) { + return F(static_cast<T1*>(p1)); +} +template <class T1, bool F(T1 *, upb::Status *)> +bool EndMessageWrapper(void *p1, upb::Status *s) { + return F(static_cast<T1 *>(p1), s); +} +inline Handlers *Handlers::New(const MessageDef *m, const FrameType *ft, + const void *owner) { + return upb_handlers_new(m, ft, owner); +} +inline const Handlers *Handlers::NewFrozen(const MessageDef *m, + const FrameType *ft, + const void *owner, + upb_handlers_callback *callback, + void *closure) { + return upb_handlers_newfrozen(m, ft, owner, callback, closure); +} +inline bool Handlers::IsFrozen() const { return upb_handlers_isfrozen(this); } +inline void Handlers::Ref(const void *owner) const { + upb_handlers_ref(this, owner); +} +inline void Handlers::Unref(const void *owner) const { + upb_handlers_unref(this, owner); +} +inline void Handlers::DonateRef(const void *from, const void *to) const { + upb_handlers_donateref(this, from, to); +} +inline void Handlers::CheckRef(const void *owner) const { + upb_handlers_checkref(this, owner); +} +inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) { + return upb_handlers_freeze(handlers, n, s); +} +inline const FrameType *Handlers::frame_type() const { + return upb_handlers_frametype(this); +} +inline const MessageDef *Handlers::message_def() const { + return upb_handlers_msgdef(this); +} +template <class T, bool F(T *)> void Handlers::SetStartMessageHandler() { + upb_handlers_setstartmsg(this, &Wrapper1<T, F>); +} +template <class T, bool F(T *, upb::Status *)> +void Handlers::SetEndMessageHandler() { + upb_handlers_setendmsg(this, &EndMessageWrapper<T, F>); +} +inline bool Handlers::SetStartStringHandler(const FieldDef *f, + const StartStringHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstartstr(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetEndStringHandler(const FieldDef *f, + const EndFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setendstr(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetStringHandler(const FieldDef *f, + const StringHandler& handler) { + handler.registered_ = true; + return upb_handlers_setstring(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetStartSequenceHandler( + const FieldDef *f, const StartFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstartseq(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetStartSubMessageHandler( + const FieldDef *f, const StartFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstartsubmsg(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f, + const EndFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setendsubmsg(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, + const EndFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setendseq(this, f, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) { + return upb_handlers_setsubhandlers(this, f, sub); +} +inline bool Handlers::SetStartStringHandler(const char *name, + const StartStringHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstartstr_n(this, name, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetEndStringHandler(const char *name, + const EndFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setendstr_n(this, name, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetStringHandler(const char *name, + const StringHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstring_n(this, name, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetStartSequenceHandler( + const char *name, const StartFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstartseq_n(this, name, handler.handler_, handler.data_, + handler.cleanup_); +} +inline bool Handlers::SetStartSubMessageHandler( + const char *name, const StartFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setstartsubmsg_n(this, name, handler.handler_, + handler.data_, handler.cleanup_); +} +inline bool Handlers::SetEndSubMessageHandler(const char *name, + const EndFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setendsubmsg_n(this, name, handler.handler_, + handler.data_, handler.cleanup_); +} +inline bool Handlers::SetEndSequenceHandler(const char *name, + const EndFieldHandler &handler) { + handler.registered_ = true; + return upb_handlers_setendseq_n(this, name, handler.handler_, handler.data_, + handler.cleanup_); +} +inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const { + return upb_handlers_getsubhandlers(this, f); +} +inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const { + return upb_handlers_getsubhandlers_sel(this, sel); +} +inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type, + Handlers::Selector *s) { + return upb_handlers_getselector(f, type, s); +} +inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) { + return upb_handlers_getendselector(start); +} +inline Handlers::GenericFunction *Handlers::GetHandler( + Handlers::Selector selector) { + return upb_handlers_gethandler(this, selector); +} +inline const void *Handlers::GetHandlerData(Handlers::Selector selector) { + return upb_handlers_gethandlerdata(this, selector); +} + +} // namespace upb + +#endif // __cplusplus + +#endif // UPB_HANDLERS_INL_H_ diff --git a/upb/handlers.c b/upb/handlers.c index b7458f2..6cbe6dc 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -3,6 +3,9 @@ * * Copyright (c) 2011-2012 Google Inc. See LICENSE for details. * Author: Josh Haberman <jhaberman@gmail.com> + * + * TODO(haberman): it's unclear whether a lot of the consistency checks should + * assert() or return false. */ #include "upb/handlers.h" @@ -16,106 +19,114 @@ // UPB_NO_CLOSURE. char _upb_noclosure; -static const upb_fieldhandler *getfh( - const upb_handlers *h, upb_selector_t selector) { - assert(selector < upb_handlers_msgdef(h)->selector_count); - upb_fieldhandler* fhbase = (void*)&h->fh_base; - return &fhbase[selector]; -} +typedef struct { + void (*func)(); + void *data; +} tabent; -static upb_fieldhandler *getfh_mutable(upb_handlers *h, - upb_selector_t selector) { - return (upb_fieldhandler*)getfh(h, selector); +static void freehandlers(upb_refcounted *r) { + upb_handlers *h = (upb_handlers*)r; + upb_msgdef_unref(h->msg, h); + for (size_t i = 0; i < h->cleanup_len; i++) { + h->cleanup[i].cleanup(h->cleanup[i].ptr); + } + free(h->cleanup); + free(h); } -bool upb_handlers_isfrozen(const upb_handlers *h) { - return upb_refcounted_isfrozen(upb_upcast(h)); +static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, + void *closure) { + const upb_handlers *h = (const upb_handlers*)r; + upb_msg_iter i; + for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + if (!upb_fielddef_issubmsg(f)) continue; + const upb_handlers *sub = upb_handlers_getsubhandlers(h, f); + if (sub) visit(r, upb_upcast(sub), closure); + } } -uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { - return upb_fielddef_isseq(f) ? 2 : 0; -} +static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; -uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { - uint32_t ret = 1; - if (upb_fielddef_isstring(f)) ret += 2; // [STARTSTR]/STRING/ENDSTR - if (upb_fielddef_isseq(f)) ret += 2; // STARTSEQ/ENDSEQ - if (upb_fielddef_issubmsg(f)) ret += 1; // [STARTSUBMSG]/ENDSUBMSG - return ret; -} +typedef struct { + upb_inttable tab; // maps upb_msgdef* -> upb_handlers*. + upb_handlers_callback *callback; + void *closure; +} dfs_state; -upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_ENUM: - return UPB_HANDLER_INT32; - case UPB_TYPE_INT64: - return UPB_HANDLER_INT64; - case UPB_TYPE_UINT32: - return UPB_HANDLER_UINT32; - case UPB_TYPE_UINT64: - return UPB_HANDLER_UINT64; - case UPB_TYPE_FLOAT: - return UPB_HANDLER_FLOAT; - case UPB_TYPE_DOUBLE: - return UPB_HANDLER_DOUBLE; - case UPB_TYPE_BOOL: - return UPB_HANDLER_BOOL; - default: assert(false); return -1; // Invalid input. +static upb_handlers *newformsg(const upb_msgdef *m, const upb_frametype *ft, + const void *owner, + dfs_state *s) { + upb_handlers *h = upb_handlers_new(m, ft, owner); + if (!h) return NULL; + if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom; + + s->callback(s->closure, h); + + // For each submessage field, get or create a handlers object and set it as + // the subhandlers. + upb_msg_iter i; + for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + if (!upb_fielddef_issubmsg(f)) continue; + + const upb_msgdef *subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); + upb_value subm_ent; + if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { + upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); + } else { + upb_handlers *sub_mh = newformsg(subdef, ft, &sub_mh, s); + if (!sub_mh) goto oom; + upb_handlers_setsubhandlers(h, f, sub_mh); + upb_handlers_unref(sub_mh, &sub_mh); + } } + return h; + +oom: + upb_handlers_unref(h, owner); + return NULL; } -bool upb_getselector( - const upb_fielddef *f, upb_handlertype_t type, upb_selector_t *s) { - // If the type checks in this function are a hot-spot, we can introduce a - // separate function that calculates the selector assuming that the type - // is correct (may even want to make it inline for the upb_sink fast-path. - switch (type) { - case UPB_HANDLER_INT32: - case UPB_HANDLER_INT64: - case UPB_HANDLER_UINT32: - case UPB_HANDLER_UINT64: - case UPB_HANDLER_FLOAT: - case UPB_HANDLER_DOUBLE: - case UPB_HANDLER_BOOL: - if (!upb_fielddef_isprimitive(f) || - upb_handlers_getprimitivehandlertype(f) != type) - return false; - *s = f->selector_base; - break; - case UPB_HANDLER_STRING: - if (!upb_fielddef_isstring(f)) return false; - *s = f->selector_base; - break; - case UPB_HANDLER_STARTSTR: - if (!upb_fielddef_isstring(f)) return false; - *s = f->selector_base + 1; - break; - case UPB_HANDLER_ENDSTR: - if (!upb_fielddef_isstring(f)) return false; - *s = f->selector_base + 2; - break; - case UPB_HANDLER_STARTSEQ: - if (!upb_fielddef_isseq(f)) return false; - *s = f->selector_base - 2; - break; - case UPB_HANDLER_ENDSEQ: - if (!upb_fielddef_isseq(f)) return false; - *s = f->selector_base - 1; - break; - case UPB_HANDLER_STARTSUBMSG: - if (!upb_fielddef_issubmsg(f)) return false; - *s = f->selector_base; - break; - case UPB_HANDLER_ENDSUBMSG: - if (!upb_fielddef_issubmsg(f)) return false; - *s = f->selector_base + 1; - break; +// This wastes a bit of space since the "func" member of this slot is unused, +// but the code is simpler. Worst-case overhead is 20% (messages with only +// non-repeated submessage fields). Can change later if necessary. +#define SUBH(h, field_base) h->table[field_base + 2].data + +static int32_t chkset(upb_handlers *h, const upb_fielddef *f, + upb_handlertype_t type) { + upb_selector_t sel; + assert(!upb_handlers_isfrozen(h)); + if (upb_handlers_msgdef(h) != upb_fielddef_msgdef(f)) return -1; + if (!upb_handlers_getselector(f, type, &sel)) return -1; + if (h->table[sel].func) return -1; + return sel; +} + +static bool addcleanup(upb_handlers *h, void *ptr, void (*cleanup)(void*)) { + if (h->cleanup_len == h->cleanup_size) { + h->cleanup_size = UPB_MAX(4, h->cleanup_size * 2); + void *resized = realloc(h->cleanup, sizeof(*h->cleanup) * h->cleanup_size); + if (!resized) { + h->cleanup_size = h->cleanup_len; + cleanup(ptr); + return false; + } + h->cleanup = resized; } - assert(*s < upb_fielddef_msgdef(f)->selector_count); + h->cleanup[h->cleanup_len].ptr = ptr; + h->cleanup[h->cleanup_len].cleanup = cleanup; + h->cleanup_len++; return true; } + +/* Public interface ***********************************************************/ + +bool upb_handlers_isfrozen(const upb_handlers *h) { + return upb_refcounted_isfrozen(upb_upcast(h)); +} + void upb_handlers_ref(const upb_handlers *h, const void *owner) { upb_refcounted_ref(upb_upcast(h), owner); } @@ -133,49 +144,20 @@ void upb_handlers_checkref(const upb_handlers *h, const void *owner) { upb_refcounted_checkref(upb_upcast(h), owner); } -static void do_cleanup(upb_handlers* h, const upb_fielddef *f, - upb_handlertype_t type) { - upb_selector_t selector; - if (!upb_getselector(f, type, &selector)) return; - upb_fieldhandler *fh = getfh_mutable(h, selector); - if (fh->cleanup) fh->cleanup(fh->data); - fh->cleanup = NULL; - fh->data = NULL; -} - -static void freehandlers(upb_refcounted *r) { - upb_handlers *h = (upb_handlers*)r; - upb_msg_iter i; - for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - for (upb_handlertype_t type = 0; type < UPB_HANDLER_MAX; type++) - do_cleanup(h, f, type); - } - upb_msgdef_unref(h->msg, h); - free(h); -} - -static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_handlers *h = (const upb_handlers*)r; - upb_msg_iter i; - for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - if (!upb_fielddef_issubmsg(f)) continue; - const upb_handlers *sub = upb_handlers_getsubhandlers(h, f); - if (sub) visit(r, upb_upcast(sub), closure); - } -} upb_handlers *upb_handlers_new(const upb_msgdef *md, const upb_frametype *ft, const void *owner) { assert(upb_msgdef_isfrozen(md)); - static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; - size_t fhandlers_size = sizeof(upb_fieldhandler) * md->selector_count; - upb_handlers *h = calloc(sizeof(*h) - sizeof(void*) + fhandlers_size, 1); + + int extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); + upb_handlers *h = calloc(sizeof(*h) + extra, 1); if (!h) return NULL; + h->msg = md; h->ft = ft; + h->cleanup = NULL; + h->cleanup_size = 0; + h->cleanup_len = 0; upb_msgdef_ref(h->msg, h); if (!upb_refcounted_init(upb_upcast(h), &vtbl, owner)) goto oom; @@ -187,95 +169,38 @@ oom: return NULL; } -bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { - // TODO: verify we have a transitive closure. - return upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s); -} - -const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } - -const upb_frametype *upb_handlers_frametype(const upb_handlers *h) { - return h->ft; -} - -void upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handler *handler) { - assert(!upb_handlers_isfrozen(h)); - h->startmsg = handler; -} - -upb_startmsg_handler *upb_handlers_getstartmsg(const upb_handlers *h) { - return h->startmsg; -} - -void upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handler *handler) { - assert(!upb_handlers_isfrozen(h)); - h->endmsg = handler; -} +const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, + const upb_frametype *ft, + const void *owner, + upb_handlers_callback *callback, + void *closure) { + dfs_state state; + state.callback = callback; + state.closure = closure; + if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; -upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h) { - return h->endmsg; -} + upb_handlers *ret = newformsg(m, ft, owner, &state); -// For now we stuff the subhandlers pointer into the fieldhandlers* -// corresponding to the UPB_HANDLER_STARTSUBMSG handler. -static const upb_handlers **subhandlersptr_sel(upb_handlers *h, - upb_selector_t startsubmsg) { - return &getfh_mutable(h, startsubmsg)->subhandlers; -} + upb_inttable_uninit(&state.tab); + if (!ret) return NULL; -static const upb_handlers **subhandlersptr(upb_handlers *h, - const upb_fielddef *f) { - assert(upb_fielddef_issubmsg(f)); - upb_selector_t selector; - bool ok = upb_getselector(f, UPB_HANDLER_STARTSUBMSG, &selector); + upb_refcounted *r = upb_upcast(ret); + bool ok = upb_refcounted_freeze(&r, 1, NULL); UPB_ASSERT_VAR(ok, ok); - return subhandlersptr_sel(h, selector); -} - -bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, - const upb_handlers *sub) { - assert(!upb_handlers_isfrozen(h)); - if (!upb_fielddef_issubmsg(f)) return false; - if (sub != NULL && - upb_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { - return false; - } - const upb_handlers **stored = subhandlersptr(h, f); - const upb_handlers *old = *stored; - if (old) upb_unref2(old, h); - *stored = sub; - if (sub) upb_ref2(sub, h); - return true; -} - -const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, - const upb_fielddef *f) { - const upb_handlers **stored = subhandlersptr((upb_handlers*)h, f); - return *stored; -} -const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, - upb_selector_t sel) { - const upb_handlers **stored = subhandlersptr_sel((upb_handlers*)h, sel); - return *stored; + return ret; } #define SETTER(name, handlerctype, handlertype) \ bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \ - handlerctype val, void *data, \ + handlerctype func, void *data, \ upb_handlerfree *cleanup) { \ - assert(!upb_handlers_isfrozen(h)); \ - if (upb_handlers_msgdef(h) != upb_fielddef_msgdef(f)) return false; \ - upb_selector_t selector; \ - bool ok = upb_getselector(f, handlertype, &selector); \ - if (!ok) return false; \ - do_cleanup(h, f, handlertype); \ - upb_fieldhandler *fh = getfh_mutable(h, selector); \ - fh->handler = (upb_func*)val; \ - fh->data = (upb_func*)data; \ - fh->cleanup = (upb_func*)cleanup; \ + int32_t sel = chkset(h, f, handlertype); \ + if (sel < 0 || (cleanup && !addcleanup(h, data, cleanup))) return false; \ + h->table[sel].func = (upb_func*)func; \ + h->table[sel].data = data; \ return true; \ - } \ + } SETTER(int32, upb_int32_handler*, UPB_HANDLER_INT32); SETTER(int64, upb_int64_handler*, UPB_HANDLER_INT64); @@ -292,133 +217,145 @@ SETTER(startsubmsg, upb_startfield_handler*, UPB_HANDLER_STARTSUBMSG); SETTER(endsubmsg, upb_endfield_handler*, UPB_HANDLER_ENDSUBMSG); SETTER(endseq, upb_endfield_handler*, UPB_HANDLER_ENDSEQ); -// Our current implementation of these "alt" functions is, according to the -// letter of the standard, undefined behavior, because we store the -// upb_int32_handler2* to memory and then read it back (and call it) as a -// upb_int32_handler*. Even though both function pointer types take 32-bit -// integer arguments, they are still technically different types (because one -// takes an "int" argument and one takes a "long" argument), and calling a -// function through a pointer to an incompatible type is undefined behavior. -// -// I think it is exceedingly unlikely that "int" and "long" would ever have -// incompatible calling conventions when both are known to be 32 bit signed -// two's complement integers. But if absolute standards-compliance is ever -// required, either due to a practical problem with the undefined behavior or a -// tool that notices the incongruity, we have an available option for being -// perfectly standard-compliant; we can store a bool for every function pointer -// indicating whether it is an "alt" pointer or not. Then at the call site -// (inside upb_sink) we can do: -// -// if (is_alt) { -// upb_int32_handler2 *func = fp; -// func(...); -// } else { -// upb_int32_handler *func = fp; -// func(...); -// } -// -// We could do this now, but it adds complexity and wastes the memory to store -// these useless bools. The bools are useless because the compiler will almost -// certainly optimize away this branch and elide the two calls into a single -// call with the 32-bit parameter calling convention. - -#ifdef UPB_TWO_32BIT_TYPES -SETTER(int32alt, upb_int32_handler2*, UPB_HANDLER_INT32); -SETTER(uint32alt, upb_uint32_handler2*, UPB_HANDLER_UINT32); -#endif - -#ifdef UPB_TWO_64BIT_TYPES -SETTER(int64alt, upb_int64_handler2*, UPB_HANDLER_INT64); -SETTER(uint64alt, upb_uint64_handler2*, UPB_HANDLER_UINT64); -#endif - #undef SETTER -upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s) { - return getfh(h, s)->handler; +bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, + const upb_handlers *sub) { + assert(sub); + assert(!upb_handlers_isfrozen(h)); + assert(upb_fielddef_issubmsg(f)); + if (SUBH(h, f->selector_base)) return false; // Can't reset. + if (upb_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { + return false; + } + SUBH(h, f->selector_base) = sub; + upb_ref2(sub, h); + return true; } -void *upb_handlers_gethandlerdata(const upb_handlers *h, upb_selector_t s) { - return getfh(h, s)->data; +const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, + const upb_fielddef *f) { + assert(upb_fielddef_issubmsg(f)); + return SUBH(h, f->selector_base); } -typedef struct { - upb_inttable tab; // maps upb_msgdef* -> upb_handlers*. - upb_handlers_callback *callback; - void *closure; -} dfs_state; +const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, + upb_selector_t sel) { + // STARTSUBMSG selector in sel is the field's selector base. + return SUBH(h, sel); +} -static upb_handlers *newformsg(const upb_msgdef *m, const upb_frametype *ft, - const void *owner, - dfs_state *s) { - upb_handlers *h = upb_handlers_new(m, ft, owner); - if (!h) return NULL; - if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom; +const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } - s->callback(s->closure, h); +const upb_frametype *upb_handlers_frametype(const upb_handlers *h) { + return h->ft; +} - // For each submessage field, get or create a handlers object and set it as - // the subhandlers. - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - if (!upb_fielddef_issubmsg(f)) continue; +void upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handler *handler) { + assert(!upb_handlers_isfrozen(h)); + h->startmsg = handler; +} - const upb_msgdef *subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); - upb_value subm_ent; - if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { - upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); - } else { - upb_handlers *sub_mh = newformsg(subdef, ft, &sub_mh, s); - if (!sub_mh) goto oom; - upb_handlers_setsubhandlers(h, f, sub_mh); - upb_handlers_unref(sub_mh, &sub_mh); - } - } - return h; +upb_startmsg_handler *upb_handlers_getstartmsg(const upb_handlers *h) { + return h->startmsg; +} -oom: - upb_handlers_unref(h, owner); - return NULL; +void upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handler *handler) { + assert(!upb_handlers_isfrozen(h)); + h->endmsg = handler; } -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const upb_frametype *ft, - const void *owner, - upb_handlers_callback *callback, - void *closure) { - dfs_state state; - state.callback = callback; - state.closure = closure; - if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; +upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h) { + return h->endmsg; +} - upb_handlers *ret = newformsg(m, ft, owner, &state); - if (!ret) return NULL; - upb_refcounted *r = upb_upcast(ret); - upb_status status = UPB_STATUS_INIT; - bool ok = upb_refcounted_freeze(&r, 1, &status); - UPB_ASSERT_VAR(ok, ok); - upb_status_uninit(&status); +upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s) { + return (upb_func *)h->table[s].func; +} - upb_inttable_uninit(&state.tab); - return ret; +const void *upb_handlers_gethandlerdata(const upb_handlers *h, + upb_selector_t s) { + return h->table[s].data; +} + +/* "Static" methods ***********************************************************/ + +bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { + // TODO: verify we have a transitive closure. + return upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s); +} + +upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: return UPB_HANDLER_INT32; + case UPB_TYPE_INT64: return UPB_HANDLER_INT64; + case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32; + case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64; + case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT; + case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE; + case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL; + default: assert(false); return -1; // Invalid input. + } +} + +bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, + upb_selector_t *s) { + switch (type) { + case UPB_HANDLER_INT32: + case UPB_HANDLER_INT64: + case UPB_HANDLER_UINT32: + case UPB_HANDLER_UINT64: + case UPB_HANDLER_FLOAT: + case UPB_HANDLER_DOUBLE: + case UPB_HANDLER_BOOL: + if (!upb_fielddef_isprimitive(f) || + upb_handlers_getprimitivehandlertype(f) != type) + return false; + *s = f->selector_base; + break; + case UPB_HANDLER_STRING: + if (!upb_fielddef_isstring(f)) return false; + *s = f->selector_base; + break; + case UPB_HANDLER_STARTSTR: + if (!upb_fielddef_isstring(f)) return false; + *s = f->selector_base + 1; + break; + case UPB_HANDLER_ENDSTR: + if (!upb_fielddef_isstring(f)) return false; + *s = f->selector_base + 2; + break; + case UPB_HANDLER_STARTSEQ: + if (!upb_fielddef_isseq(f)) return false; + *s = f->selector_base - 2; + break; + case UPB_HANDLER_ENDSEQ: + if (!upb_fielddef_isseq(f)) return false; + *s = f->selector_base - 1; + break; + case UPB_HANDLER_STARTSUBMSG: + if (!upb_fielddef_issubmsg(f)) return false; + *s = f->selector_base; + break; + case UPB_HANDLER_ENDSUBMSG: + if (!upb_fielddef_issubmsg(f)) return false; + *s = f->selector_base + 1; + break; + // Subhandler slot is selector_base + 2. + } + assert(*s < upb_fielddef_msgdef(f)->selector_count); + return true; } -#define STDMSG_WRITER(type, ctype) \ - bool upb_stdmsg_set ## type (const upb_sinkframe *frame, ctype val) { \ - const upb_stdmsg_fval *f = upb_sinkframe_handlerdata(frame); \ - uint8_t *m = upb_sinkframe_userdata(frame); \ - if (f->hasbit > 0) \ - *(uint8_t*)&m[f->hasbit / 8] |= 1 << (f->hasbit % 8); \ - *(ctype*)&m[f->offset] = val; \ - return true; \ - } \ - -STDMSG_WRITER(double, double) -STDMSG_WRITER(float, float) -STDMSG_WRITER(int32, int32_t) -STDMSG_WRITER(int64, int64_t) -STDMSG_WRITER(uint32, uint32_t) -STDMSG_WRITER(uint64, uint64_t) -STDMSG_WRITER(bool, bool) -#undef STDMSG_WRITER +uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) { + return upb_fielddef_isseq(f) ? 2 : 0; +} + +uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { + uint32_t ret = 1; + if (upb_fielddef_isseq(f)) ret += 2; // STARTSEQ/ENDSEQ + if (upb_fielddef_isstring(f)) ret += 2; // [STARTSTR]/STRING/ENDSTR + if (upb_fielddef_issubmsg(f)) ret += 2; // [STARTSUBMSG]/ENDSUBMSG/SUBH + return ret; +} diff --git a/upb/handlers.h b/upb/handlers.h index 79ca0d8..09743ff 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -25,24 +25,54 @@ #include "upb/def.h" #ifdef __cplusplus + struct upb_frametype; + namespace upb { + typedef upb_frametype FrameType; class Handlers; -class SinkFrame; -} + +template <class T> class Handler; +typedef Handler<void *(*)(void *, const void *)> StartFieldHandler; +typedef Handler<bool(*)(void *, const void *)> EndFieldHandler; +typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler; +typedef Handler<size_t(*)(void *, const void *, const char *, size_t)> + StringHandler; + +template <class T> struct ValueHandler { + typedef Handler<bool(*)(void *, const void *, T)> H; +}; + +typedef ValueHandler<upb_int32_t>::H Int32Handler; +typedef ValueHandler<upb_int64_t>::H Int64Handler; +typedef ValueHandler<upb_uint32_t>::H UInt32Handler; +typedef ValueHandler<upb_uint64_t>::H UInt64Handler; +typedef ValueHandler<float>::H FloatHandler; +typedef ValueHandler<double>::H DoubleHandler; +typedef ValueHandler<bool>::H BoolHandler; +template <class T> struct CanonicalType; + +} // namespace upb + typedef upb::FrameType upb_frametype; typedef upb::Handlers upb_handlers; -typedef upb::SinkFrame upb_sinkframe; -UPB_INLINE void *upb_sinkframe_handlerdata(const upb_sinkframe* frame); -#else + +#else // #ifdef __cplusplus + struct upb_frametype; struct upb_handlers; struct upb_sinkframe; typedef struct upb_frametype upb_frametype; typedef struct upb_handlers upb_handlers; typedef struct upb_sinkframe upb_sinkframe; -#endif + +#endif // #ifdef __cplusplus + +typedef struct { + void (*func)(); + const void *data; +} upb_handlers_tabent; // All the different types of handlers that can be registered. // Only needed for the advanced functions in upb::Handlers. @@ -83,49 +113,20 @@ typedef int32_t upb_selector_t; // parsing or visiting a message of a specific type. // // Any handlers that are not set behave as if they had successfully consumed -// the value. For start* handlers that return a void* closure, an unset handler -// will propagate the existing closure. +// the value. Any unset Start* handlers will propagate their closure to the +// inner frame. +// +// The easiest way to create the *Handler objects needed by the Set* methods is +// with the UpbBind() and UpbMakeHandler() macros; see below. class upb::Handlers { public: typedef upb_selector_t Selector; typedef upb_handlertype_t Type; - typedef bool StartMessageHandler(const SinkFrame*); - typedef void EndMessageHandler(const SinkFrame*, Status* status); - typedef void* StartFieldHandler(const SinkFrame*); - typedef bool EndFieldHandler(const SinkFrame*); - typedef void* StartStringHandler(const SinkFrame* c, size_t size_hint); - typedef size_t StringHandler(const SinkFrame* c, const char* buf, size_t len); - - template <class T> struct Value { - typedef bool Handler(const SinkFrame*, T val); - }; - - typedef Value<upb_int32_t>::Handler Int32Handler; - typedef Value<upb_int64_t>::Handler Int64Handler; - typedef Value<upb_uint32_t>::Handler UInt32Handler; - typedef Value<upb_uint64_t>::Handler UInt64Handler; - typedef Value<float>::Handler FloatHandler; - typedef Value<double>::Handler DoubleHandler; - typedef Value<bool>::Handler BoolHandler; - -#ifdef UPB_TWO_32BIT_TYPES - typedef Value<upb_int32alt_t>::Handler Int32Handler2; - typedef Value<upb_uint32alt_t>::Handler UInt32Handler2; -#endif - -#ifdef UPB_TWO_64BIT_TYPES - typedef Value<upb_int64alt_t>::Handler Int64Handler2; - typedef Value<upb_uint64alt_t>::Handler UInt64Handler2; -#endif - // Any function pointer can be converted to this and converted back to its // correct type. typedef void GenericFunction(); - // For freeing handler data. - typedef void Free(void *data); - typedef void HandlersCallback(void *closure, upb_handlers *h); // Returns a new handlers object for the given frozen msgdef that will use @@ -168,103 +169,83 @@ class upb::Handlers { // Sets the startmsg handler for the message, which is defined as follows: // - // bool startmsg(const upb::SinkFrame* frame) { + // bool startmsg(MyType* closure) { // // Called when the message begins. Returns true if processing should // // continue. // return true; // } - void SetStartMessageHandler(StartMessageHandler *handler); - StartMessageHandler *GetStartMessageHandler() const; + // + // TODO(haberman): change this to work with UpbMakeHandler and auto-deduce, + // like all of the field handlers. + template<class T, bool F(T*)> void SetStartMessageHandler(); // Sets the endmsg handler for the message, which is defined as follows: // - // void endmsg(const upb::SinkFrame* frame, upb_status *status) { + // bool endmsg(MyType* closure, upb_status *status) { // // Called when processing of this message ends, whether in success or // // failure. "status" indicates the final status of processing, and // // can also be modified in-place to update the final status. // } - void SetEndMessageHandler(EndMessageHandler *handler); - EndMessageHandler *GetEndMessageHandler() const; + // + // TODO(haberman): change this to work with UpbMakeHandler and auto-deduce, + // like all of the field handlers. + template<class T, bool F(T*, upb::Status*)> void SetEndMessageHandler(); // Sets the value handler for the given field, which is defined as follows // (this is for an int32 field; other field types will pass their native // C/C++ type for "val"): // - // bool value(const upb::SinkFrame *frame, upb_int32_t val) { + // bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) { // // Called when the field's value is encountered. "d" contains // // whatever data was bound to this field when it was registered. // // Returns true if processing should continue. // return true; // } // - // The value type must exactly match f->type(). - // For example, SetInt32Handler() may only be used for fields of type - // UPB_TYPE_INT32 and UPB_TYPE_ENUM. - // - // "d" is the data that will be bound to this callback and passed to it. - // If "fr" is non-NULL it will be run when the data is no longer needed. + // handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...))); // - // Returns "false" if "f" does not belong to this message or has the wrong - // type for this handler. + // The value type must exactly match f->type(). + // For example, a handler that takes an int32_t parameter may only be used for + // fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM. // - // NOTE: the prototype above uses "upb_int32_t" and not "int32_t" from - // stdint.h. For C++ any int32 typedef will work correctly thanks to - // function overloading on the function pointer type. But in C things are - // more complicated; "int" and "long" could both be 32-bit types, but the - // two are incompatible with each other when it comes to function pointers. - // Since we don't know what the underlying type of int32_t is, we have to - // define our own which we *do* know the underlying type of. The easiest - // and most portable choice is to define handlers in C with the upb_intXX_t - // types. - bool SetInt32Handler (const FieldDef* f, Int32Handler* h, void* d, Free* fr); - bool SetInt64Handler (const FieldDef* f, Int64Handler* h, void* d, Free* fr); - bool SetUInt32Handler(const FieldDef* f, UInt32Handler* h, void* d, Free* fr); - bool SetUInt64Handler(const FieldDef* f, UInt64Handler* h, void* d, Free* fr); - bool SetFloatHandler (const FieldDef* f, FloatHandler* h, void* d, Free* fr); - bool SetDoubleHandler(const FieldDef* f, DoubleHandler* h, void* d, Free* fr); - bool SetBoolHandler (const FieldDef* f, BoolHandler* h, void* d, Free* fr); + // Returns false if the handler failed to register; in this case the cleanup + // handler (if any) will be called immediately. + bool SetInt32Handler (const FieldDef* f, const Int32Handler& h); + bool SetInt64Handler (const FieldDef* f, const Int64Handler& h); + bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h); + bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h); + bool SetFloatHandler (const FieldDef* f, const FloatHandler& h); + bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h); + bool SetBoolHandler (const FieldDef* f, const BoolHandler& h); // Convenience versions that look up the field by name first. These return // false if no field with this name exists, or for any of the other reasons // that the FieldDef* version returns false. - bool SetInt32Handler (const char *name, Int32Handler* h, void* d, Free* fr); - bool SetInt64Handler (const char *name, Int64Handler* h, void* d, Free* fr); - bool SetUInt32Handler(const char *name, UInt32Handler* h, void* d, Free* fr); - bool SetUInt64Handler(const char *name, UInt64Handler* h, void* d, Free* fr); - bool SetFloatHandler (const char *name, FloatHandler* h, void* d, Free* fr); - bool SetDoubleHandler(const char *name, DoubleHandler* h, void* d, Free* fr); - bool SetBoolHandler (const char *name, BoolHandler* h, void* d, Free* fr); - - // On platforms where there are two 32-bit or 64-bit integer types, provide - // registration functions for both. Function overloading should make this - // all transparent to the user. -#ifdef UPB_TWO_32BIT_TYPES - bool SetInt32Handler (const FieldDef* f, Int32Handler2* h, void* d, Free* x); - bool SetUInt32Handler(const FieldDef* f, UInt32Handler2* h, void* d, Free* x); - bool SetInt32Handler (const char *name, Int32Handler2* h, void* d, Free* x); - bool SetUInt32Handler(const char *name, UInt32Handler2* h, void* d, Free* x); -#endif - -#ifdef UPB_TWO_64BIT_TYPES - bool SetInt64Handler (const FieldDef* f, Int64Handler2* h, void* d, Free* x); - bool SetUInt64Handler(const FieldDef* f, UInt64Handler2* h, void* d, Free* x); - bool SetInt64Handler (const char *name, Int64Handler2* h, void* d, Free* x); - bool SetUInt64Handler(const char *name, UInt64Handler2* h, void* d, Free* x); -#endif - - // Like the above, but these are templated on the type of the value. For - // example, templating on int64_t is equivalent to calling SetInt64Handler. - // Attempts to template on a type that does not map to a UPB_TYPE_* type - // (like int8_t, since protobufs have no 8-bit type) will get an "undefined - // function" compilation error. - template<class T> bool SetValueHandler( - const FieldDef* f, typename Value<T>::Handler* h, void* d, Free* fr); - template<class T> bool SetValueHandler( - const char* name, typename Value<T>::Handler* h, void* d, Free* fr); + bool SetInt32Handler (const char *name, const Int32Handler& h); + bool SetInt64Handler (const char *name, const Int64Handler& h); + bool SetUInt32Handler(const char *name, const UInt32Handler& h); + bool SetUInt64Handler(const char *name, const UInt64Handler& h); + bool SetFloatHandler (const char *name, const FloatHandler& h); + bool SetDoubleHandler(const char *name, const DoubleHandler& h); + bool SetBoolHandler (const char *name, const BoolHandler& h); + + // Like the previous, but templated on the type on the value (ie. int32). + // This is mostly useful to call from other templates. To call this you must + // specify the template parameter explicitly, ie: + // h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); + template <class T> + bool SetValueHandler( + const FieldDef *f, + const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler); + template <class T> + bool SetValueHandler( + const char *name, + const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler); // Sets handlers for a string field, which are defined as follows: // - // void* startstr(const upb::SinkFrame *frame, size_t size_hint) { + // MySubClosure* startstr(MyClosure* c, const MyHandlerData* d, + // size_t size_hint) { // // Called when a string value begins. The return value indicates the // // closure for the string. "size_hint" indicates the size of the // // string if it is known, however if the string is length-delimited @@ -279,7 +260,8 @@ class upb::Handlers { // return closure; // } // - // size_t str(const upb::SinkFrame* frame, const char *str, size_t len) { + // size_t str(MyClosure* closure, const MyHandlerData* d, + // const char *str, size_t len) { // // Called for each buffer of string data; the multiple physical buffers // // are all part of the same logical string. The return value indicates // // how many bytes were consumed. If this number is less than "len", @@ -290,98 +272,80 @@ class upb::Handlers { // return len; // } // - // bool endstr(const upb::SinkFrame* frame) { - // // Called when a string value ends. + // bool endstr(MyClosure* c, const MyHandlerData* d) { + // // Called when a string value ends. Return value indicates whether + // // processing should continue. // return true; // } - bool SetStartStringHandler(const FieldDef* f, StartStringHandler* h, - void* d, Free* fr); - bool SetStringHandler(const FieldDef* f, StringHandler* h, void* d, Free* fr); - bool SetEndStringHandler(const FieldDef* f, EndFieldHandler* h, - void* d, Free* fr); + bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h); + bool SetStringHandler(const FieldDef* f, const StringHandler& h); + bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h); // Convenience versions that look up the field by name first. These return // false if no field with this name exists, or for any of the other reasons // that the FieldDef* version returns false. - bool SetStartStringHandler(const char* name, StartStringHandler* h, - void* d, Free* fr); - bool SetStringHandler(const char* name, StringHandler* h, void* d, Free* fr); - bool SetEndStringHandler(const char* name, EndFieldHandler* h, - void* d, Free* fr); + bool SetStartStringHandler(const char* name, const StartStringHandler& h); + bool SetStringHandler(const char* name, const StringHandler& h); + bool SetEndStringHandler(const char* name, const EndFieldHandler& h); // Sets the startseq handler, which is defined as follows: // - // void *startseq(const upb::SinkFrame* frame) { + // MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) { // // Called when a sequence (repeated field) begins. The returned // // pointer indicates the closure for the sequence (or UPB_BREAK // // to interrupt processing). // return closure; // } // + // h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...))); + // // Returns "false" if "f" does not belong to this message or is not a // repeated field. - // - // "data" is the data that will be bound to this callback and passed to it. - // If "cleanup" is non-NULL it will be run when the data is no longer needed. - bool SetStartSequenceHandler(const FieldDef* f, StartFieldHandler *handler, - void* data, Free* cleanup); - bool SetStartSequenceHandler(const char* name, StartFieldHandler *handler, - void* data, Free* cleanup); + bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h); + bool SetStartSequenceHandler(const char* name, const StartFieldHandler& h); // Sets the startsubmsg handler for the given field, which is defined as // follows: // - // void *startsubmsg(const upb::SinkFrame *frame) { + // MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) { // // Called when a submessage begins. The returned pointer indicates the // // closure for the sequence (or UPB_BREAK to interrupt processing). // return closure; // } // - // "data" is the data that will be bound to this callback and passed to it. - // If "cleanup" is non-NULL it will be run when the data is no longer needed. + // h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, + // new MyHandlerData(...))); // // Returns "false" if "f" does not belong to this message or is not a // submessage/group field. - bool SetStartSubMessageHandler(const FieldDef* f, StartFieldHandler *handler, - void* data, Free* cleanup); - bool SetStartSubMessageHandler(const char* name, StartFieldHandler *handler, - void* data, Free* cleanup); + bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h); + bool SetStartSubMessageHandler(const char* name, const StartFieldHandler& h); // Sets the endsubmsg handler for the given field, which is defined as // follows: // - // bool endsubmsg(const upb::SinkFrame *frame) { + // bool endsubmsg(MyClosure* c, const MyHandlerData* d) { // // Called when a submessage ends. Returns true to continue processing. // return true; // } // - // "data" is the data that will be bound to this callback and passed to it. - // If "cleanup" is non-NULL it will be run when the data is no longer needed. - // // Returns "false" if "f" does not belong to this message or is not a // submessage/group field. - bool SetEndSubMessageHandler(const FieldDef* f, EndFieldHandler *handler, - void* data, Free* cleanup); - bool SetEndSubMessageHandler(const char* name, EndFieldHandler *handler, - void* data, Free* cleanup); + bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h); + bool SetEndSubMessageHandler(const char *name, const EndFieldHandler &h); // Starts the endsubseq handler for the given field, which is defined as // follows: // - // bool endseq(const upb::SinkFrame *frame) { + // bool endseq(MyClosure* c, const MyHandlerData* d) { // // Called when a sequence ends. Returns true continue processing. // return true; // } // - // "data" is the data that will be bound to this callback and passed to it. - // If "cleanup" is non-NULL it will be run when the data is no longer needed. - // // Returns "false" if "f" does not belong to this message or is not a // repeated field. - bool SetEndSequenceHandler(const FieldDef* f, EndFieldHandler *handler, - void* data, Free* cleanup); - bool SetEndSequenceHandler(const char* name, EndFieldHandler *handler, - void* data, Free* cleanup); + bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h); + bool SetEndSequenceHandler(const char* name, const EndFieldHandler& h); // Sets or gets the object that specifies handlers for the given field, which // must be a submessage or group. Returns NULL if no handlers are set. @@ -408,11 +372,7 @@ class upb::Handlers { GenericFunction* GetHandler(Selector selector); // Returns the handler data that was registered with this handler. - void* GetHandlerData(Selector selector); - - // Gets the byte offset from a Handlers* where the given handler can be found. - // Useful for JITs that want to read the pointer in their fast path. - static size_t GetHandlerOffset(Selector selector); + const void* GetHandlerData(Selector selector); // Could add any of the following functions as-needed, with some minor // implementation changes: @@ -422,7 +382,6 @@ class upb::Handlers { private: UPB_DISALLOW_POD_OPS(Handlers); - friend void* ::upb_sinkframe_handlerdata(const upb_sinkframe* frame); #else struct upb_handlers { @@ -430,43 +389,175 @@ struct upb_handlers { upb_refcounted base; const upb_msgdef *msg; const upb_frametype *ft; - bool (*startmsg)(const upb_sinkframe*); - void (*endmsg)(const upb_sinkframe*, upb_status*); - void *fh_base[1]; // Start of dynamically-sized field handler array. + bool (*startmsg)(void*); + bool (*endmsg)(void*, upb_status*); + struct { + void *ptr; + void (*cleanup)(void*); + } *cleanup; + size_t cleanup_len, cleanup_size; + upb_handlers_tabent table[1]; // Dynamically-sized field handler array. }; -// Native C API. #ifdef __cplusplus + +namespace upb { + +// Convenience macros for creating a Handler object that is wrapped with a +// type-safe wrapper function that converts the "void*" parameters/returns +// of the underlying C API into nice C++ function. +// +// Sample usage: +// bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) { +// // do stuff ... +// return true; +// } +// +// // Handler that doesn't need any data bound to it. +// bool OnValue(MyClosure* c, int32_t val) { +// // do stuff ... +// return true; +// } +// +// // Takes ownership of the MyHandlerData. +// handlers->SetInt32Handler(f1, UpbBind(OnValue, new MyHandlerData(...))); +// handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue)); + +#ifdef UPB_CXX11 + +// In C++11, the "template" disambiguator can appear even outside templates, +// so all calls can safely use this pair of macros. + +#define UpbMakeHandler(f) \ + upb::MakeHandler(upb::MatchWrapper(f).template Wrapper<f>) + +// We have to be careful to only evaluate "d" once. +#define UpbBind(f, d) \ + upb::BindHandler(upb::MatchWrapper(f).template Wrapper<f>, f, (d)) + +#else + +// Prior to C++11, the "template" disambiguator may only appear inside a +// template, so the regular macro must not use "template" + +#define UpbMakeHandler(f) \ + upb::MakeHandler(upb::MatchWrapper(f).Wrapper<f>) + +#define UpbBind(f, d) \ + upb::BindHandler(upb::MatchWrapper(f).Wrapper<f>, f, (d)) + +#endif // UPB_CXX11 + +// This macro must be used in C++98 for calls from inside a template. But we +// define this variant in all cases; code that wants to be compatible with both +// C++98 and C++11 should always use this macro when calling from a template. +#define UpbMakeHandlerT(f) \ + upb::MakeHandler(upb::MatchWrapper(f).template Wrapper<f>) + +#define UpbBindT(f, d) \ + upb::BindHandler(upb::MatchWrapper(f).template Wrapper<f>, f, (d)) + + +// FieldHandler: a struct that contains the (handler, data, deleter) tuple that +// is used by all field-level handlers. Users could Make() these directly but +// it's more convenient to use the Upb{Bind,Make}ValueHandler macros. +// +// This class is intentionally not copyable or assignable; it can only be +// constructed as a temporary object with Make() and then must be registered as +// a handler (this is enforced with the assert() in the destructor). +template <class T> class Handler { + public: + // The underlying, non-type-safe handler function signature that upb uses + // internally. + typedef T FuncPtr; + + ~Handler() { assert(registered_); } + + static Handler<T> Make(FuncPtr h, void* hd, void (*fr)(void*)) { + return Handler<T>(h, hd, fr); + } + + private: + friend class Handlers; + + Handler(FuncPtr h, void *d, void (*c)(void *)) + : handler_(h), data_(d), cleanup_(c), registered_(false) {} + Handler(const Handler&); + void operator=(const Handler&); + + FuncPtr handler_; + void *data_; + void (*cleanup_)(void*); + mutable bool registered_; + + // Noisy friend declarations; these are all of the "Bind" functions, + // two for each type of handler. They need to be friends so that + // they can call the copy constructor to return a temporary. + + template <class T1> + friend typename ValueHandler<T1>::H MakeHandler(bool (*wrapper)(void *, + const void *, + T1)); + + template <class C, class D, class T1, class T2> + friend typename ValueHandler<T1>::H BindHandler( + bool (*wrapper)(void *, const void *, T1), bool (*h)(C *, const D *, T2), + D *data); + + friend StartFieldHandler MakeHandler(void* (*wrapper)(void *, const void *)); + + template <class R, class C, class D> + friend StartFieldHandler BindHandler(void *(*wrapper)(void *, const void *), + R *(*h)(C *, const D *), D *data); + + friend EndFieldHandler MakeHandler(bool (*wrapper)(void *, const void *)); + + template <class C, class D> + friend EndFieldHandler BindHandler(bool (*wrapper)(void *, const void *), + bool (*h)(C *, const D *), D *data); + + friend StringHandler MakeHandler(size_t (*wrapper)(void *, const void *, + const char *, size_t)); + + template <class C, class D> + friend StringHandler BindHandler( + size_t (*wrapper)(void *, const void *, const char *, size_t), + size_t (*h)(C *, const D *, const char *, size_t), D *data); + + friend StartStringHandler MakeHandler(void *(*wrapper)(void *, const void *, + size_t)); + + template <class R, class C, class D> + friend StartStringHandler BindHandler(void *(*wrapper)(void *, const void *, + size_t), + R *(*h)(C *, const D *, size_t), + D *data); +}; + +} // namespace upb + extern "C" { -#endif -typedef bool upb_startmsg_handler(const upb_sinkframe *frame); -typedef void upb_endmsg_handler(const upb_sinkframe *frame, upb_status *status); -typedef void* upb_startfield_handler(const upb_sinkframe *frame); -typedef bool upb_endfield_handler(const upb_sinkframe *frame); +#endif // __cplusplus + +// Native C API. typedef void upb_handlers_callback(void *closure, upb_handlers *h); typedef void upb_handlerfree(void *d); typedef void upb_func(); -typedef bool upb_int32_handler(const upb_sinkframe *f, upb_int32_t val); -typedef bool upb_int64_handler(const upb_sinkframe *f, upb_int64_t val); -typedef bool upb_uint32_handler(const upb_sinkframe *f, upb_uint32_t val); -typedef bool upb_uint64_handler(const upb_sinkframe *f, upb_uint64_t val); -typedef bool upb_float_handler(const upb_sinkframe *f, float val); -typedef bool upb_double_handler(const upb_sinkframe *f, double val); -typedef bool upb_bool_handler(const upb_sinkframe *f, bool val); -typedef void* upb_startstr_handler(const upb_sinkframe *f, size_t size_hint); -typedef size_t upb_string_handler( - const upb_sinkframe *f, const char *buf, size_t n); - -#ifdef UPB_TWO_32BIT_TYPES -typedef bool upb_int32_handler2(const upb_sinkframe *f, upb_int32alt_t val); -typedef bool upb_uint32_handler2(const upb_sinkframe *f, upb_uint32alt_t val); -#endif - -#ifdef UPB_TWO_64BIT_TYPES -typedef bool upb_int64_handler2(const upb_sinkframe *f, upb_int64alt_t val); -typedef bool upb_uint64_handler2(const upb_sinkframe *f, upb_uint64alt_t val); -#endif +typedef bool upb_startmsg_handler(void *c); +typedef bool upb_endmsg_handler(void *c, upb_status *status); +typedef void* upb_startfield_handler(void *c, const void *hd); +typedef bool upb_endfield_handler(void *c, const void *hd); +typedef bool upb_int32_handler(void *c, const void *hd, int32_t val); +typedef bool upb_int64_handler(void *c, const void *hd, int64_t val); +typedef bool upb_uint32_handler(void *c, const void *hd, uint32_t val); +typedef bool upb_uint64_handler(void *c, const void *hd, uint64_t val); +typedef bool upb_float_handler(void *c, const void *hd, float val); +typedef bool upb_double_handler(void *c, const void *hd, double val); +typedef bool upb_bool_handler(void *c, const void *hd, bool val); +typedef void* upb_startstr_handler(void *c, const void *hd, size_t size_hint); +typedef size_t upb_string_handler(void *c, const void *hd, const char *buf, + size_t n); upb_handlers *upb_handlers_new(const upb_msgdef *m, const upb_frametype *ft, @@ -478,95 +569,79 @@ const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, void *closure); // From upb_refcounted. -void upb_handlers_unref(const upb_handlers *h, const void *owner); bool upb_handlers_isfrozen(const upb_handlers *h); void upb_handlers_ref(const upb_handlers *h, const void *owner); -void upb_handlers_donateref( - const upb_handlers *h, const void *from, const void *to); +void upb_handlers_unref(const upb_handlers *h, const void *owner); +void upb_handlers_donateref(const upb_handlers *h, const void *from, + const void *to); void upb_handlers_checkref(const upb_handlers *h, const void *owner); -bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s); const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); const upb_frametype *upb_handlers_frametype(const upb_handlers *h); void upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handler *handler); upb_startmsg_handler *upb_handlers_getstartmsg(const upb_handlers *h); void upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handler *handler); upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h); -bool upb_handlers_setint32( - upb_handlers *h, const upb_fielddef *f, upb_int32_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setint64( - upb_handlers *h, const upb_fielddef *f, upb_int64_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setuint32( - upb_handlers *h, const upb_fielddef *f, upb_uint32_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setuint64( - upb_handlers *h, const upb_fielddef *f, upb_uint64_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setfloat( - upb_handlers *h, const upb_fielddef *f, upb_float_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setdouble( - upb_handlers *h, const upb_fielddef *f, upb_double_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setbool( - upb_handlers *h, const upb_fielddef *f, upb_bool_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setstartstr( - upb_handlers *h, const upb_fielddef *f, upb_startstr_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setstring( - upb_handlers *h, const upb_fielddef *f, upb_string_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setendstr( - upb_handlers *h, const upb_fielddef *f, upb_endfield_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setstartseq( - upb_handlers *h, const upb_fielddef *f, upb_startfield_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setstartsubmsg( - upb_handlers *h, const upb_fielddef *f, upb_startfield_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setendsubmsg( - upb_handlers *h, const upb_fielddef *f, upb_endfield_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setendseq( - upb_handlers *h, const upb_fielddef *f, upb_endfield_handler *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setsubhandlers( - upb_handlers *h, const upb_fielddef *f, const upb_handlers *sub); -const upb_handlers *upb_handlers_getsubhandlers( - const upb_handlers *h, const upb_fielddef *f); -const upb_handlers *upb_handlers_getsubhandlers_sel( - const upb_handlers *h, upb_selector_t sel); +bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f, + upb_int32_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f, + upb_int64_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f, + upb_uint32_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f, + upb_uint64_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f, + upb_float_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f, + upb_double_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f, + upb_bool_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f, + upb_startstr_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f, + upb_string_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f, + upb_endfield_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f, + upb_startfield_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f, + upb_startfield_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f, + upb_endfield_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f, + upb_endfield_handler *handler, void *d, + upb_handlerfree *fr); +bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, + const upb_handlers *sub); +const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, + const upb_fielddef *f); +const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, + upb_selector_t sel); +upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s); +const void *upb_handlers_gethandlerdata(const upb_handlers *h, + upb_selector_t s); + +// "Static" methods +bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s); upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); -bool upb_getselector( - const upb_fielddef *f, upb_handlertype_t type, upb_selector_t *s); -UPB_INLINE upb_selector_t upb_getendselector(upb_selector_t start) { +bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, + upb_selector_t *s); +UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { return start + 1; } -upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s); -void *upb_handlers_gethandlerdata(const upb_handlers *h, upb_selector_t s); -size_t upb_gethandleroffset(upb_selector_t s); - -#ifdef UPB_TWO_32BIT_TYPES -bool upb_handlers_setint32alt( - upb_handlers *h, const upb_fielddef *f, upb_int32_handler2 *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setuint32alt( - upb_handlers *h, const upb_fielddef *f, upb_uint32_handler2 *handler, - void *d, upb_handlerfree *fr); -#endif - -#ifdef UPB_TWO_64BIT_TYPES -bool upb_handlers_setint64alt( - upb_handlers *h, const upb_fielddef *f, upb_int64_handler2 *handler, - void *d, upb_handlerfree *fr); -bool upb_handlers_setuint64alt( - upb_handlers *h, const upb_fielddef *f, upb_uint64_handler2 *handler, - void *d, upb_handlerfree *fr); -#endif // Internal-only. uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); @@ -599,414 +674,8 @@ DEFINE_NAME_SETTER(startsubmsg, upb_startfield_handler*); DEFINE_NAME_SETTER(endsubmsg, upb_endfield_handler*); DEFINE_NAME_SETTER(endseq, upb_endfield_handler*); -#ifdef UPB_TWO_32BIT_TYPES -DEFINE_NAME_SETTER(int32alt, upb_int32_handler2*); -DEFINE_NAME_SETTER(uint32alt, upb_uint32_handler2*); -#endif - -#ifdef UPB_TWO_64BIT_TYPES -DEFINE_NAME_SETTER(int64alt, upb_int64_handler2*); -DEFINE_NAME_SETTER(uint64alt, upb_uint64_handler2*); -#endif - #undef DEFINE_NAME_SETTER -// Value writers for every in-memory type: write the data to a known offset -// from the closure "c." These depend on the fval being a pointer to a -// structure that is (or begins with) the upb_stdmsg_fval type. -// -// TODO(haberman): These are hacky; remove them and replace with an API that -// lets you set a simple "writer" handler in a way that can generate -// specialized code right then. - -typedef struct upb_stdmsg_fval { -#ifdef __cplusplus - upb_stdmsg_fval(size_t offset_, int32_t hasbit_) - : offset(offset_), - hasbit(hasbit_) { - } -#endif - size_t offset; - int32_t hasbit; -} upb_stdmsg_fval; - -#ifdef __cplusplus -extern "C" { -#endif -bool upb_stdmsg_setint32(const upb_sinkframe *frame, int32_t val); -bool upb_stdmsg_setint64(const upb_sinkframe *frame, int64_t val); -bool upb_stdmsg_setuint32(const upb_sinkframe *frame, uint32_t val); -bool upb_stdmsg_setuint64(const upb_sinkframe *frame, uint64_t val); -bool upb_stdmsg_setfloat(const upb_sinkframe *frame, float val); -bool upb_stdmsg_setdouble(const upb_sinkframe *frame, double val); -bool upb_stdmsg_setbool(const upb_sinkframe *frame, bool val); -#ifdef __cplusplus -} // extern "C" -#endif - -#ifdef __cplusplus - -namespace upb { - -// This function should be specialized by types that have a FrameType. -template<class T> inline const FrameType* GetFrameType() { return NULL; } - -// C++ Wrappers -inline Handlers* Handlers::New(const MessageDef* m, const FrameType* ft, - const void *owner) { - return upb_handlers_new(m, ft, owner); -} -inline const Handlers* Handlers::NewFrozen( - const MessageDef *m, const FrameType* ft, const void *owner, - upb_handlers_callback *callback, void *closure) { - return upb_handlers_newfrozen(m, ft, owner, callback, closure); -} -inline bool Handlers::IsFrozen() const { - return upb_handlers_isfrozen(this); -} -inline void Handlers::Ref(const void* owner) const { - upb_handlers_ref(this, owner); -} -inline void Handlers::Unref(const void* owner) const { - upb_handlers_unref(this, owner); -} -inline void Handlers::DonateRef(const void *from, const void *to) const { - upb_handlers_donateref(this, from, to); -} -inline void Handlers::CheckRef(const void *owner) const { - upb_handlers_checkref(this, owner); -} -inline bool Handlers::Freeze(Handlers*const* handlers, int n, Status* s) { - return upb_handlers_freeze(handlers, n, s); -} -inline const FrameType* Handlers::frame_type() const { - return upb_handlers_frametype(this); -} -inline const MessageDef* Handlers::message_def() const { - return upb_handlers_msgdef(this); -} -inline void Handlers::SetStartMessageHandler( - Handlers::StartMessageHandler *handler) { - upb_handlers_setstartmsg(this, handler); -} -inline void Handlers::SetEndMessageHandler( - Handlers::EndMessageHandler *handler) { - upb_handlers_setendmsg(this, handler); -} -inline bool Handlers::SetInt32Handler( - const FieldDef *f, Handlers::Int32Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint32(this, f, handler, d, fr); -} -inline bool Handlers::SetInt64Handler( - const FieldDef *f, Handlers::Int64Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint64(this, f, handler, d, fr); -} -inline bool Handlers::SetUInt32Handler( - const FieldDef *f, Handlers::UInt32Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint32(this, f, handler, d, fr); -} -inline bool Handlers::SetUInt64Handler( - const FieldDef *f, Handlers::UInt64Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint64(this, f, handler, d, fr); -} -inline bool Handlers::SetFloatHandler( - const FieldDef *f, Handlers::FloatHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setfloat(this, f, handler, d, fr); -} -inline bool Handlers::SetDoubleHandler( - const FieldDef *f, Handlers::DoubleHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setdouble(this, f, handler, d, fr); -} -inline bool Handlers::SetBoolHandler( - const FieldDef *f, Handlers::BoolHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setbool(this, f, handler, d, fr); -} -inline bool Handlers::SetStartStringHandler( - const FieldDef* f, Handlers::StartStringHandler* handler, - void* d, Handlers::Free* fr) { - return upb_handlers_setstartstr(this, f, handler, d, fr); -} -inline bool Handlers::SetEndStringHandler( - const FieldDef* f, Handlers::EndFieldHandler* handler, - void* d, Handlers::Free* fr) { - return upb_handlers_setendstr(this, f, handler, d, fr); -} -inline bool Handlers::SetStringHandler( - const FieldDef *f, Handlers::StringHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setstring(this, f, handler, d, fr); -} -inline bool Handlers::SetStartSequenceHandler( - const FieldDef* f, Handlers::StartFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setstartseq(this, f, handler, d, fr); -} -inline bool Handlers::SetStartSubMessageHandler( - const FieldDef* f, Handlers::StartFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setstartsubmsg(this, f, handler, d, fr); -} -inline bool Handlers::SetEndSubMessageHandler( - const FieldDef* f, Handlers::EndFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setendsubmsg(this, f, handler, d, fr); -} -inline bool Handlers::SetEndSequenceHandler( - const FieldDef* f, Handlers::EndFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setendseq(this, f, handler, d, fr); -} -inline bool Handlers::SetSubHandlers( - const FieldDef* f, const Handlers* sub) { - return upb_handlers_setsubhandlers(this, f, sub); -} -inline bool Handlers::SetInt32Handler( - const char* name, Handlers::Int32Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint32_n(this, name, handler, d, fr); -} -inline bool Handlers::SetInt64Handler( - const char* name, Handlers::Int64Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint64_n(this, name, handler, d, fr); -} -inline bool Handlers::SetUInt32Handler( - const char* name, Handlers::UInt32Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint32_n(this, name, handler, d, fr); -} -inline bool Handlers::SetUInt64Handler( - const char* name, Handlers::UInt64Handler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint64_n(this, name, handler, d, fr); -} -inline bool Handlers::SetFloatHandler( - const char* name, Handlers::FloatHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setfloat_n(this, name, handler, d, fr); -} -inline bool Handlers::SetDoubleHandler( - const char* name, Handlers::DoubleHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setdouble_n(this, name, handler, d, fr); -} -inline bool Handlers::SetBoolHandler( - const char* name, Handlers::BoolHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setbool_n(this, name, handler, d, fr); -} -inline bool Handlers::SetStartStringHandler( - const char* name, Handlers::StartStringHandler* handler, - void* d, Handlers::Free* fr) { - return upb_handlers_setstartstr_n(this, name, handler, d, fr); -} -inline bool Handlers::SetEndStringHandler( - const char* name, Handlers::EndFieldHandler* handler, - void* d, Handlers::Free* fr) { - return upb_handlers_setendstr_n(this, name, handler, d, fr); -} -inline bool Handlers::SetStringHandler( - const char* name, Handlers::StringHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setstring_n(this, name, handler, d, fr); -} -inline bool Handlers::SetStartSequenceHandler( - const char* name, Handlers::StartFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setstartseq_n(this, name, handler, d, fr); -} -inline bool Handlers::SetStartSubMessageHandler( - const char* name, Handlers::StartFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setstartsubmsg_n(this, name, handler, d, fr); -} -inline bool Handlers::SetEndSubMessageHandler( - const char* name, Handlers::EndFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setendsubmsg_n(this, name, handler, d, fr); -} -inline bool Handlers::SetEndSequenceHandler( - const char* name, Handlers::EndFieldHandler *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setendseq_n(this, name, handler, d, fr); -} -inline Handlers::StartMessageHandler *Handlers::GetStartMessageHandler() const { - return upb_handlers_getstartmsg(this); -} -inline Handlers::EndMessageHandler *Handlers::GetEndMessageHandler() const { - return upb_handlers_getendmsg(this); -} -inline const Handlers* Handlers::GetSubHandlers( - const FieldDef* f) const { - return upb_handlers_getsubhandlers(this, f); -} -inline const Handlers* Handlers::GetSubHandlers( - Handlers::Selector sel) const { - return upb_handlers_getsubhandlers_sel(this, sel); -} -inline bool Handlers::GetSelector( - const FieldDef* f, Handlers::Type type, Handlers::Selector* s) { - return upb_getselector(f, type, s); -} -inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) { - return upb_getendselector(start); -} -inline Handlers::GenericFunction* Handlers::GetHandler( - Handlers::Selector selector) { - return upb_handlers_gethandler(this, selector); -} -inline void* Handlers::GetHandlerData(Handlers::Selector selector) { - return upb_handlers_gethandlerdata(this, selector); -} -inline size_t Handlers::GetHandlerOffset(Handlers::Selector selector) { - return upb_gethandleroffset(selector); -} - -#ifdef UPB_TWO_32BIT_TYPES -inline bool Handlers::SetInt32Handler( - const FieldDef *f, Handlers::Int32Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint32alt(this, f, handler, d, fr); -} -inline bool Handlers::SetUInt32Handler( - const FieldDef *f, Handlers::UInt32Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint32alt(this, f, handler, d, fr); -} -inline bool Handlers::SetInt32Handler( - const char* name, Handlers::Int32Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint32alt_n(this, name, handler, d, fr); -} -inline bool Handlers::SetUInt32Handler( - const char* name, Handlers::UInt32Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint32alt_n(this, name, handler, d, fr); -} -#endif - -#ifdef UPB_TWO_64BIT_TYPES -inline bool Handlers::SetInt64Handler( - const FieldDef *f, Handlers::Int64Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint64alt(this, f, handler, d, fr); -} -inline bool Handlers::SetUInt64Handler( - const FieldDef *f, Handlers::UInt64Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint64alt(this, f, handler, d, fr); -} -inline bool Handlers::SetInt64Handler( - const char* name, Handlers::Int64Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setint64alt_n(this, name, handler, d, fr); -} -inline bool Handlers::SetUInt64Handler( - const char* name, Handlers::UInt64Handler2 *handler, - void *d, Handlers::Free *fr) { - return upb_handlers_setuint64alt_n(this, name, handler, d, fr); -} -#endif - -#define SET_VALUE_HANDLER(type, ctype, handlertype) \ - template<> \ - inline bool Handlers::SetValueHandler<ctype>( \ - const FieldDef* f, \ - handlertype* handler, \ - void* data, Handlers::Free* cleanup) { \ - return upb_handlers_set ## type(this, f, handler, data, cleanup); \ - } \ - template<> \ - inline bool Handlers::SetValueHandler<ctype>( \ - const char* f, \ - handlertype* handler, \ - void* data, Handlers::Free* cleanup) { \ - return upb_handlers_set ## type ## _n(this, f, handler, data, cleanup); \ - } -SET_VALUE_HANDLER(double, double, DoubleHandler); -SET_VALUE_HANDLER(float, float, FloatHandler); -SET_VALUE_HANDLER(uint64, upb_uint64_t, UInt64Handler); -SET_VALUE_HANDLER(uint32, upb_uint32_t, UInt32Handler); -SET_VALUE_HANDLER(int64, upb_int64_t, Int64Handler); -SET_VALUE_HANDLER(int32, upb_int32_t, Int32Handler); -SET_VALUE_HANDLER(bool, bool, BoolHandler); - -#ifdef UPB_TWO_32BIT_TYPES -SET_VALUE_HANDLER(int32alt, upb_int32alt_t, Int32Handler2); -SET_VALUE_HANDLER(uint32alt, upb_uint32alt_t, UInt32Handler2); -#endif - -#ifdef UPB_TWO_64BIT_TYPES -SET_VALUE_HANDLER(int64alt, upb_int64alt_t, Int64Handler2); -SET_VALUE_HANDLER(uint64alt, upb_uint64alt_t, UInt64Handler2); -#endif - -#undef SET_VALUE_HANDLER - -template <class T> void DeletePointer(void *p) { delete static_cast<T*>(p); } - -template <class T> -void SetStoreValueHandler( - const FieldDef* f, size_t offset, int32_t hasbit, Handlers* h); - -// A handy templated function that will retrieve a value handler for a given -// C++ type. -#define SET_STORE_VALUE_HANDLER(type, ctype, handlerctype) \ - template <> \ - inline void SetStoreValueHandler<ctype>(const FieldDef* f, size_t offset, \ - int32_t hasbit, Handlers* h) { \ - h->SetValueHandler<handlerctype>( \ - f, upb_stdmsg_set ## type, new upb_stdmsg_fval(offset, hasbit), \ - &upb::DeletePointer<upb_stdmsg_fval>); \ - } - -SET_STORE_VALUE_HANDLER(double, double, double); -SET_STORE_VALUE_HANDLER(float, float, float); -SET_STORE_VALUE_HANDLER(uint64, upb_uint64_t, uint64_t); -SET_STORE_VALUE_HANDLER(uint32, upb_uint32_t, uint32_t); -SET_STORE_VALUE_HANDLER(int64, upb_int64_t, int64_t); -SET_STORE_VALUE_HANDLER(int32, upb_int32_t, int32_t); -SET_STORE_VALUE_HANDLER(bool, bool, bool); - -#ifdef UPB_TWO_32BIT_TYPES -SET_STORE_VALUE_HANDLER(int32, upb_int32alt_t, int32_t); -SET_STORE_VALUE_HANDLER(uint32, upb_uint32alt_t, uint32_t); -#endif - -#ifdef UPB_TWO_64BIT_TYPES -SET_STORE_VALUE_HANDLER(int64, upb_int64alt_t, int64_t); -SET_STORE_VALUE_HANDLER(uint64, upb_uint64alt_t, uint64_t); -#endif - -#undef SET_STORE_VALUE_HANDLER +#include "upb/handlers-inl.h" -} // namespace upb -#endif - -// Implementation detail, put in the header file only so -// upb_sinkframe_handlerdata() can be inlined. -typedef struct { - upb_func *handler; - - // Could put either or both of these in a separate table to save memory when - // they are sparse. - void *data; - upb_handlerfree *cleanup; - - // TODO(haberman): this is wasteful; only the first "fieldhandler" of a - // submessage field needs this. To reduce memory footprint we should either: - // - put the subhandlers in a separate "fieldhandler", stored as part of - // a union with one of the above fields. - // - count selector offsets by individual pointers instead of by whole - // fieldhandlers. - const upb_handlers *subhandlers; -} upb_fieldhandler; - -#endif +#endif // UPB_HANDLERS_H diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index da4c48d..18bb430 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -95,6 +95,10 @@ typedef struct { // Maps (upb_handlers* or upb_fielddef*) -> int32 pclabel_base upb_inttable pclabels; + // For marking labels that should go into the generated code. + // Maps pclabel -> owned char* label. + upb_inttable asmlabels; + // This is not the same as len(pclabels) because the table only contains base // offsets for each def, but each def can have many pclabels. uint32_t pclabel_count; @@ -131,7 +135,7 @@ static const upb_decoder_typeinfo upb_decoder_types[] = { static upb_selector_t getselector(const upb_fielddef *f, upb_handlertype_t type) { upb_selector_t selector; - bool ok = upb_getselector(f, type, &selector); + bool ok = upb_handlers_getselector(f, type, &selector); UPB_ASSERT_VAR(ok, ok); return selector; } @@ -165,11 +169,11 @@ void freeplan(void *_p) { free(p); } -static decoderplan *getdecoderplan(const upb_handlers *h) { +static const decoderplan *getdecoderplan(const upb_handlers *h) { if (upb_handlers_frametype(h) != upb_pbdecoder_getframetype()) return NULL; upb_selector_t sel; - if (!upb_getselector(UPB_BYTESTREAM_BYTES, UPB_HANDLER_STRING, &sel)) + if (!upb_handlers_getselector(UPB_BYTESTREAM_BYTES, UPB_HANDLER_STRING, &sel)) return NULL; return upb_handlers_gethandlerdata(h, sel); } @@ -180,7 +184,7 @@ bool upb_pbdecoder_isdecoder(const upb_handlers *h) { bool upb_pbdecoder_hasjitcode(const upb_handlers *h) { #ifdef UPB_USE_JIT_X64 - decoderplan *p = getdecoderplan(h); + const decoderplan *p = getdecoderplan(h); if (!p) return false; return p->jit_code != NULL; #else @@ -190,7 +194,7 @@ bool upb_pbdecoder_hasjitcode(const upb_handlers *h) { } const upb_handlers *upb_pbdecoder_getdesthandlers(const upb_handlers *h) { - decoderplan *p = getdecoderplan(h); + const decoderplan *p = getdecoderplan(h); if (!p) return NULL; return p->dest_handlers; } @@ -582,7 +586,7 @@ static const upb_fielddef *decode_tag(upb_pbdecoder *d) { uint32_t tag = decode_v32(d); uint8_t wire_type = tag & 0x7; uint32_t fieldnum = tag >> 3; const upb_fielddef *f = NULL; - const upb_handlers *h = upb_sinkframe_handlers(upb_sink_top(d->sink)); + const upb_handlers *h = d->sink->top->h; // TODO(haberman): rm f = upb_msgdef_itof(upb_handlers_msgdef(h), fieldnum); bool packed = false; @@ -645,17 +649,19 @@ static const upb_fielddef *decode_tag(upb_pbdecoder *d) { } } -void *start(const upb_sinkframe *fr, size_t size_hint) { +void *start(void *closure, const void *handler_data, size_t size_hint) { + UPB_UNUSED(handler_data); UPB_UNUSED(size_hint); - upb_pbdecoder *d = upb_sinkframe_userdata(fr); + upb_pbdecoder *d = closure; assert(d); assert(d->sink); upb_sink_startmsg(d->sink); return d; } -bool end(const upb_sinkframe *fr) { - upb_pbdecoder *d = upb_sinkframe_userdata(fr); +bool end(void *closure, const void *handler_data) { + UPB_UNUSED(handler_data); + upb_pbdecoder *d = closure; if (d->residual_end > d->residual) { // We have preserved bytes. @@ -667,7 +673,6 @@ bool end(const upb_sinkframe *fr) { if (d->top == d->stack + 1 && d->top->is_sequence && !d->top->is_packed) { - assert(upb_sinkframe_depth(upb_sink_top(d->sink)) == 1); pop_seq(d); } if (d->top != d->stack) { @@ -679,47 +684,47 @@ bool end(const upb_sinkframe *fr) { return true; } -size_t decode(const upb_sinkframe *fr, const char *buf, size_t size) { - upb_pbdecoder *d = upb_sinkframe_userdata(fr); - decoderplan *plan = upb_sinkframe_handlerdata(fr); +size_t decode(void *closure, const void *hd, const char *buf, size_t size) { + upb_pbdecoder *d = closure; + const decoderplan *plan = hd; UPB_UNUSED(plan); - assert(upb_sinkframe_handlers(upb_sink_top(d->sink)) == plan->dest_handlers); + assert(d->sink->top->h == plan->dest_handlers); if (size == 0) return 0; // Assume we'll consume the whole buffer unless this is overwritten. d->ret = size; + d->buf_param = buf; + d->size_param = size; if (_setjmp(d->exitjmp)) { // Hit end-of-buffer or error. return d->ret; } - d->buf_param = buf; - d->size_param = size; if (d->residual_end > d->residual) { // We have residual bytes from the last buffer. - d->userbuf_remaining = size; + d->userbuf_remaining = d->size_param; } else { d->userbuf_remaining = 0; - advancetobuf(d, buf, size); + advancetobuf(d, buf, d->size_param); if (d->top != d->stack && upb_fielddef_isstring(d->top->f) && !d->top->is_sequence) { // Last buffer ended in the middle of a string; deliver more of it. size_t len = d->top->end_ofs - offset(d); - if (size >= len) { + if (d->size_param >= len) { upb_sink_putstring(d->sink, getselector(d->top->f, UPB_HANDLER_STRING), d->ptr, len); advance(d, len); pop_string(d); } else { upb_sink_putstring(d->sink, getselector(d->top->f, UPB_HANDLER_STRING), - d->ptr, size); - advance(d, size); + d->ptr, d->size_param); + advance(d, d->size_param); d->residual_end = d->residual; advancetobuf(d, d->residual, 0); - return size; + return d->size_param; } } } @@ -761,7 +766,8 @@ size_t decode(const upb_sinkframe *fr, const char *buf, size_t size) { } } -void init(void *_d) { +void init(void *_d, upb_pipeline *p) { + UPB_UNUSED(p); upb_pbdecoder *d = _d; d->limit = &d->stack[UPB_MAX_NESTING]; d->sink = NULL; diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h index 4307434..c1b6cb3 100644 --- a/upb/pb/decoder.h +++ b/upb/pb/decoder.h @@ -70,10 +70,6 @@ const upb_handlers *upb_pbdecoder_getdesthandlers(const upb_handlers *h); namespace upb { -template<> inline const FrameType* GetFrameType<upb::pb::Decoder>() { - return upb_pbdecoder_getframetype(); -} - namespace pb { inline bool ResetDecoderSink(Decoder* r, Sink* sink) { return upb_pbdecoder_resetsink(r, sink); diff --git a/upb/pb/decoder_x64.dasc b/upb/pb/decoder_x64.dasc index 7d4c537..154fee3 100644 --- a/upb/pb/decoder_x64.dasc +++ b/upb/pb/decoder_x64.dasc @@ -12,9 +12,11 @@ |// function) we must respect alignment rules. All x86-64 systems require |// 16-byte stack alignment. +#define _GNU_SOURCE #include <stdio.h> #include <sys/mman.h> #include "dynasm/dasm_x86.h" +#include "upb/shim/shim.h" #ifndef MAP_ANONYMOUS # define MAP_ANONYMOUS MAP_ANON @@ -61,7 +63,7 @@ static uint32_t upb_getpclabel(decoderplan *plan, const void *obj, int n) { return upb_value_getuint32(v) + n; } -static upb_jitmsginfo *upb_getmsginfo(decoderplan *plan, +static upb_jitmsginfo *upb_getmsginfo(const decoderplan *plan, const upb_handlers *h) { upb_value v; bool found = upb_inttable_lookupptr(&plan->msginfo, h, &v); @@ -161,6 +163,7 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; } |.define ARG2_64, rsi |.define ARG3_32, edx |.define ARG3_64, rdx +|.define ARG4_32, ecx |.define ARG4_64, rcx |.define XMMARG1, xmm0 @@ -193,13 +196,11 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; } ||{ || uintptr_t data = (uintptr_t)gethandlerdata(h, f, type); || if (data > 0xffffffff) { -| mov64 rax, data -| mov SINKFRAME->u.handler_data, rax -|| } else if (data > 0x7fffffff) { -| mov eax, data -| mov SINKFRAME->u.handler_data, rax +| mov64 ARG2_64, data +|| } else if (data) { +| mov ARG2_32, data || } else { -| mov qword SINKFRAME->u.handler_data, data +| xor ARG2_32, ARG2_32 || } || } |.endmacro @@ -269,6 +270,8 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; } |// table on the raw (length-masked) varint to save 3-4 cycles of latency. |// Currently only support tables where all entries are in the array part. |.macro dyndispatch_, h +|| asmlabel(plan, "_UPB_MCODE_DISPATCH_%s.%d", +|| upb_msgdef_fullname(upb_handlers_msgdef(h)), rand()); |=>upb_getpclabel(plan, h, DYNDISPATCH): | decode_loaded_varint, 0 | mov ecx, esi @@ -310,22 +313,21 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; } | |.macro pushsinkframe, handlers, field, endtype | mov rax, DECODER->sink -| mov dword SINKFRAME->u.selector, getselector(field, endtype) +| mov dword SINKFRAME->selector, getselector(field, endtype) | lea rcx, [SINKFRAME + sizeof(upb_sinkframe)] // rcx for short addressing | cmp rcx, SINK:rax->limit | jae ->exit_jit // Frame stack overflow. | mov64 r9, (uintptr_t)handlers | mov SINKFRAME:rcx->h, r9 | mov SINKFRAME:rcx->closure, CLOSURE -| mov SINK:rax->top_, rcx -| mov SINKFRAME:rcx->sink_, rax +| mov SINK:rax->top, rcx | mov SINKFRAME, rcx |.endmacro | |.macro popsinkframe | sub SINKFRAME, sizeof(upb_sinkframe) | mov rax, DECODER->sink -| mov SINK:rax->top_, SINKFRAME +| mov SINK:rax->top, SINKFRAME | mov CLOSURE, SINKFRAME->closure |.endmacro | @@ -415,12 +417,28 @@ static uintptr_t gethandlerdata(const upb_handlers *h, const upb_fielddef *f, return (uintptr_t)upb_handlers_gethandlerdata(h, getselector(f, type)); } +static void asmlabel(decoderplan *plan, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + char *str = NULL; + size_t size = 0; + upb_vrprintf(&str, &size, 0, fmt, ap); + va_end(ap); + uint32_t label = plan->pclabel_count++; + dasm_growpc(plan, plan->pclabel_count); + |=>label: + upb_inttable_insert(&plan->asmlabels, label, upb_value_ptr(str)); +} + // Decodes the next val into ARG2, advances PTR. static void upb_decoderplan_jit_decodefield(decoderplan *plan, size_t tag_size, const upb_handlers *h, const upb_fielddef *f) { // Decode the value into arg 3 for the callback. + asmlabel(plan, "UPB_MCODE_DECODE_FIELD_%s.%s", + upb_msgdef_fullname(upb_handlers_msgdef(h)), + upb_fielddef_name(f)); switch (upb_fielddef_descriptortype(f)) { case UPB_DESCRIPTOR_TYPE_DOUBLE: | movsd XMMARG1, qword [PTR + tag_size] @@ -496,39 +514,36 @@ static void upb_decoderplan_jit_decodefield(decoderplan *plan, upb_func *handler = gethandler(h, f, UPB_HANDLER_STARTSTR); if (handler) { + // void* startstr(void *c, const void *hd, size_t hint) | mov DECODER->tmp_len, ARG2_32 - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE + | mov ARG3_64, ARG2_64 | load_handler_data h, f, UPB_HANDLER_STARTSTR | callp handler | check_ptr_ret - | mov CLOSURE, rax - | mov ARG3_32, DECODER->tmp_len + | mov ARG1_64, rax // sub-closure + | mov ARG4_32, DECODER->tmp_len } else { - | mov ARG3_64, ARG2_64 + | mov ARG1_64, CLOSURE + | mov ARG4_64, ARG2_64 } handler = gethandler(h, f, UPB_HANDLER_STRING); if (handler) { - // TODO: push a real frame so we can resume into the string. - // (but maybe do this only if the string breaks). - | pushsinkframe h, f, UPB_HANDLER_ENDSTR - - // size_t str(const upb_sinkframe *frame, const char *buf, size_t len) - | mov ARG1_64, SINKFRAME + // size_t str(void *c, const void *hd, const char *buf, size_t len) | load_handler_data h, f, UPB_HANDLER_STRING - | mov ARG2_64, PTR + | mov ARG3_64, PTR | callp handler // TODO: properly handle returns other than "n" (the whole string). | add PTR, rax - | popsinkframe } else { - | add PTR, ARG3_64 + | add PTR, ARG4_64 } handler = gethandler(h, f, UPB_HANDLER_ENDSTR); if (handler) { // bool endstr(const upb_sinkframe *frame); - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | load_handler_data h, f, UPB_HANDLER_ENDSTR | callp handler | check_bool_ret @@ -553,13 +568,16 @@ static void upb_decoderplan_jit_callcb(decoderplan *plan, const upb_fielddef *f) { // Call callbacks. Specializing the append accessors didn't yield a speed // increase in benchmarks. + asmlabel(plan, "UPB_MCODE_CALLCB_%s.%s", + upb_msgdef_fullname(upb_handlers_msgdef(h)), + upb_fielddef_name(f)); if (upb_fielddef_issubmsg(f)) { // Call startsubmsg handler (if any). upb_func *startsubmsg = gethandler(h, f, UPB_HANDLER_STARTSUBMSG); if (startsubmsg) { // upb_sflow_t startsubmsg(const upb_sinkframe *frame) | mov DECODER->tmp_len, ARG2_32 - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | load_handler_data h, f, UPB_HANDLER_STARTSUBMSG | callp startsubmsg | check_ptr_ret @@ -594,37 +612,46 @@ static void upb_decoderplan_jit_callcb(decoderplan *plan, upb_func *endsubmsg = gethandler(h, f, UPB_HANDLER_ENDSUBMSG); if (endsubmsg) { // upb_flow_t endsubmsg(void *closure, upb_value fval); - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | load_handler_data h, f, UPB_HANDLER_ENDSUBMSG | callp endsubmsg | check_bool_ret } } else if (!upb_fielddef_isstring(f)) { upb_handlertype_t handlertype = upb_handlers_getprimitivehandlertype(f); + upb_selector_t sel = getselector(f, handlertype); upb_func *handler = gethandler(h, f, handlertype); - const upb_stdmsg_fval *fv = (void*)gethandlerdata(h, f, handlertype); - // Test for callbacks we can specialize. - // Can't switch() on function pointers. - if (handler == (void*)&upb_stdmsg_setint64 || - handler == (void*)&upb_stdmsg_setuint64) { - | mov [CLOSURE + fv->offset], ARG2_64 - | sethas CLOSURE, fv->hasbit - } else if (handler == (void*)&upb_stdmsg_setdouble) { - | movsd qword [CLOSURE + fv->offset], XMMARG1 - | sethas CLOSURE, fv->hasbit - } else if (handler == (void*)&upb_stdmsg_setint32 || - handler == (void*)&upb_stdmsg_setuint32) { - | mov [CLOSURE + fv->offset], ARG2_32 - | sethas CLOSURE, fv->hasbit - } else if (handler == (void*)&upb_stdmsg_setfloat) { - | movss dword [CLOSURE + fv->offset], XMMARG1 - | sethas CLOSURE, fv->hasbit - } else if (handler == (void*)&upb_stdmsg_setbool) { - | mov [CLOSURE + fv->offset], ARG2_8 - | sethas CLOSURE, fv->hasbit + const upb_shim_data *data = upb_shim_getdata(h, sel); + if (data) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + | mov [CLOSURE + data->offset], ARG2_64 + break; + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + | mov [CLOSURE + data->offset], ARG2_32 + break; + case UPB_TYPE_DOUBLE: + | movsd qword [CLOSURE + data->offset], XMMARG1 + break; + case UPB_TYPE_FLOAT: + | movss dword [CLOSURE + data->offset], XMMARG1 + break; + case UPB_TYPE_BOOL: + | mov [CLOSURE + data->offset], ARG2_8 + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + case UPB_TYPE_MESSAGE: + assert(false); break; + } + | sethas CLOSURE, data->hasbit } else if (handler) { // bool value(const upb_sinkframe* frame, ctype val) - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE + | mov ARG3_64, ARG2_64 | load_handler_data h, f, handlertype | callp handler | check_bool_ret @@ -647,7 +674,7 @@ static void upb_decoderplan_jit_endseq(decoderplan *plan, | popframe upb_func *endseq = gethandler(h, f, UPB_HANDLER_ENDSEQ); if (endseq) { - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | load_handler_data h, f, UPB_HANDLER_ENDSEQ | callp endseq } @@ -658,6 +685,9 @@ static void upb_decoderplan_jit_field(decoderplan *plan, const upb_handlers *h, const upb_fielddef *f, const upb_fielddef *next_f) { + asmlabel(plan, "UPB_MCODE_FIELD_%s.%s", + upb_msgdef_fullname(upb_handlers_msgdef(h)), + upb_fielddef_name(f)); uint64_t tag = upb_get_encoded_tag(f); uint64_t next_tag = next_f ? upb_get_encoded_tag(next_f) : 0; int tag_size = upb_value_size(tag); @@ -672,7 +702,7 @@ static void upb_decoderplan_jit_field(decoderplan *plan, if (upb_fielddef_isseq(f)) { upb_func *startseq = gethandler(h, f, UPB_HANDLER_STARTSEQ); if (startseq) { - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | load_handler_data h, f, UPB_HANDLER_STARTSEQ | callp startseq | check_ptr_ret @@ -726,6 +756,8 @@ static int upb_compare_uint32(const void *a, const void *b) { static void upb_decoderplan_jit_msg(decoderplan *plan, const upb_handlers *h) { + asmlabel(plan, "UPB_MCODE_DECODEMSG_%s", + upb_msgdef_fullname(upb_handlers_msgdef(h))); |=>upb_getpclabel(plan, h, AFTER_STARTMSG): | push rbp | mov rbp, rsp @@ -739,7 +771,7 @@ static void upb_decoderplan_jit_msg(decoderplan *plan, upb_startmsg_handler *startmsg = upb_handlers_getstartmsg(h); if (startmsg) { // upb_flow_t startmsg(void *closure); - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | callp startmsg | check_bool_ret } @@ -792,7 +824,7 @@ static void upb_decoderplan_jit_msg(decoderplan *plan, upb_endmsg_handler *endmsg = upb_handlers_getendmsg(h); if (endmsg) { // void endmsg(void *closure, upb_status *status) { - | mov ARG1_64, SINKFRAME + | mov ARG1_64, CLOSURE | mov ARG2_64, DECODER->sink | mov ARG2_64, SINK:ARG2_64->pipeline_ | add ARG2_64, offsetof(upb_pipeline, status_) @@ -815,6 +847,7 @@ static void upb_decoderplan_jit(decoderplan *plan) { // calculate the structure offsets ourself instead of symbolically // (ie. [r15 + 0xcd] instead of DECODER->ptr). So we tolerate a bit of // unnecessary duplication/redundancy. + asmlabel(plan, "upb_jit_trampoline"); | push rbp | mov rbp, rsp | push r15 @@ -828,13 +861,14 @@ static void upb_decoderplan_jit(decoderplan *plan) { | mov DECODER->saved_rbp, rbp | mov FRAME, DECODER:ARG1_64->top | mov rax, DECODER:ARG1_64->sink - | mov SINKFRAME, SINK:rax->top_ + | mov SINKFRAME, SINK:rax->top | mov CLOSURE, SINKFRAME->closure | mov PTR, DECODER->ptr // TODO: push return addresses for re-entry (will be necessary for multiple // buffer support). | call ARG2_64 + asmlabel(plan, "exitjit"); |->exit_jit: | mov rbp, DECODER->saved_rbp | lea rsp, [rbp - 48] @@ -903,6 +937,8 @@ static void upb_decoderplan_makejit(decoderplan *plan) { upb_inttable_init(&plan->pclabels, UPB_CTYPE_UINT32); upb_decoderplan_jit_assignpclabels(plan, plan->dest_handlers); + upb_inttable_init(&plan->asmlabels, UPB_CTYPE_PTR); + void **globals = malloc(UPB_JIT_GLOBAL__MAX * sizeof(*globals)); dasm_init(plan, 1); dasm_setupglobal(plan, globals, UPB_JIT_GLOBAL__MAX); @@ -947,18 +983,57 @@ static void upb_decoderplan_makejit(decoderplan *plan) { upb_inttable_uninit(&plan->pclabels); - dasm_free(plan); - free(globals); - mprotect(plan->jit_code, plan->jit_size, PROT_EXEC | PROT_READ); #ifndef NDEBUG - // View with: objdump -M intel -D -b binary -mi386 -Mx86-64 /tmp/machine-code - // Or: ndisasm -b 64 /tmp/machine-code - FILE *f = fopen("/tmp/machine-code", "wb"); - fwrite(plan->jit_code, plan->jit_size, 1, f); - fclose(f); + // Dump to a .o file in /tmp, for easy inspection. + + // Convert all asm labels from pclabel offsets to machine code offsets. + upb_inttable mclabels; + upb_inttable_init(&mclabels, UPB_CTYPE_PTR); + upb_inttable_begin(&i, &plan->asmlabels); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + upb_inttable_insert( + &mclabels, + dasm_getpclabel(plan, upb_inttable_iter_key(&i)), + upb_inttable_iter_value(&i)); + } + + FILE *f = fopen("/tmp/upb-jit-code.s", "w"); + if (f) { + fputs(" .text", f); + size_t linelen = 0; + for (size_t i = 0; i < plan->jit_size; i++) { + upb_value v; + if (upb_inttable_lookup(&mclabels, i, &v)) { + const char *label = upb_value_getptr(v); + fprintf(f, "\n\n_%s:\n", label); + fprintf(f, " .globl _%s", label); + linelen = 1000; + } + if (linelen >= 77) { + linelen = fprintf(f, "\n .byte %u", plan->jit_code[i]); + } else { + linelen += fprintf(f, ",%u", plan->jit_code[i]); + } + } + fputs("\n", f); + fclose(f); + } else { + fprintf(stderr, "Couldn't open /tmp/upb-jit-code.s for writing/\n"); + } + + upb_inttable_uninit(&mclabels); #endif + + upb_inttable_begin(&i, &plan->asmlabels); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + free(upb_value_getptr(upb_inttable_iter_value(&i))); + } + upb_inttable_uninit(&plan->asmlabels); + + dasm_free(plan); + free(globals); } static void upb_decoderplan_freejit(decoderplan *plan) { @@ -975,10 +1050,10 @@ static void upb_decoderplan_freejit(decoderplan *plan) { // TODO: unregister } -static void upb_decoder_enterjit(upb_pbdecoder *d, decoderplan *plan) { +static void upb_decoder_enterjit(upb_pbdecoder *d, const decoderplan *plan) { if (plan->jit_code && d->top == d->stack && - d->sink->top_ == d->sink->stack && + d->sink->top == d->sink->stack && d->ptr && d->ptr < d->jit_end) { #ifndef NDEBUG register uint64_t rbx asm ("rbx") = 11; diff --git a/upb/pb/glue.c b/upb/pb/glue.c index bcde039..2c621f4 100644 --- a/upb/pb/glue.c +++ b/upb/pb/glue.c @@ -30,7 +30,7 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, // Create sinks. upb_sink *reader_sink = upb_pipeline_newsink(&pipeline, reader_h); upb_sink *decoder_sink = upb_pipeline_newsink(&pipeline, decoder_h); - upb_pbdecoder *d = upb_sinkframe_userdata(upb_sink_base(decoder_sink)); + upb_pbdecoder *d = upb_sink_getobj(decoder_sink); upb_pbdecoder_resetsink(d, reader_sink); // Push input data. @@ -42,7 +42,7 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, return NULL; } - upb_descreader *r = upb_sinkframe_userdata(upb_sink_base(reader_sink)); + upb_descreader *r = upb_sink_getobj(reader_sink); upb_def **defs = upb_descreader_getdefs(r, owner, n); upb_def **defscopy = malloc(sizeof(upb_def*) * (*n)); memcpy(defscopy, defs, sizeof(upb_def*) * (*n)); diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index 91c1e2d..08eda15 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -38,8 +38,7 @@ static int endfield(upb_textprinter *p) { return 0; } -static int putescaped(upb_textprinter *p, const char *buf, size_t len, - bool preserve_utf8) { +static int putescaped(const char* buf, size_t len, bool preserve_utf8) { // Based on CEscapeInternal() from Google's protobuf release. char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf); const char *end = buf + len; @@ -84,9 +83,9 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len, } #define TYPE(name, ctype, fmt) \ - static bool put ## name(const upb_sinkframe *frame, ctype val) { \ - upb_textprinter *p = upb_sinkframe_userdata(frame); \ - const upb_fielddef *f = upb_sinkframe_handlerdata(frame); \ + static bool put ## name(void *closure, const void *handler_data, ctype val) {\ + upb_textprinter *p = closure; \ + const upb_fielddef *f = handler_data; \ CHECK(indent(p)); \ puts(upb_fielddef_name(f)); \ puts(": "); \ @@ -97,9 +96,9 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len, return false; \ } -static bool putbool(const upb_sinkframe *frame, bool val) { - upb_textprinter *p = upb_sinkframe_userdata(frame); - const upb_fielddef *f = upb_sinkframe_handlerdata(frame); +static bool putbool(void *closure, const void *handler_data, bool val) { + upb_textprinter *p = closure; + const upb_fielddef *f = handler_data; CHECK(indent(p)); puts(upb_fielddef_name(f)); puts(": "); @@ -121,44 +120,49 @@ TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g") TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g") // Output a symbolic value from the enum if found, else just print as int32. -static bool putenum(const upb_sinkframe *frame, int32_t val) { - const upb_fielddef *f = upb_sinkframe_handlerdata(frame); +static bool putenum(void *closure, const void *handler_data, int32_t val) { + const upb_fielddef *f = handler_data; const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f)); const char *label = upb_enumdef_iton(enum_def, val); if (label) { puts(label); } else { - CHECK(putint32(frame, val)); + CHECK(putint32(closure, handler_data, val)); } return true; err: return false; } -static void *startstr(const upb_sinkframe *frame, size_t size_hint) { +static void *startstr(void *closure, const void *handler_data, + size_t size_hint) { + UPB_UNUSED(handler_data); UPB_UNUSED(size_hint); - upb_textprinter *p = upb_sinkframe_userdata(frame); + upb_textprinter *p = closure; putchar('"'); return p; } -static bool endstr(const upb_sinkframe *frame) { +static bool endstr(void *closure, const void *handler_data) { + UPB_UNUSED(closure); + UPB_UNUSED(handler_data); putchar('"'); return true; } -static size_t putstr(const upb_sinkframe *frame, const char *buf, size_t len) { - upb_textprinter *p = upb_sinkframe_userdata(frame); - const upb_fielddef *f = upb_sinkframe_handlerdata(frame); - CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING)); +static size_t putstr(void *closure, const void *hd, const char *buf, + size_t len) { + UPB_UNUSED(closure); + const upb_fielddef *f = hd; + CHECK(putescaped(buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING)); return len; err: return 0; } -static void *startsubmsg(const upb_sinkframe *frame) { - upb_textprinter *p = upb_sinkframe_userdata(frame); - const upb_fielddef *f = upb_sinkframe_handlerdata(frame); +static void *startsubmsg(void *closure, const void *handler_data) { + upb_textprinter *p = closure; + const upb_fielddef *f = handler_data; CHECK(indent(p)); printf("%s {", upb_fielddef_name(f)); if (!p->single_line) @@ -169,8 +173,9 @@ err: return UPB_BREAK; } -static bool endsubmsg(const upb_sinkframe *frame) { - upb_textprinter *p = upb_sinkframe_userdata(frame); +static bool endsubmsg(void *closure, const void *handler_data) { + UPB_UNUSED(handler_data); + upb_textprinter *p = closure; p->indent_depth--; CHECK(indent(p)); putchar('}'); diff --git a/upb/shim/shim.c b/upb/shim/shim.c new file mode 100644 index 0000000..6a79ac0 --- /dev/null +++ b/upb/shim/shim.c @@ -0,0 +1,69 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2013 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + */ + +#include "upb/shim/shim.h" + +#include <stdlib.h> + +// Fallback implementation if the shim is not specialized by the JIT. +#define SHIM_WRITER(type, ctype) \ + bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \ + uint8_t *m = c; \ + const upb_shim_data *d = hd; \ + if (d->hasbit > 0) \ + *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \ + *(ctype*)&m[d->offset] = val; \ + return true; \ + } \ + +SHIM_WRITER(double, double) +SHIM_WRITER(float, float) +SHIM_WRITER(int32, int32_t) +SHIM_WRITER(int64, int64_t) +SHIM_WRITER(uint32, uint32_t) +SHIM_WRITER(uint64, uint64_t) +SHIM_WRITER(bool, bool) +#undef SHIM_WRITER + +bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, + int32_t hasbit) { + upb_shim_data *d = malloc(sizeof(*d)); + if (!d) return false; + d->offset = offset; + d->hasbit = hasbit; + +#define TYPE(u, l) \ + case UPB_TYPE_##u: return upb_handlers_set##l(h, f, upb_shim_set##l, d, free) + + switch (upb_fielddef_type(f)) { + TYPE(INT64, int64); + TYPE(INT32, int32); + TYPE(ENUM, int32); + TYPE(UINT64, uint64); + TYPE(UINT32, uint32); + TYPE(DOUBLE, double); + TYPE(FLOAT, float); + TYPE(BOOL, bool); + default: assert(false); return false; + } +#undef TYPE +} + +const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s) { + upb_func *f = upb_handlers_gethandler(h, s); + if ((upb_int64_handler*)f == upb_shim_setint64 || + (upb_int32_handler*)f == upb_shim_setint32 || + (upb_uint64_handler*)f == upb_shim_setuint64 || + (upb_uint32_handler*)f == upb_shim_setuint32 || + (upb_double_handler*)f == upb_shim_setdouble || + (upb_float_handler*)f == upb_shim_setfloat || + (upb_bool_handler*)f == upb_shim_setbool) { + return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s); + } else { + return NULL; + } +} diff --git a/upb/shim/shim.h b/upb/shim/shim.h new file mode 100644 index 0000000..98310d7 --- /dev/null +++ b/upb/shim/shim.h @@ -0,0 +1,74 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2013 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * For handlers that do very tiny, very simple operations, the function call + * overhead of calling a handler can be significant. This file allows the + * user to define handlers that do something very simple like store the value + * to memory and/or set a hasbit. JIT compilers can then special-case these + * handlers and emit specialized code for them instead of actually calling the + * handler. + * + * The functionality is very simple/limited right now but may expand to be able + * to call another function. + */ + +#ifndef UPB_SHIM_H +#define UPB_SHIM_H + +#include "upb/handlers.h" + +typedef struct { + size_t offset; + int32_t hasbit; +} upb_shim_data; + +#ifdef __cplusplus + +namespace upb { + +struct Shim { + typedef upb_shim_data Data; + + // Sets a handler for the given field that writes the value to the given + // offset and, if hasbit >= 0, sets a bit at the given bit offset. Returns + // true if the handler was set successfully. + static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit); + + // If this handler is a shim, returns the corresponding upb::Shim::Data. + // Otherwise returns NULL. + static const Data* GetData(const Handlers* h, Handlers::Selector s); +}; + +} // namespace upb + +extern "C" { +#endif + +// C API. +bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, + int32_t hasbit); +const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s); + +#ifdef __cplusplus +} // extern "C" + +namespace upb { + +// C++ Wrappers. +inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs, + int32_t hasbit) { + return upb_shim_set(h, f, ofs, hasbit); +} +inline const Shim::Data* Shim::GetData(const Handlers* h, + Handlers::Selector s) { + return upb_shim_getdata(h, s); +} + +} // namespace + +#endif + +#endif // UPB_SHIM_H @@ -15,7 +15,7 @@ static void upb_sink_resetobj(void *obj); static const upb_frametype upb_sink_frametype; static bool chkstack(upb_sink *s) { - if (s->top_ + 1 >= s->limit) { + if (s->top + 1 >= s->limit) { upb_status_seterrliteral(&s->pipeline_->status_, "Nesting too deep."); return false; } else { @@ -134,7 +134,7 @@ void *upb_pipeline_allocobj(upb_pipeline *p, const upb_frametype *ft) { obj->prev = p->obj_head; obj->ft = ft; p->obj_head = obj; - if (ft->init) ft->init(&obj->data); + if (ft->init) ft->init(&obj->data, p); return &obj->data; } @@ -180,21 +180,6 @@ void upb_pipeline_donateref( } -/* upb_sinkframe **************************************************************/ - -int upb_sinkframe_depth(const upb_sinkframe* frame) { - return frame - frame->sink_->stack; -} - -const upb_handlers* upb_sinkframe_handlers(const upb_sinkframe* frame) { - return frame->h; -} - -upb_pipeline *upb_sinkframe_pipeline(const upb_sinkframe* frame) { - return frame->sink_->pipeline_; -} - - /* upb_sink *******************************************************************/ static const upb_frametype upb_sink_frametype = { @@ -205,82 +190,79 @@ static const upb_frametype upb_sink_frametype = { }; void upb_sink_reset(upb_sink *s, void *closure) { - s->top_ = s->stack; - s->top_->closure = closure; + s->top = s->stack; + s->top->closure = closure; } static void upb_sink_resetobj(void *obj) { upb_sink *s = obj; - s->top_ = s->stack; + s->top = s->stack; } static void upb_sink_init(upb_sink *s, const upb_handlers *h, upb_pipeline *p) { s->pipeline_ = p; - s->limit = &s->stack[UPB_MAX_NESTING]; - s->stack[0].h = h; - s->top_ = s->stack; + s->stack = upb_pipeline_alloc(p, sizeof(*s->stack) * UPB_MAX_NESTING); + s->top = s->stack; + s->limit = s->stack + UPB_MAX_NESTING; + s->top->h = h; if (h->ft) { - s->stack[0].closure = upb_pipeline_allocobj(p, h->ft); + s->top->closure = upb_pipeline_allocobj(p, h->ft); } } -const upb_sinkframe *upb_sink_top(const upb_sink *s) { - return s->top_; -} - -const upb_sinkframe *upb_sink_base(const upb_sink *s) { - return s->stack; -} - upb_pipeline *upb_sink_pipeline(const upb_sink *s) { return s->pipeline_; } +void *upb_sink_getobj(const upb_sink *s) { + return s->stack[0].closure; +} + bool upb_sink_startmsg(upb_sink *s) { - const upb_handlers *h = s->top_->h; + const upb_handlers *h = s->top->h; upb_startmsg_handler *startmsg = upb_handlers_getstartmsg(h); - return startmsg ? startmsg(s->top_) : true; + return startmsg ? startmsg(s->top->closure) : true; } void upb_sink_endmsg(upb_sink *s) { - assert(s->top_ == s->stack); - upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top_->h); + assert(s->top == s->stack); + upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top->h); if (endmsg) { - endmsg(s->top_, &s->pipeline_->status_); + endmsg(s->top->closure, &s->pipeline_->status_); } } -#define PUTVAL(type, ctype, htype) \ +#define PUTVAL(type, ctype) \ bool upb_sink_put ## type(upb_sink *s, upb_selector_t sel, ctype val) { \ - const upb_handlers *h = s->top_->h; \ + const upb_handlers *h = s->top->h; \ upb_ ## type ## _handler *handler = (upb_ ## type ## _handler*) \ upb_handlers_gethandler(h, sel); \ if (handler) { \ - s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel); \ - bool ok = handler(s->top_, val); \ + const void *hd = upb_handlers_gethandlerdata(h, sel); \ + bool ok = handler(s->top->closure, hd, val); \ if (!ok) return false; \ } \ return true; \ } -PUTVAL(int32, int32_t, INT32); -PUTVAL(int64, int64_t, INT64); -PUTVAL(uint32, uint32_t, UINT32); -PUTVAL(uint64, uint64_t, UINT64); -PUTVAL(float, float, FLOAT); -PUTVAL(double, double, DOUBLE); -PUTVAL(bool, bool, BOOL); +PUTVAL(int32, int32_t); +PUTVAL(int64, int64_t); +PUTVAL(uint32, uint32_t); +PUTVAL(uint64, uint64_t); +PUTVAL(float, float); +PUTVAL(double, double); +PUTVAL(bool, bool); #undef PUTVAL size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, const char *buf, size_t n) { - const upb_handlers *h = s->top_->h; + const upb_handlers *h = s->top->h; upb_string_handler *handler = (upb_string_handler*)upb_handlers_gethandler(h, sel); if (handler) { - s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel);; - n = handler(s->top_, buf, n); + const void *hd = upb_handlers_gethandlerdata(h, sel);; + n = handler(s->top->closure, hd, buf, n); } return n; @@ -289,39 +271,39 @@ size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, bool upb_sink_startseq(upb_sink *s, upb_selector_t sel) { if (!chkstack(s)) return false; - void *subc = s->top_->closure; - const upb_handlers *h = s->top_->h; + void *subc = s->top->closure; + const upb_handlers *h = s->top->h; upb_startfield_handler *startseq = (upb_startfield_handler*)upb_handlers_gethandler(h, sel); if (startseq) { - s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel); - subc = startseq(s->top_); + const void *hd = upb_handlers_gethandlerdata(h, sel); + subc = startseq(s->top->closure, hd); if (subc == UPB_BREAK) { return false; } } - s->top_->u.selector = upb_getendselector(sel); - ++s->top_; - s->top_->h = h; - s->top_->closure = subc; - s->top_->sink_ = s; + s->top->selector = upb_handlers_getendselector(sel); + ++s->top; + s->top->h = h; + s->top->closure = subc; return true; } bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { - --s->top_; - assert(sel == s->top_->u.selector); + --s->top; + assert(sel == s->top->selector); - const upb_handlers *h = s->top_->h; + const upb_handlers *h = s->top->h; upb_endfield_handler *endseq = (upb_endfield_handler*)upb_handlers_gethandler(h, sel); if (endseq) { - bool ok = endseq(s->top_); + const void *hd = upb_handlers_gethandlerdata(h, sel); + bool ok = endseq(s->top->closure, hd); if (!ok) { - ++s->top_; + ++s->top; return false; } } @@ -332,38 +314,38 @@ bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, size_t size_hint) { if (!chkstack(s)) return false; - void *subc = s->top_->closure; - const upb_handlers *h = s->top_->h; + void *subc = s->top->closure; + const upb_handlers *h = s->top->h; upb_startstr_handler *startstr = (upb_startstr_handler*)upb_handlers_gethandler(h, sel); if (startstr) { - s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel); - subc = startstr(s->top_, size_hint); + const void *hd = upb_handlers_gethandlerdata(h, sel); + subc = startstr(s->top->closure, hd, size_hint); if (subc == UPB_BREAK) { return false; } } - s->top_->u.selector = upb_getendselector(sel); - ++s->top_; - s->top_->h = h; - s->top_->closure = subc; - s->top_->sink_ = s; + s->top->selector = upb_handlers_getendselector(sel); + ++s->top; + s->top->h = h; + s->top->closure = subc; return true; } bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { - --s->top_; - assert(sel == s->top_->u.selector); - const upb_handlers *h = s->top_->h; + --s->top; + assert(sel == s->top->selector); + const upb_handlers *h = s->top->h; upb_endfield_handler *endstr = (upb_endfield_handler*)upb_handlers_gethandler(h, sel); if (endstr) { - bool ok = endstr(s->top_); + const void *hd = upb_handlers_gethandlerdata(h, sel); + bool ok = endstr(s->top->closure, hd); if (!ok) { - ++s->top_; + ++s->top; return false; } } @@ -374,44 +356,47 @@ bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel) { if (!chkstack(s)) return false; - void *subc = s->top_->closure; - const upb_handlers *h = s->top_->h; + void *subc = s->top->closure; + const upb_handlers *h = s->top->h; upb_startfield_handler *startsubmsg = (upb_startfield_handler*)upb_handlers_gethandler(h, sel); if (startsubmsg) { - s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel); - subc = startsubmsg(s->top_); + const void *hd = upb_handlers_gethandlerdata(h, sel); + subc = startsubmsg(s->top->closure, hd); if (subc == UPB_BREAK) { return false; } } - s->top_->u.selector= upb_getendselector(sel); - ++s->top_; - s->top_->h = upb_handlers_getsubhandlers_sel(h, sel); + s->top->selector= upb_handlers_getendselector(sel); + ++s->top; + s->top->h = upb_handlers_getsubhandlers_sel(h, sel); // TODO: should add support for submessages without any handlers - assert(s->top_->h); - s->top_->closure = subc; - s->top_->sink_ = s; + assert(s->top->h); + s->top->closure = subc; upb_sink_startmsg(s); return true; } bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { - upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top_->h); - if (endmsg) endmsg(s->top_, &s->pipeline_->status_); - --s->top_; + upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top->h); + if (endmsg) { + // TODO(haberman): check return value. + endmsg(s->top->closure, &s->pipeline_->status_); + } + --s->top; - assert(sel == s->top_->u.selector); - const upb_handlers *h = s->top_->h; + assert(sel == s->top->selector); + const upb_handlers *h = s->top->h; upb_endfield_handler *endsubmsg = (upb_endfield_handler*)upb_handlers_gethandler(h, sel); if (endsubmsg) { - bool ok = endsubmsg(s->top_); + const void *hd = upb_handlers_gethandlerdata(h, sel); + bool ok = endsubmsg(s->top->closure, hd); if (!ok) { - ++s->top_; + ++s->top; return false; } } @@ -420,5 +405,5 @@ bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { } const upb_handlers *upb_sink_tophandlers(upb_sink *s) { - return s->top_->h; + return s->top->h; } @@ -30,22 +30,13 @@ template <int size> class SeededPipeline; } typedef upb::Pipeline upb_pipeline; typedef upb::Sink upb_sink; -UPB_INLINE upb_sink* upb_sinkframe_sink(const upb_sinkframe* frame); -UPB_INLINE void* upb_sinkframe_userdata(const upb_sinkframe* frame); -UPB_INLINE void* upb_sinkframe_handlerdata(const upb_sinkframe* frame); #else struct upb_pipeline; struct upb_sink; typedef struct upb_pipeline upb_pipeline; typedef struct upb_sink upb_sink; #endif - -struct upb_frametype { - size_t size; - void (*init)(void* obj); - void (*uninit)(void* obj); - void (*reset)(void* obj); -}; +struct upb_sinkframe; #ifdef __cplusplus @@ -122,6 +113,13 @@ struct upb_pipeline { upb_status status_; }; +struct upb_frametype { + size_t size; + void (*init)(void* obj, upb_pipeline *p); + void (*uninit)(void* obj); + void (*reset)(void* obj); +}; + #ifdef __cplusplus // For convenience, a template for a pipeline with an array of initial memory. @@ -136,84 +134,6 @@ class upb::SeededPipeline : public upb::Pipeline { char mem_[initial_size]; }; -class upb::SinkFrame { - public: - // Returns the sink that this frame belongs to. - Sink* sink() const; - - // Returns the pipeline that this sink and frame belong to. - Pipeline* pipeline() const; - - // The depth of this frame (counts all kind of frames (sequence, submessage, - // and string frames). - int depth() const; - - // The Handlers object for this frame. - const Handlers* handlers() const; - - // Returns the user data that is bound to this sink frame (as returned - // by the Start{SubMessage,String,Sequence} handler, or passed to - // Sink::Reset()). - void* userdata() const; - - // A templated version of userdata() that type-checks the templated return - // type. - // - // TODO(haberman): this isn't truly robust until sequence and string frames - // have distinct FrameTypes in the Handlers. - template<class T> - T* GetUserdata() const { -#ifdef NDEBUG - return static_cast<T*>(userdata()); -#else - const FrameType* type = handlers()->frame_type(); - if (!type || type == GetFrameType<T>()) { - return static_cast<T*>(userdata()); - } else { - assert(false); - return NULL; - } -#endif - } - - // Returns the data that was bound to the currently-executing callback in the - // Handlers object. If not currently in a handler, the results are undefined. - void* handler_data() const; - - private: - UPB_DISALLOW_POD_OPS(SinkFrame); - friend class upb::Sink; - friend upb_sink* ::upb_sinkframe_sink(const upb_sinkframe* frame); - friend void* ::upb_sinkframe_userdata(const upb_sinkframe* frame); - friend void* ::upb_sinkframe_handlerdata(const upb_sinkframe* frame); - -#else -struct upb_sinkframe { -#endif - upb_sink *sink_; - const upb_handlers *h; - void *closure; - - union { - // For the top frame (sink->top), the handler_data for the - // currently-executing callback, otherwise undefined. - // TODO(haberman): have a special pointer value to indicate "not in a - // callback"; this will be a way to enforce non-reentrancy of a sink. - void *handler_data; - - // For other frames, the END* callback that will run when the subframe is - // popped (for example, for a "sequence" frame the frame above it will be a - // UPB_HANDLER_ENDSEQ handler). But this is only necessary for assertion - // checking inside upb_sink and can be omitted if the sink has only one - // caller. - // TODO(haberman): have a mechanism for ensuring that a sink only has one - // caller. - upb_selector_t selector; - } u; -}; - -#ifdef __cplusplus - // A upb::Sink is an object that binds a upb::Handlers object to some runtime // state. It is the object that can actually call a set of handlers. // @@ -234,13 +154,12 @@ class upb::Sink { // used as the top-level closure. void Reset(void *closure); - // Returns the top-most and base (lowest) frame of the stack, respectively. - const SinkFrame* top() const; - const SinkFrame* base() const; - // Returns the pipeline that this sink comes from. Pipeline* pipeline() const; + // Returns the top-level object that is bound to this sink. + template <class T> T* GetObject() const; + // Functions for pushing data into the sink. // // These return false if processing should stop (either due to error or just @@ -285,23 +204,9 @@ class upb::Sink { struct upb_sink { #endif upb_pipeline *pipeline_; - upb_sinkframe *top_, *limit; - upb_sinkframe stack[UPB_MAX_NESTING]; + struct upb_sinkframe *top, *limit, *stack; }; -// C API. -UPB_INLINE upb_sink *upb_sinkframe_sink(const upb_sinkframe* frame) { - return frame->sink_; -} - -UPB_INLINE void *upb_sinkframe_userdata(const upb_sinkframe* frame) { - return frame->closure; -} - -UPB_INLINE void *upb_sinkframe_handlerdata(const upb_sinkframe* frame) { - return frame->u.handler_data; -} - #ifdef __cplusplus extern "C" { #endif @@ -321,14 +226,9 @@ void upb_pipeline_donateref( upb_sink *upb_pipeline_newsink(upb_pipeline *p, const upb_handlers *h); const upb_status *upb_pipeline_status(const upb_pipeline *p); -int upb_sinkframe_depth(const upb_sinkframe* frame); -const upb_handlers* upb_sinkframe_handlers(const upb_sinkframe* frame); -upb_pipeline* upb_sinkframe_pipeline(const upb_sinkframe* frame); - void upb_sink_reset(upb_sink *s, void *closure); upb_pipeline *upb_sink_pipeline(const upb_sink *s); -const upb_sinkframe *upb_sink_top(const upb_sink *s); -const upb_sinkframe *upb_sink_base(const upb_sink *s); +void *upb_sink_getobj(const upb_sink *s); bool upb_sink_startmsg(upb_sink *s); void upb_sink_endmsg(upb_sink *s); bool upb_sink_putint32(upb_sink *s, upb_selector_t sel, int32_t val); @@ -386,36 +286,15 @@ inline void Pipeline::DonateRef(const upb::Handlers* h, const void *owner) { return upb_pipeline_donateref(this, h, owner); } -inline Sink* SinkFrame::sink() const { - return upb_sinkframe_sink(this); -} -inline Pipeline* SinkFrame::pipeline() const { - return upb_sinkframe_pipeline(this); -} -inline void* SinkFrame::userdata() const { - return upb_sinkframe_userdata(this); -} -inline void* SinkFrame::handler_data() const { - return upb_sinkframe_handlerdata(this); -} -inline int SinkFrame::depth() const { - return upb_sinkframe_depth(this); -} -inline const Handlers* SinkFrame::handlers() const { - return upb_sinkframe_handlers(this); -} - inline void Sink::Reset(void *closure) { upb_sink_reset(this, closure); } inline Pipeline* Sink::pipeline() const { return upb_sink_pipeline(this); } -inline const SinkFrame* Sink::top() const { - return upb_sink_top(this); -} -inline const SinkFrame* Sink::base() const { - return upb_sink_base(this); +template <class T> +inline T* Sink::GetObject() const { + return static_cast<T*>(upb_sink_getobj(this)); } inline bool Sink::StartMessage() { return upb_sink_startmsg(this); @@ -470,4 +349,23 @@ inline bool Sink::EndSequence(Handlers::Selector sel) { } // namespace upb #endif +// TODO(haberman): move this to sink.c. We keep it here now only because the +// JIT needs to modify it directly, which it only needs to do because it makes +// the interpreter handle fallback cases. When the JIT is self-sufficient, it +// will no longer need to touch the sink's stack at all. +struct upb_sinkframe { + const upb_handlers *h; + void *closure; + + // For any frames besides the top, this is the END* callback that will run + // when the subframe is popped (for example, for a "sequence" frame the frame + // above it will be a UPB_HANDLER_ENDSEQ handler). But this is only + // necessary for assertion checking inside upb_sink and can be omitted if the + // sink has only one caller. + // + // TODO(haberman): have a mechanism for ensuring that a sink only has one + // caller. + upb_selector_t selector; +}; + #endif diff --git a/upb/table.h b/upb/table.h index 2b4c80c..f96dee9 100644 --- a/upb/table.h +++ b/upb/table.h @@ -164,6 +164,7 @@ void upb_inttable_compact(upb_inttable *t); // A special-case inlinable version of the lookup routine for 32-bit integers. UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, upb_value *v) { + *v = upb_value_int32(0); // Silence compiler warnings. if (key < t->array_size) { _upb_value arrval = t->array[key]; if (upb_arrhas(arrval)) { @@ -35,11 +35,12 @@ extern "C" { #define UPB_C99 #endif -#if (defined(__cplusplus) && __cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \ + defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11) #define UPB_CXX11 #endif -#if defined(__GXX_EXPERIMENTAL_CXX0X__) && !defined(UPB_NO_CXX11) +#ifdef UPB_CXX11 #define UPB_DISALLOW_POD_OPS(class_name) \ class_name() = delete; \ ~class_name() = delete; \ @@ -70,27 +71,15 @@ extern "C" { #endif // Type detection and typedefs for integer types. +// For platforms where there are multiple 32-bit or 64-bit types, we need to be +// able to enumerate them so we can properly create overloads for all variants. // -// We unfortunately cannot just use stdint.h types in all cases, because some -// platforms have more than one 32-bit type (or 64-bit type). For example, on -// x86-64, both "long" and "long long" are 64-bit types, but they are -// unfortunately incompatible with each other despite being the same size. -// Since the types are incompatible, functions pointers between them are -// incompatible also, which leads to trouble since handlers are declared in -// terms of function pointers. Since we don't know which of these types -// stdint.h will use (and we have no way of inspecting the typedefs, either at -// preprocessing or compilation time), we are forced to declare our own -// typedefs that we *do* know the real underlying type of. -// -// If any platform existed where there three integer types were the same size, -// this would have to become more complicated. For example, short, int, and -// long could all be 32-bits. Even more diabolically, short, int, long, and -// long long could all be 64 bits and still be standard-compliant. However, -// few platforms are this strange, and it's unlikely that upb will be used on -// the strangest ones. -// -// For more information, see: -// http://blog.reverberate.org/2013/03/cc-gripe-1-integer-types.html +// If any platform existed where there were three integer types with the same +// size, this would have to become more complicated. For example, short, int, +// and long could all be 32-bits. Even more diabolically, short, int, long, +// and long long could all be 64 bits and still be standard-compliant. +// However, few platforms are this strange, and it's unlikely that upb will be +// used on the strangest ones. // Can't count on stdint.h limits like INT32_MAX, because in C++ these are // only defined when __STDC_LIMIT_MACROS are defined before the *first* include @@ -348,7 +337,7 @@ typedef struct { #define UPB__VALUE_INIT_NONE UPB_VALUE_INIT(NULL, ptr) #ifdef NDEBUG -#define SET_TYPE(dest, val) +#define SET_TYPE(dest, val) UPB_UNUSED(val) #define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE} #else #define SET_TYPE(dest, val) dest = val |