summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile54
-rw-r--r--benchmarks/parsetoproto2.upb.cc292
-rw-r--r--benchmarks/parsetostruct.upb.c14
-rw-r--r--upb/def.h2
-rw-r--r--upb/msg.c13
-rw-r--r--upb/pb/glue.c30
-rw-r--r--upb/pb/glue.h3
7 files changed, 388 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index b0e3d9a..f413ca2 100644
--- a/Makefile
+++ b/Makefile
@@ -296,7 +296,16 @@ BENCHMARKS=$(UPB_BENCHMARKS) \
benchmarks/b.parsetostruct_googlemessage1.proto2_table \
benchmarks/b.parsetostruct_googlemessage2.proto2_table \
benchmarks/b.parsetostruct_googlemessage1.proto2_compiled \
- benchmarks/b.parsetostruct_googlemessage2.proto2_compiled
+ benchmarks/b.parsetostruct_googlemessage2.proto2_compiled \
+ benchmarks/b.parsetoproto2_googlemessage1.upb \
+ benchmarks/b.parsetoproto2_googlemessage2.upb
+
+ifdef USE_JIT
+BENCHMARKS += \
+ benchmarks/b.parsetoproto2_googlemessage1.upb_jit \
+ benchmarks/b.parsetoproto2_googlemessage2.upb_jit
+endif
+
upb_benchmarks: $(UPB_BENCHMARKS)
benchmarks: $(BENCHMARKS)
benchmark:
@@ -375,6 +384,26 @@ benchmarks/b.parsestream_googlemessage2.upb_jit: \
-DMESSAGE_DESCRIPTOR_FILE=\"google_messages.proto.pb\" \
-DMESSAGE_FILE=\"google_message2.dat\" -DJIT=true \
$(LIBUPB)
+
+benchmarks/b.parsetoproto2_googlemessage1.upb_jit \
+benchmarks/b.parsetoproto2_googlemessage2.upb_jit: \
+ benchmarks/parsetoproto2.upb.cc benchmarks/google_messages.pb.cc
+ $(E) 'CXX benchmarks/parsetoproto2.upb.cc (benchmarks.SpeedMessage1, jit)'
+ $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o benchmarks/b.parsetoproto2_googlemessage1.upb_jit $< \
+ -DMESSAGE_CIDENT="benchmarks::SpeedMessage1" \
+ -DMESSAGE_NAME=\"benchmarks.SpeedMessage1\" \
+ -DMESSAGE_FILE=\"google_message1.dat\" \
+ -DMESSAGE_HFILE=\"google_messages.pb.h\" \
+ -DMESSAGE_DESCRIPTOR_FILE=\"google_messages.proto.pb\" -DJIT=true \
+ benchmarks/google_messages.pb.cc -lprotobuf -lpthread $(LIBUPB)
+ $(E) 'CXX benchmarks/parsetoproto2.upb.cc (benchmarks.SpeedMessage2, jit)'
+ $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o benchmarks/b.parsetoproto2_googlemessage2.upb_jit $< \
+ -DMESSAGE_CIDENT="benchmarks::SpeedMessage2" \
+ -DMESSAGE_NAME=\"benchmarks.SpeedMessage2\" \
+ -DMESSAGE_FILE=\"google_message2.dat\" \
+ -DMESSAGE_HFILE=\"google_messages.pb.h\" -DJIT=true \
+ -DMESSAGE_DESCRIPTOR_FILE=\"google_messages.proto.pb\" \
+ benchmarks/google_messages.pb.cc -lprotobuf -lpthread $(LIBUPB)
endif
benchmarks/b.parsetostruct_googlemessage1.proto2_table \
@@ -395,8 +424,7 @@ benchmarks/b.parsetostruct_googlemessage2.proto2_table: \
benchmarks/b.parsetostruct_googlemessage1.proto2_compiled \
benchmarks/b.parsetostruct_googlemessage2.proto2_compiled: \
- benchmarks/parsetostruct.proto2_compiled.cc \
- benchmarks/parsetostruct.proto2_table.cc benchmarks/google_messages.pb.cc
+ benchmarks/parsetostruct.proto2_compiled.cc benchmarks/google_messages.pb.cc
$(E) 'CXX benchmarks/parsetostruct.proto2_compiled.cc (benchmarks.SpeedMessage1)'
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o benchmarks/b.parsetostruct_googlemessage1.proto2_compiled $< \
-DMESSAGE_CIDENT="benchmarks::SpeedMessage1" \
@@ -410,6 +438,26 @@ benchmarks/b.parsetostruct_googlemessage2.proto2_compiled: \
-DMESSAGE_HFILE=\"google_messages.pb.h\" \
benchmarks/google_messages.pb.cc -lprotobuf -lpthread
+benchmarks/b.parsetoproto2_googlemessage1.upb \
+benchmarks/b.parsetoproto2_googlemessage2.upb: \
+ benchmarks/parsetoproto2.upb.cc benchmarks/google_messages.pb.cc
+ $(E) 'CXX benchmarks/parsetoproto2.upb.cc (benchmarks.SpeedMessage1, nojit)'
+ $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o benchmarks/b.parsetoproto2_googlemessage1.upb $< \
+ -DMESSAGE_CIDENT="benchmarks::SpeedMessage1" \
+ -DMESSAGE_NAME=\"benchmarks.SpeedMessage1\" \
+ -DMESSAGE_FILE=\"google_message1.dat\" \
+ -DMESSAGE_HFILE=\"google_messages.pb.h\" \
+ -DMESSAGE_DESCRIPTOR_FILE=\"google_messages.proto.pb\" -DJIT=false \
+ benchmarks/google_messages.pb.cc -lprotobuf -lpthread $(LIBUPB)
+ $(E) 'CXX benchmarks/parsetoproto2.upb.cc (benchmarks.SpeedMessage2, nojit)'
+ $(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o benchmarks/b.parsetoproto2_googlemessage2.upb $< \
+ -DMESSAGE_CIDENT="benchmarks::SpeedMessage2" \
+ -DMESSAGE_NAME=\"benchmarks.SpeedMessage2\" \
+ -DMESSAGE_FILE=\"google_message2.dat\" \
+ -DMESSAGE_HFILE=\"google_messages.pb.h\" \
+ -DMESSAGE_DESCRIPTOR_FILE=\"google_messages.proto.pb\" -DJIT=false \
+ benchmarks/google_messages.pb.cc -lprotobuf -lpthread $(LIBUPB)
+
# Lua extension ##################################################################
diff --git a/benchmarks/parsetoproto2.upb.cc b/benchmarks/parsetoproto2.upb.cc
new file mode 100644
index 0000000..e60c5d5
--- /dev/null
+++ b/benchmarks/parsetoproto2.upb.cc
@@ -0,0 +1,292 @@
+
+
+#define __STDC_LIMIT_MACROS 1
+#include "main.c"
+
+#include <stdint.h>
+#include "upb/bytestream.h"
+#include "upb/def.h"
+#include "upb/msg.h"
+#include "upb/pb/decoder.h"
+#include "upb/pb/glue.h"
+
+// Need to violate the encapsulation of GeneratedMessageReflection -- see below.
+#define private public
+#include MESSAGE_HFILE
+#include <google/protobuf/descriptor.h>
+#undef private
+
+static size_t len;
+MESSAGE_CIDENT msg[NUM_MESSAGES];
+MESSAGE_CIDENT msg2;
+static upb_stringsrc strsrc;
+static upb_decoder d;
+upb_msgdef *def;
+
+#define PROTO2_APPEND(type, ctype) \
+ upb_flow_t proto2_append_ ## type(void *_r, upb_value fval, upb_value val) { \
+ (void)fval; \
+ typedef google::protobuf::RepeatedField<ctype> R; \
+ R *r = (R*)_r; \
+ r->Add(upb_value_get ## type(val)); \
+ return UPB_CONTINUE; \
+ }
+
+PROTO2_APPEND(double, double)
+PROTO2_APPEND(float, float)
+PROTO2_APPEND(uint64, uint64_t)
+PROTO2_APPEND(int64, int64_t)
+PROTO2_APPEND(int32, int32_t)
+PROTO2_APPEND(uint32, uint32_t)
+PROTO2_APPEND(bool, bool)
+
+upb_flow_t proto2_setstr(void *m, upb_value fval, upb_value val) {
+ assert(m != NULL);
+ upb_stdmsg_sethas(m, fval);
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ std::string **str = (std::string**)UPB_INDEX(m, f->offset, 1);
+ if (*str == f->default_ptr) *str = new std::string;
+ upb_strref *ref = upb_value_getstrref(val);
+ // XXX: only supports contiguous strings atm.
+ (*str)->assign(ref->ptr, ref->len);
+ return UPB_CONTINUE;
+}
+
+upb_flow_t proto2_append_str(void *_r, upb_value fval, upb_value val) {
+ assert(_r != NULL);
+ typedef google::protobuf::RepeatedPtrField<std::string> R;
+ (void)fval;
+ R *r = (R*)_r;
+ upb_strref *ref = upb_value_getstrref(val);
+ // XXX: only supports contiguous strings atm.
+ r->Add()->assign(ref->ptr, ref->len);
+ return UPB_CONTINUE;
+}
+
+upb_sflow_t proto2_startseq(void *m, upb_value fval) {
+ assert(m != NULL);
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ return UPB_CONTINUE_WITH(UPB_INDEX(m, f->offset, 1));
+}
+
+upb_sflow_t proto2_startsubmsg(void *m, upb_value fval) {
+ assert(m != NULL);
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ upb_stdmsg_sethas(m, fval);
+ google::protobuf::Message *prototype = (google::protobuf::Message*)f->prototype;
+ void **subm = (void**)UPB_INDEX(m, f->offset, 1);
+ if (*subm == NULL || *subm == f->default_ptr)
+ *subm = prototype->New();
+ assert(*subm != NULL);
+ return UPB_CONTINUE_WITH(*subm);
+}
+
+class UpbRepeatedPtrField : public google::protobuf::internal::RepeatedPtrFieldBase {
+ public:
+ class TypeHandler {
+ public:
+ typedef void Type;
+ };
+ void *Add(google::protobuf::Message *m) {
+ void *submsg = RepeatedPtrFieldBase::AddFromCleared<TypeHandler>();
+ if (!submsg) {
+ submsg = m->New();
+ RepeatedPtrFieldBase::AddAllocated<TypeHandler>(submsg);
+ }
+ return submsg;
+ }
+};
+
+upb_sflow_t proto2_startsubmsg_r(void *_r, upb_value fval) {
+ assert(_r != NULL);
+ // Compared to the other writers, this implementation is particularly sketchy.
+ // The object we are modifying is a RepeatedPtrField<SubType>*, but we can't
+ // properly declare that templated pointer because we don't have access to
+ // that type at compile-time (and wouldn't want to create a separate callback
+ // for each type anyway). Instead we access the pointer as a
+ // RepeatedPtrFieldBase, which is indeed a superclass of RepeatedPtrField.
+ // But we can't properly declare a TypeHandler for the submessage's type,
+ // for the same reason that we can't create a RepeatedPtrField<SubType>*.
+ // Instead we treat it as a void*, and create the submessage using
+ // google::protobuf::Message::New() if we need to.
+ class TypeHandler {
+ public:
+ typedef void Type;
+ };
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ UpbRepeatedPtrField *r = (UpbRepeatedPtrField*)_r;
+ void *submsg = r->Add((google::protobuf::Message*)f->prototype);
+ assert(submsg != NULL);
+ return UPB_CONTINUE_WITH(submsg);
+}
+
+#define PROTO2MSG(type, size) { static upb_accessor_vtbl vtbl = { \
+ &proto2_startsubmsg, \
+ &upb_stdmsg_set ## type, \
+ &proto2_startseq, \
+ &proto2_startsubmsg_r, \
+ &proto2_append_ ## type, \
+ NULL, NULL, NULL, NULL, NULL, NULL}; \
+ return &vtbl; }
+
+static upb_accessor_vtbl *proto2_accessor(upb_fielddef *f) {
+ switch (f->type) {
+ case UPB_TYPE(DOUBLE): PROTO2MSG(double, 8)
+ case UPB_TYPE(FLOAT): PROTO2MSG(float, 4)
+ case UPB_TYPE(UINT64):
+ case UPB_TYPE(FIXED64): PROTO2MSG(uint64, 8)
+ case UPB_TYPE(INT64):
+ case UPB_TYPE(SFIXED64):
+ case UPB_TYPE(SINT64): PROTO2MSG(int64, 8)
+ case UPB_TYPE(INT32):
+ case UPB_TYPE(SINT32):
+ case UPB_TYPE(ENUM):
+ case UPB_TYPE(SFIXED32): PROTO2MSG(int32, 4)
+ case UPB_TYPE(UINT32):
+ case UPB_TYPE(FIXED32): PROTO2MSG(uint32, 4)
+ case UPB_TYPE(BOOL): PROTO2MSG(bool, 1)
+ case UPB_TYPE(STRING):
+ case UPB_TYPE(BYTES):
+ case UPB_TYPE(GROUP):
+ case UPB_TYPE(MESSAGE): {
+ static upb_accessor_vtbl vtbl = {
+ &proto2_startsubmsg,
+ &proto2_setstr,
+ &proto2_startseq,
+ &proto2_startsubmsg_r,
+ &proto2_append_str,
+ NULL, NULL, NULL, NULL, NULL, NULL};
+ return &vtbl;
+ }
+ }
+ return NULL;
+}
+
+static void layout_msgdef_from_proto2(upb_msgdef *upb_md,
+ const google::protobuf::Message *m,
+ const google::protobuf::Descriptor *proto2_d) {
+ // Hack: we break the encapsulation of GeneratedMessageReflection to get at
+ // the offsets we need. If/when we do this for real, we will need
+ // GeneratedMessageReflection to expose those offsets publicly.
+ const google::protobuf::internal::GeneratedMessageReflection *r =
+ (google::protobuf::internal::GeneratedMessageReflection*)m->GetReflection();
+ for (int i = 0; i < proto2_d->field_count(); i++) {
+ const google::protobuf::FieldDescriptor *proto2_f = proto2_d->field(i);
+ upb_fielddef *upb_f = upb_msgdef_itof(upb_md, proto2_f->number());
+ assert(upb_f);
+
+ // Encapsulation violation BEGIN
+ uint32_t data_offset = r->offsets_[proto2_f->index()];
+ uint32_t hasbit = (r->has_bits_offset_ * 8) + proto2_f->index();
+ // Encapsulation violation END
+
+ upb_f->offset = data_offset;
+ upb_f->hasbit = hasbit;
+ upb_fielddef_setaccessor(upb_f, proto2_accessor(upb_f));
+
+ if (upb_isstring(upb_f) && !upb_isseq(upb_f)) {
+ upb_f->default_ptr = &r->GetStringReference(*m, proto2_f, NULL);
+ } else if (upb_issubmsg(upb_f)) {
+ // XXX: skip leading "."
+ const google::protobuf::Descriptor *subm_descriptor =
+ google::protobuf::DescriptorPool::generated_pool()->
+ FindMessageTypeByName(upb_fielddef_typename(upb_f) + 1);
+ assert(subm_descriptor);
+ upb_f->prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(subm_descriptor);
+ if (!upb_isseq(upb_f))
+ upb_f->default_ptr = &r->GetMessage(*m, proto2_f);
+ }
+ }
+}
+
+static bool initialize()
+{
+ // Initialize upb state, decode descriptor.
+ upb_status status = UPB_STATUS_INIT;
+ upb_symtab *s = upb_symtab_new();
+
+ char *data = upb_readfile(MESSAGE_DESCRIPTOR_FILE, &len);
+ if (!data) {
+ fprintf(stderr, "Couldn't read file: " MESSAGE_DESCRIPTOR_FILE);
+ return false;
+ }
+ int n;
+ upb_def **defs = upb_load_descriptor(data, len, &n, &status);
+ free(data);
+ if(!upb_ok(&status)) {
+ upb_status_print(&status, stderr);
+ return false;
+ }
+
+ // Setup offsets and accessors to properly write into a proto2 generated
+ // class.
+ for (int i = 0; i < n; i++) {
+ upb_def *def = defs[i];
+ upb_msgdef *upb_md = upb_dyncast_msgdef(def);
+ if (!upb_md) continue;
+ const google::protobuf::Descriptor *proto2_md =
+ google::protobuf::DescriptorPool::generated_pool()->
+ FindMessageTypeByName(upb_def_fqname(def));
+ if (!proto2_md) abort();
+ const google::protobuf::Message *proto2_m =
+ google::protobuf::MessageFactory::generated_factory()->GetPrototype(proto2_md);
+ layout_msgdef_from_proto2(upb_md, proto2_m, proto2_md);
+ }
+
+ upb_symtab_add(s, defs, n, &status);
+ if(!upb_ok(&status)) {
+ upb_status_print(&status, stderr);
+ return false;
+ }
+ for(int i = 0; i < n; i++) upb_def_unref(defs[i]);
+ free(defs);
+
+ def = upb_dyncast_msgdef(upb_symtab_lookup(s, MESSAGE_NAME));
+ if(!def) {
+ fprintf(stderr, "Error finding symbol '%s'.\n", MESSAGE_NAME);
+ return false;
+ }
+ upb_symtab_unref(s);
+
+ // Read the message data itself.
+ char *str = upb_readfile(MESSAGE_FILE, &len);
+ if(str == NULL) {
+ fprintf(stderr, "Error reading " MESSAGE_FILE "\n");
+ return false;
+ }
+ upb_status_uninit(&status);
+
+ msg2.ParseFromArray(str, len);
+
+ upb_stringsrc_init(&strsrc);
+ upb_stringsrc_reset(&strsrc, str, len);
+ upb_handlers *h = upb_handlers_new();
+ upb_accessors_reghandlers(h, def);
+ if (!JIT) h->should_jit = false;
+ upb_decoder_initforhandlers(&d, h);
+ upb_handlers_unref(h);
+
+ return true;
+}
+
+static void cleanup() {
+ upb_stringsrc_uninit(&strsrc);
+ upb_decoder_uninit(&d);
+ upb_def_unref(UPB_UPCAST(def));
+}
+
+static size_t run(int i)
+{
+ (void)i;
+ upb_status status = UPB_STATUS_INIT;
+ msg[i % NUM_MESSAGES].Clear();
+ upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), 0, UINT64_MAX, &msg[i % NUM_MESSAGES]);
+ upb_decoder_decode(&d, &status);
+ if(!upb_ok(&status)) goto err;
+ return len;
+
+err:
+ fprintf(stderr, "Decode error: ");
+ upb_status_print(&status, stderr);
+ return 0;
+}
diff --git a/benchmarks/parsetostruct.upb.c b/benchmarks/parsetostruct.upb.c
index a436fd4..64a4d35 100644
--- a/benchmarks/parsetostruct.upb.c
+++ b/benchmarks/parsetostruct.upb.c
@@ -9,7 +9,7 @@
static upb_msgdef *def;
static size_t len;
-static void *msg;
+static void *msg[NUM_MESSAGES];
static upb_stringsrc strsrc;
static upb_decoder d;
@@ -38,7 +38,8 @@ static bool initialize()
return false;
}
upb_status_uninit(&status);
- msg = upb_stdmsg_new(def);
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ msg[i] = upb_stdmsg_new(def);
upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str, len);
@@ -56,7 +57,8 @@ static bool initialize()
static void cleanup()
{
- upb_stdmsg_free(msg, def);
+ for (int i = 0; i < NUM_MESSAGES; i++)
+ upb_stdmsg_free(msg[i], def);
upb_def_unref(UPB_UPCAST(def));
upb_stringsrc_uninit(&strsrc);
upb_decoder_uninit(&d);
@@ -64,10 +66,10 @@ static void cleanup()
static size_t run(int i)
{
- (void)i;
upb_status status = UPB_STATUS_INIT;
- upb_msg_clear(msg, def);
- upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), 0, UINT64_MAX, msg);
+ i %= NUM_MESSAGES;
+ upb_msg_clear(msg[i], def);
+ upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), 0, UINT64_MAX, msg[i]);
upb_decoder_decode(&d, &status);
if(!upb_ok(&status)) goto err;
return len;
diff --git a/upb/def.h b/upb/def.h
index 66d3c70..86f84ce 100644
--- a/upb/def.h
+++ b/upb/def.h
@@ -93,6 +93,8 @@ typedef struct _upb_fielddef {
upb_value defaultval; // Only meaningful for non-repeated scalars and strings.
upb_value fval;
struct _upb_accessor_vtbl *accessor;
+ const void *default_ptr;
+ const void *prototype;
} upb_fielddef;
upb_fielddef *upb_fielddef_new(void);
diff --git a/upb/msg.c b/upb/msg.c
index 0a9948a..de7607c 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -11,11 +11,13 @@
#include "upb/msg.h"
void upb_msg_clear(void *msg, upb_msgdef *md) {
+ assert(msg != NULL);
memset(msg, 0, md->hasbit_bytes);
// TODO: set primitive fields to defaults?
}
void *upb_stdarray_append(upb_stdarray *a, size_t type_size) {
+ assert(a != NULL);
assert(a->len <= a->size);
if (a->len == a->size) {
size_t old_size = a->size;
@@ -81,12 +83,14 @@ void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h,
/* Standard writers. **********************************************************/
void upb_stdmsg_sethas(void *_m, upb_value fval) {
+ assert(_m != NULL);
char *m = _m;
upb_fielddef *f = upb_value_getfielddef(fval);
if (f->hasbit >= 0) m[f->hasbit / 8] |= (1 << (f->hasbit % 8));
}
bool upb_stdmsg_has(void *_m, upb_value fval) {
+ assert(_m != NULL);
char *m = _m;
upb_fielddef *f = upb_value_getfielddef(fval);
return f->hasbit < 0 || (m[f->hasbit / 8] & (1 << (f->hasbit % 8)));
@@ -95,6 +99,7 @@ bool upb_stdmsg_has(void *_m, upb_value fval) {
#define UPB_ACCESSORS(type, ctype) \
upb_flow_t upb_stdmsg_set ## type (void *_m, upb_value fval, \
upb_value val) { \
+ assert(_m != NULL); \
upb_fielddef *f = upb_value_getfielddef(fval); \
uint8_t *m = _m; \
upb_stdmsg_sethas(_m, fval); \
@@ -105,12 +110,14 @@ bool upb_stdmsg_has(void *_m, upb_value fval) {
upb_flow_t upb_stdmsg_set ## type ## _r(void *a, upb_value _fval, \
upb_value val) { \
(void)_fval; \
+ assert(a != NULL); \
ctype *p = upb_stdarray_append((upb_stdarray*)a, sizeof(ctype)); \
*p = upb_value_get ## type(val); \
return UPB_CONTINUE; \
} \
\
upb_value upb_stdmsg_get ## type(void *_m, upb_value fval) { \
+ assert(_m != NULL); \
uint8_t *m = _m; \
upb_fielddef *f = upb_value_getfielddef(fval); \
upb_value ret; \
@@ -118,6 +125,7 @@ bool upb_stdmsg_has(void *_m, upb_value fval) {
return ret; \
} \
upb_value upb_stdmsg_seqget ## type(void *i) { \
+ assert(i != NULL); \
upb_value val; \
upb_value_set ## type(&val, *(ctype*)i); \
return val; \
@@ -153,6 +161,7 @@ static void _upb_stdmsg_setstr(void *_dst, upb_value src) {
}
upb_flow_t upb_stdmsg_setstr(void *_m, upb_value fval, upb_value val) {
+ assert(_m != NULL);
char *m = _m;
upb_fielddef *f = upb_value_getfielddef(fval);
upb_stdmsg_sethas(_m, fval);
@@ -161,16 +170,19 @@ upb_flow_t upb_stdmsg_setstr(void *_m, upb_value fval, upb_value val) {
}
upb_flow_t upb_stdmsg_setstr_r(void *a, upb_value fval, upb_value val) {
+ assert(a != NULL);
(void)fval;
_upb_stdmsg_setstr(upb_stdarray_append((upb_stdarray*)a, sizeof(void*)), val);
return UPB_CONTINUE;
}
upb_value upb_stdmsg_getstr(void *m, upb_value fval) {
+ assert(m != NULL);
return upb_stdmsg_getptr(m, fval);
}
upb_value upb_stdmsg_seqgetstr(void *i) {
+ assert(i != NULL);
return upb_stdmsg_seqgetptr(i);
}
@@ -244,6 +256,7 @@ void upb_stdmsg_recycle(void **m, upb_msgdef *md) {
}
upb_sflow_t upb_stdmsg_startsubmsg(void *_m, upb_value fval) {
+ assert(_m != NULL);
char *m = _m;
upb_fielddef *f = upb_value_getfielddef(fval);
void **subm = (void*)&m[f->offset];
diff --git a/upb/pb/glue.c b/upb/pb/glue.c
index 6b52435..e13db3e 100644
--- a/upb/pb/glue.c
+++ b/upb/pb/glue.c
@@ -53,8 +53,8 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md,
#endif
// TODO: read->load.
-void upb_read_descriptor(upb_symtab *symtab, const char *str, size_t len,
- upb_status *status) {
+upb_def **upb_load_descriptor(const char *str, size_t len, int *n,
+ upb_status *status) {
upb_stringsrc strsrc;
upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str, len);
@@ -70,12 +70,17 @@ void upb_read_descriptor(upb_symtab *symtab, const char *str, size_t len,
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), 0, UINT64_MAX, &r);
upb_decoder_decode(&d, status);
- int n;
- upb_def **defs = upb_descreader_getdefs(&r, &n);
+ upb_def **defs = upb_descreader_getdefs(&r, n);
+ upb_def **defscopy = malloc(sizeof(upb_def*) * (*n));
+ memcpy(defscopy, defs, sizeof(upb_def*) * (*n));
+
+ upb_descreader_uninit(&r);
+ upb_stringsrc_uninit(&strsrc);
+ upb_decoder_uninit(&d);
// Set default accessors and layouts on all messages.
- for(int i = 0; i < n; i++) {
- upb_def *def = defs[i];
+ for(int i = 0; i < *n; i++) {
+ upb_def *def = defscopy[i];
upb_msgdef *md = upb_dyncast_msgdef(def);
if (!md) continue;
// For field in msgdef:
@@ -87,13 +92,16 @@ void upb_read_descriptor(upb_symtab *symtab, const char *str, size_t len,
upb_msgdef_layout(md);
}
- if (upb_ok(status)) upb_symtab_add(symtab, defs, n, status);
+ return defscopy;
+}
+void upb_read_descriptor(upb_symtab *s, const char *str, size_t len,
+ upb_status *status) {
+ int n;
+ upb_def **defs = upb_load_descriptor(str, len, &n, status);
+ if (upb_ok(status)) upb_symtab_add(s, defs, n, status);
for(int i = 0; i < n; i++) upb_def_unref(defs[i]);
-
- upb_descreader_uninit(&r);
- upb_stringsrc_uninit(&strsrc);
- upb_decoder_uninit(&d);
+ free(defs);
}
char *upb_readfile(const char *filename, size_t *len) {
diff --git a/upb/pb/glue.h b/upb/pb/glue.h
index 5359120..a2a478c 100644
--- a/upb/pb/glue.h
+++ b/upb/pb/glue.h
@@ -47,6 +47,9 @@ void upb_strtomsg(const char *str, size_t len, void *msg,
//void upb_msgtotext(struct _upb_string *str, void *msg,
// struct _upb_msgdef *md, bool single_line);
+upb_def **upb_load_descriptor(const char *str, size_t len, int *n,
+ upb_status *status);
+
void upb_read_descriptor(struct _upb_symtab *symtab, const char *str, size_t len,
upb_status *status);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback