summaryrefslogtreecommitdiff
path: root/upb/descriptor/reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'upb/descriptor/reader.c')
-rw-r--r--upb/descriptor/reader.c269
1 files changed, 158 insertions, 111 deletions
diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c
index 16f3b24..529d5ef 100644
--- a/upb/descriptor/reader.c
+++ b/upb/descriptor/reader.c
@@ -16,8 +16,8 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include "upb/bytestream.h"
#include "upb/def.h"
+#include "upb/sink.h"
#include "upb/descriptor/descriptor.upb.h"
static char *upb_strndup(const char *buf, size_t n) {
@@ -28,7 +28,8 @@ static char *upb_strndup(const char *buf, size_t n) {
return ret;
}
-// Returns a newly allocated string that joins input strings together, for example:
+// Returns a newly allocated string that joins input strings together, for
+// example:
// join("Foo.Bar", "Baz") -> "Foo.Bar.Baz"
// join("", "Baz") -> "Baz"
// Caller owns a ref on the returned string.
@@ -45,9 +46,21 @@ static char *upb_join(const char *base, const char *name) {
}
}
+
+/* upb_deflist ****************************************************************/
+
+// upb_deflist is an internal-only dynamic array for storing a growing list of
+// upb_defs.
+typedef struct {
+ upb_def **defs;
+ size_t len;
+ size_t size;
+ bool owned;
+} upb_deflist;
+
void upb_deflist_init(upb_deflist *l) {
- l->size = 8;
- l->defs = malloc(l->size * sizeof(void*));
+ l->size = 0;
+ l->defs = NULL;
l->len = 0;
l->owned = true;
}
@@ -56,15 +69,19 @@ 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);
- free(l->defs);
}
-void upb_deflist_push(upb_deflist *l, upb_def *d) {
- if(l->len == l->size) {
- l->size *= 2;
- l->defs = realloc(l->defs, l->size * sizeof(void*));
+bool upb_deflist_push(upb_deflist *l, upb_def *d, upb_pipeline *p) {
+ 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*));
+ if (!l->defs) return false;
+ l->size = new_size;
}
- l->defs[l->len++] = d;
+ l->defs[l->len - 1] = d;
+ return true;
}
void upb_deflist_donaterefs(upb_deflist *l, void *owner) {
@@ -74,9 +91,6 @@ void upb_deflist_donaterefs(upb_deflist *l, void *owner) {
l->owned = false;
}
-
-/* upb_descreader ************************************************************/
-
static upb_def *upb_deflist_last(upb_deflist *l) {
return l->defs[l->len-1];
}
@@ -91,17 +105,67 @@ static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) {
}
}
-void upb_descreader_init(upb_descreader *r) {
+
+/* upb_descreader ************************************************************/
+
+// We keep a stack of all the messages scopes we are currently in, as well as
+// the top-level file scope. This is necessary to correctly qualify the
+// definitions that are contained inside. "name" tracks the name of the
+// message or package (a bare name -- not qualified by any enclosing scopes).
+typedef struct {
+ char *name;
+ // Index of the first def that is under this scope. For msgdefs, the
+ // msgdef itself is at start-1.
+ int start;
+} upb_descreader_frame;
+
+struct upb_descreader {
+ upb_deflist defs;
+ upb_descreader_frame stack[UPB_MAX_TYPE_DEPTH];
+ int stack_len;
+
+ uint32_t number;
+ char *name;
+ bool saw_number;
+ bool saw_name;
+
+ char *default_string;
+
+ upb_fielddef *f;
+};
+
+void upb_descreader_init(void *r);
+void upb_descreader_uninit(void *r);
+
+const upb_frametype upb_descreader_frametype = {
+ sizeof(upb_descreader),
+ upb_descreader_init,
+ upb_descreader_uninit,
+ NULL,
+};
+
+const upb_frametype *upb_descreader_getframetype() {
+ return &upb_descreader_frametype;
+}
+
+// Registers handlers that will build the defs. Pass the descreader as the
+// closure.
+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);
- upb_status_init(&r->status);
r->stack_len = 0;
r->name = NULL;
r->default_string = NULL;
}
-void upb_descreader_uninit(upb_descreader *r) {
+void upb_descreader_uninit(void *_r) {
+ upb_descreader *r = _r;
free(r->name);
- upb_status_uninit(&r->status);
upb_deflist_uninit(&r->defs);
free(r->default_string);
while (r->stack_len > 0) {
@@ -149,37 +213,37 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) {
}
// Handlers for google.protobuf.FileDescriptorProto.
-static bool file_startmsg(void *_r) {
- upb_descreader *r = _r;
+static bool file_startmsg(const upb_sinkframe *frame) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_descreader_startcontainer(r);
return true;
}
-static void file_endmsg(void *_r, upb_status *status) {
+static void file_endmsg(const upb_sinkframe *frame, upb_status *status) {
UPB_UNUSED(status);
- upb_descreader *r = _r;
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_descreader_endcontainer(r);
}
-static size_t file_onpackage(void *_r, void *fval, const char *buf, size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t file_onpackage(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// 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(void *_r) {
- upb_descreader *r = _r;
+static bool enumval_startmsg(const upb_sinkframe *frame) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
r->saw_number = false;
r->saw_name = false;
return true;
}
-static size_t enumval_onname(void *_r, void *fval, const char *buf, size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t enumval_onname(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// XXX: see comment at the top of the file.
free(r->name);
r->name = upb_strndup(buf, n);
@@ -187,16 +251,15 @@ static size_t enumval_onname(void *_r, void *fval, const char *buf, size_t n) {
return n;
}
-static bool enumval_onnumber(void *_r, void *fval, int32_t val) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static bool enumval_onnumber(const upb_sinkframe *frame, int32_t val) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
r->number = val;
r->saw_number = true;
return true;
}
-static void enumval_endmsg(void *_r, upb_status *status) {
- upb_descreader *r = _r;
+static void enumval_endmsg(const upb_sinkframe *frame, upb_status *status) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
if(!r->saw_number || !r->saw_name) {
upb_status_seterrliteral(status, "Enum value missing name or number.");
return;
@@ -214,16 +277,17 @@ static void enumval_endmsg(void *_r, upb_status *status) {
// Handlers for google.protobuf.EnumDescriptorProto.
-static bool enum_startmsg(void *_r) {
- upb_descreader *r = _r;
- upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs)));
+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);
return true;
}
-static void enum_endmsg(void *_r, upb_status *status) {
- upb_descreader *r = _r;
+static void enum_endmsg(const upb_sinkframe *frame, upb_status *status) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
- if (upb_def_fullname(upb_descreader_last((upb_descreader*)_r)) == NULL) {
+ if (upb_def_fullname(upb_descreader_last(r)) == NULL) {
upb_status_seterrliteral(status, "Enum had no name.");
return;
}
@@ -233,9 +297,9 @@ static void enum_endmsg(void *_r, upb_status *status) {
}
}
-static size_t enum_onname(void *_r, void *fval, const char *buf, size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t enum_onname(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// XXX: see comment at the top of the file.
char *fullname = upb_strndup(buf, n);
upb_def_setfullname(upb_descreader_last(r), fullname);
@@ -244,8 +308,8 @@ static size_t enum_onname(void *_r, void *fval, const char *buf, size_t n) {
}
// Handlers for google.protobuf.FieldDescriptorProto
-static bool field_startmsg(void *_r) {
- upb_descreader *r = _r;
+static bool field_startmsg(const upb_sinkframe *frame) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
r->f = upb_fielddef_new(&r->defs);
free(r->default_string);
r->default_string = NULL;
@@ -258,27 +322,19 @@ static bool parse_default(char *str, upb_value *d, int type) {
bool success = true;
if (str) {
switch(type) {
- case UPB_TYPE(INT32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(SFIXED32): upb_value_setint32(d, 0); break;
- case UPB_TYPE(INT64):
- case UPB_TYPE(SINT64):
- case UPB_TYPE(SFIXED64): upb_value_setint64(d, 0); break;
- case UPB_TYPE(UINT32):
- case UPB_TYPE(FIXED32): upb_value_setuint32(d, 0);
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64): upb_value_setuint64(d, 0); break;
- case UPB_TYPE(DOUBLE): upb_value_setdouble(d, 0); break;
- case UPB_TYPE(FLOAT): upb_value_setfloat(d, 0); break;
- case UPB_TYPE(BOOL): upb_value_setbool(d, false); break;
+ case UPB_TYPE_INT32: upb_value_setint32(d, 0); break;
+ case UPB_TYPE_INT64: upb_value_setint64(d, 0); break;
+ case UPB_TYPE_UINT32: upb_value_setuint32(d, 0);
+ case UPB_TYPE_UINT64: upb_value_setuint64(d, 0); break;
+ case UPB_TYPE_FLOAT: upb_value_setfloat(d, 0); break;
+ case UPB_TYPE_DOUBLE: upb_value_setdouble(d, 0); break;
+ case UPB_TYPE_BOOL: upb_value_setbool(d, false); break;
default: abort();
}
} else {
char *end;
switch (type) {
- case UPB_TYPE(INT32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(SFIXED32): {
+ case UPB_TYPE_INT32: {
long val = strtol(str, &end, 0);
if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
success = false;
@@ -286,14 +342,11 @@ static bool parse_default(char *str, upb_value *d, int type) {
upb_value_setint32(d, val);
break;
}
- case UPB_TYPE(INT64):
- case UPB_TYPE(SINT64):
- case UPB_TYPE(SFIXED64):
+ case UPB_TYPE_INT64:
upb_value_setint64(d, strtoll(str, &end, 0));
if (errno == ERANGE || *end) success = false;
break;
- case UPB_TYPE(UINT32):
- case UPB_TYPE(FIXED32): {
+ case UPB_TYPE_UINT32: {
unsigned long val = strtoul(str, &end, 0);
if (val > UINT32_MAX || errno == ERANGE || *end)
success = false;
@@ -301,20 +354,19 @@ static bool parse_default(char *str, upb_value *d, int type) {
upb_value_setuint32(d, val);
break;
}
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64):
+ case UPB_TYPE_UINT64:
upb_value_setuint64(d, strtoull(str, &end, 0));
if (errno == ERANGE || *end) success = false;
break;
- case UPB_TYPE(DOUBLE):
+ case UPB_TYPE_DOUBLE:
upb_value_setdouble(d, strtod(str, &end));
if (errno == ERANGE || *end) success = false;
break;
- case UPB_TYPE(FLOAT):
+ case UPB_TYPE_FLOAT:
upb_value_setfloat(d, strtof(str, &end));
if (errno == ERANGE || *end) success = false;
break;
- case UPB_TYPE(BOOL): {
+ case UPB_TYPE_BOOL: {
if (strcmp(str, "false") == 0)
upb_value_setbool(d, false);
else if (strcmp(str, "true") == 0)
@@ -328,8 +380,8 @@ static bool parse_default(char *str, upb_value *d, int type) {
return success;
}
-static void field_endmsg(void *_r, upb_status *status) {
- upb_descreader *r = _r;
+static void field_endmsg(const upb_sinkframe *frame, upb_status *status) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_fielddef *f = r->f;
// TODO: verify that all required fields were present.
assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL);
@@ -340,7 +392,7 @@ static void field_endmsg(void *_r, upb_status *status) {
upb_status_seterrliteral(status, "Submessages cannot have defaults.");
return;
}
- if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE(ENUM)) {
+ if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
upb_fielddef_setdefaultcstr(f, r->default_string);
} else {
upb_value val;
@@ -356,30 +408,27 @@ static void field_endmsg(void *_r, upb_status *status) {
}
}
-static bool field_ontype(void *_r, void *fval, int32_t val) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
- upb_fielddef_settype(r->f, val);
+static bool field_ontype(const upb_sinkframe *frame, int32_t val) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
+ upb_fielddef_setdescriptortype(r->f, val);
return true;
}
-static bool field_onlabel(void *_r, void *fval, int32_t val) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static bool field_onlabel(const upb_sinkframe *frame, int32_t val) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_fielddef_setlabel(r->f, val);
return true;
}
-static bool field_onnumber(void *_r, void *fval, int32_t val) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static bool field_onnumber(const upb_sinkframe *frame, int32_t val) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_fielddef_setnumber(r->f, val);
return true;
}
-static size_t field_onname(void *_r, void *fval, const char *buf, size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t field_onname(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
upb_fielddef_setname(r->f, name);
@@ -387,10 +436,9 @@ static size_t field_onname(void *_r, void *fval, const char *buf, size_t n) {
return n;
}
-static size_t field_ontypename(void *_r, void *fval, const char *buf,
- size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t field_ontypename(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
upb_fielddef_setsubdefname(r->f, name);
@@ -398,10 +446,9 @@ static size_t field_ontypename(void *_r, void *fval, const char *buf,
return n;
}
-static size_t field_ondefaultval(void *_r, void *fval, const char *buf,
- size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t field_ondefaultval(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// 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.
@@ -411,15 +458,16 @@ static size_t field_ondefaultval(void *_r, void *fval, const char *buf,
}
// Handlers for google.protobuf.DescriptorProto (representing a message).
-static bool msg_startmsg(void *_r) {
- upb_descreader *r = _r;
- upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs)));
+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);
upb_descreader_startcontainer(r);
return true;
}
-static void msg_endmsg(void *_r, upb_status *status) {
- upb_descreader *r = _r;
+static void msg_endmsg(const upb_sinkframe *frame, upb_status *status) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_msgdef *m = upb_descreader_top(r);
if(!upb_def_fullname(upb_upcast(m))) {
upb_status_seterrliteral(status, "Encountered message with no name.");
@@ -428,9 +476,9 @@ static void msg_endmsg(void *_r, upb_status *status) {
upb_descreader_endcontainer(r);
}
-static size_t msg_onname(void *_r, void *fval, const char *buf, size_t n) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static size_t msg_onname(const upb_sinkframe *frame,
+ const char *buf, size_t n) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_msgdef *m = upb_descreader_top(r);
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
@@ -439,18 +487,16 @@ static size_t msg_onname(void *_r, void *fval, const char *buf, size_t n) {
return n;
}
-static bool msg_onendfield(void *_r, void *fval) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static bool msg_onendfield(const upb_sinkframe *frame) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
upb_msgdef *m = upb_descreader_top(r);
upb_msgdef_addfield(m, r->f, &r->defs);
r->f = NULL;
return true;
}
-static bool discardfield(void *_r, void *fval) {
- UPB_UNUSED(fval);
- upb_descreader *r = _r;
+static bool discardfield(const upb_sinkframe *frame) {
+ upb_descreader *r = upb_sinkframe_userdata(frame);
// Discard extension field so we don't leak it.
upb_fielddef_unref(r->f, &r->defs);
r->f = NULL;
@@ -496,7 +542,8 @@ static void reghandlers(void *closure, upb_handlers *h) {
}
}
-const upb_handlers *upb_descreader_newhandlers(const void *owner) {
+const upb_handlers *upb_descreader_gethandlers(const void *owner) {
return upb_handlers_newfrozen(
- GOOGLE_PROTOBUF_FILEDESCRIPTORSET, owner, reghandlers, NULL);
+ GOOGLE_PROTOBUF_FILEDESCRIPTORSET, &upb_descreader_frametype,
+ owner, reghandlers, NULL);
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback