From cfdb9907cb87d15eaab72ceefbfa42fd7a4c3127 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Sat, 11 May 2013 16:45:38 -0700 Subject: Synced with 3 months of Google-internal development. Major changes: - Got rid of all bytestream interfaces in favor of using regular handlers. - new Pipeline object represents a upb pipeline, does bump allocation internally to manage memory. - proto2 support now can handle extensions. --- upb/descriptor/reader.c | 269 ++++++++++++++++++++++++++++-------------------- 1 file changed, 158 insertions(+), 111 deletions(-) (limited to 'upb/descriptor/reader.c') 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 #include #include -#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); } -- cgit v1.2.3