Synced with Google-internal development.

C++ handlers are now type-safe; SinkFrame is gone.
Various other changes.
pull/13171/head
Josh Haberman 12 years ago
parent cfdb9907cb
commit 90bb4246c3
  1. 5
      Makefile
  2. 2
      bindings/lua/upb.c
  3. 135
      tests/test_decoder.cc
  4. 3
      tests/test_vs_proto2.cc
  5. 1
      upb/def.c
  6. 80
      upb/descriptor/descriptor.upb.c
  7. 122
      upb/descriptor/descriptor.upb.h
  8. 166
      upb/descriptor/reader.c
  9. 4
      upb/descriptor/reader.h
  10. 2
      upb/google/bridge.cc
  11. 143
      upb/google/proto1.cc
  12. 243
      upb/google/proto2.cc
  13. 470
      upb/handlers-inl.h
  14. 557
      upb/handlers.c
  15. 1007
      upb/handlers.h
  16. 55
      upb/pb/decoder.c
  17. 4
      upb/pb/decoder.h
  18. 199
      upb/pb/decoder_x64.dasc
  19. 4
      upb/pb/glue.c
  20. 51
      upb/pb/textprinter.c
  21. 69
      upb/shim/shim.c
  22. 74
      upb/shim/shim.h
  23. 179
      upb/sink.c
  24. 172
      upb/sink.h
  25. 1
      upb/table.h
  26. 35
      upb/upb.h

@ -49,7 +49,7 @@ CXX=g++
CFLAGS=-std=gnu99
CXXFLAGS=-Ibindings/cpp
INCLUDE=-Itests -I.
CPPFLAGS=$(INCLUDE) -Wall -Wextra $(USER_CFLAGS)
CPPFLAGS=$(INCLUDE) -Wall -Wextra -Wno-sign-compare $(USER_CFLAGS)
LDLIBS=-lpthread upb/libupb.a
LUA=lua5.1 # 5.1 and 5.2 should both be supported
@ -82,7 +82,7 @@ deps: Makefile $(ALLSRC)
# The core library.
CORE= \
upb/bytestream.c \
upb/bytestream.upb.c \
upb/def.c \
upb/descriptor/reader.c \
upb/descriptor/descriptor.upb.c \
@ -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 \

@ -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 {

@ -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++) {

@ -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();

@ -676,6 +676,7 @@ upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
return upb_fielddef_istagdelim(f) ?
UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE;
}
return 0;
}
bool upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {

@ -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),

@ -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

@ -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;

@ -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);

@ -208,7 +208,7 @@ static upb::MessageDef* NewMessageDef(const goog::Message& m, const void* owner,
// Must do this before processing submessages to prevent infinite recursion.
defs->AddMessage(&m, md);
vector<const goog::FieldDescriptor*> fields;
std::vector<const goog::FieldDescriptor*> fields;
d->file()->pool()->FindAllExtensions(d, &fields);
for (int i = 0; i < d->field_count(); i++) {
fields.push_back(d->field(i));

@ -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,
static string* StartRepeatedString(proto2::RepeatedPtrField<string>* r,
size_t size_hint) {
proto2::RepeatedPtrField<string>* r =
static_cast<proto2::RepeatedPtrField<string>*>(frame->userdata());
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,
static string* StartOutOfLineString(proto2::Message* m,
const FieldOffset* info,
size_t size_hint) {
const FieldOffset* info =
static_cast<const FieldOffset*>(frame->handler_data());
void* m = frame->userdata();
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);

@ -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,
// 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,
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,
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;

@ -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_

@ -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);
}
bool upb_handlers_isfrozen(const upb_handlers *h) {
return upb_refcounted_isfrozen(upb_upcast(h));
free(h->cleanup);
free(h);
}
uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
return upb_fielddef_isseq(f) ? 2 : 0;
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_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;
}
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 const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
typedef struct {
upb_inttable tab; // maps upb_msgdef* -> upb_handlers*.
upb_handlers_callback *callback;
void *closure;
} dfs_state;
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;
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)
oom:
upb_handlers_unref(h, owner);
return NULL;
}
// 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;
*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;
}
assert(*s < upb_fielddef_msgdef(f)->selector_count);
h->cleanup = resized;
}
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);
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;
}
return h;
oom:
upb_handlers_unref(h, owner);
return NULL;
upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h) {
return h->endmsg;
}
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_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s) {
return (upb_func *)h->table[s].func;
}
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);
const void *upb_handlers_gethandlerdata(const upb_handlers *h,
upb_selector_t s) {
return h->table[s].data;
}
upb_inttable_uninit(&state.tab);
return ret;
/* "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);
}
#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
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;
}
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;
}

File diff suppressed because it is too large Load Diff

@ -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;
}
@ -290,7 +294,6 @@ static void suspendjmp(upb_pbdecoder *d) {
}
static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
assert(len >= 0);
assert(d->ptr == d->end);
d->bufstart_ofs += (d->ptr - d->buf);
switchtobuf(d, buf, buf + len);
@ -583,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;
@ -646,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.
@ -668,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) {
@ -680,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;
}
}
}
@ -762,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;

@ -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);

@ -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);
// 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;

@ -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));

@ -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('}');

@ -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;
}
}

@ -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

@ -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

Loading…
Cancel
Save