diff options
Diffstat (limited to 'src/upb_descriptor.c')
-rw-r--r-- | src/upb_descriptor.c | 530 |
1 files changed, 0 insertions, 530 deletions
diff --git a/src/upb_descriptor.c b/src/upb_descriptor.c deleted file mode 100644 index f70f1ba..0000000 --- a/src/upb_descriptor.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2008-2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman <jhaberman@gmail.com> - */ - -#include "upb_descriptor.h" - -#include <stdlib.h> -#include <errno.h> -#include "upb_def.h" - -// 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. */ -static char *upb_join(char *base, char *name) { - if (!base || strlen(base) == 0) { - return strdup(name); - } else { - char *ret = malloc(strlen(base) + strlen(name) + 2); - ret[0] = '\0'; - strcat(ret, base); - strcat(ret, "."); - strcat(ret, name); - return ret; - } -} - -/* upb_descreader ************************************************************/ - -// A upb_descreader builds a list of defs by handling a parse of a protobuf in -// the format defined in descriptor.proto. The output of a upb_descreader is -// a upb_symtabtxn. - -static upb_def *upb_deflist_last(upb_deflist *l) { - return l->defs[l->len-1]; -} - -// Qualify the defname for all defs starting with offset "start" with "str". -static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) { - for(uint32_t i = start; i < l->len; i++) { - upb_def *def = l->defs[i]; - char *name = def->fqname; - def->fqname = upb_join(str, name); - free(name); - } -} - -// Forward declares for top-level file descriptors. -static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h); -static upb_mhandlers * upb_enumdef_register_EnumDescriptorProto(upb_handlers *h); - -void upb_descreader_init(upb_descreader *r, upb_symtabtxn *txn) { - upb_deflist_init(&r->defs); - upb_status_init(&r->status); - r->txn = txn; - r->stack_len = 0; - r->name = NULL; - r->default_string = NULL; -} - -void upb_descreader_uninit(upb_descreader *r) { - free(r->name); - upb_status_uninit(&r->status); - upb_deflist_uninit(&r->defs); - free(r->default_string); - while (r->stack_len > 0) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; - free(f->name); - } -} - -static upb_msgdef *upb_descreader_top(upb_descreader *r) { - if (r->stack_len <= 1) return NULL; - int index = r->stack[r->stack_len-1].start - 1; - assert(index >= 0); - return upb_downcast_msgdef(r->defs.defs[index]); -} - -static upb_def *upb_descreader_last(upb_descreader *r) { - return upb_deflist_last(&r->defs); -} - -// Start/end handlers for FileDescriptorProto and DescriptorProto (the two -// entities that have names and can contain sub-definitions. -void upb_descreader_startcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[r->stack_len++]; - f->start = r->defs.len; - f->name = NULL; -} - -void upb_descreader_endcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; - upb_deflist_qualify(&r->defs, f->name, f->start); - free(f->name); - f->name = NULL; -} - -void upb_descreader_setscopename(upb_descreader *r, char *str) { - upb_descreader_frame *f = &r->stack[r->stack_len-1]; - free(f->name); - f->name = str; -} - -// Handlers for google.protobuf.FileDescriptorProto. -static upb_flow_t upb_descreader_FileDescriptorProto_startmsg(void *_r) { - upb_descreader *r = _r; - upb_descreader_startcontainer(r); - return UPB_CONTINUE; -} - -static void upb_descreader_FileDescriptorProto_endmsg(void *_r, - upb_status *status) { - (void)status; - upb_descreader *r = _r; - upb_descreader_endcontainer(r); -} - -static upb_flow_t upb_descreader_FileDescriptorProto_package(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_descreader_setscopename(r, upb_strref_dup(upb_value_getstrref(val))); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_descreader_register_FileDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_descreader_FileDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_descreader_FileDescriptorProto_endmsg); - -#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDNUM -#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(PACKAGE), FTYPE(PACKAGE), false); - upb_fhandlers_setvalue(f, &upb_descreader_FileDescriptorProto_package); - - upb_mhandlers_newfhandlers_subm(m, FNUM(MESSAGE_TYPE), FTYPE(MESSAGE_TYPE), true, - upb_msgdef_register_DescriptorProto(h)); - upb_mhandlers_newfhandlers_subm(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true, - upb_enumdef_register_EnumDescriptorProto(h)); - // TODO: services, extensions - return m; -} -#undef FNUM -#undef FTYPE - -// Handlers for google.protobuf.FileDescriptorSet. -static void upb_descreader_FileDescriptorSet_onendmsg(void *_r, - upb_status *status) { - // Move all defs (which are now guaranteed to be fully-qualified) to the txn. - upb_descreader *r = _r; - if (upb_ok(status)) { - for (unsigned int i = 0; i < r->defs.len; i++) { - // TODO: check return for duplicate def. - upb_symtabtxn_add(r->txn, r->defs.defs[i]); - } - r->defs.len = 0; - } -} - -static upb_mhandlers *upb_descreader_register_FileDescriptorSet(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setendmsg(m, upb_descreader_FileDescriptorSet_onendmsg); - -#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDNUM -#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDTYPE - upb_mhandlers_newfhandlers_subm(m, FNUM(FILE), FTYPE(FILE), true, - upb_descreader_register_FileDescriptorProto(h)); - return m; -} -#undef FNUM -#undef FTYPE - -upb_mhandlers *upb_descreader_reghandlers(upb_handlers *h) { - h->should_jit = false; - return upb_descreader_register_FileDescriptorSet(h); -} - -// google.protobuf.EnumValueDescriptorProto. -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_startmsg(void *_r) { - upb_descreader *r = _r; - r->saw_number = false; - r->saw_name = false; - return UPB_CONTINUE; -} - -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_name(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - free(r->name); - r->name = upb_strref_dup(upb_value_getstrref(val)); - r->saw_name = true; - return UPB_CONTINUE; -} - -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_number(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - r->number = upb_value_getint32(val); - r->saw_number = true; - return UPB_CONTINUE; -} - -static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_r, - upb_status *status) { - upb_descreader *r = _r; - if(!r->saw_number || !r->saw_name) { - upb_status_setf(status, UPB_ERROR, "Enum value missing name or number."); - return; - } - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); - if (upb_inttable_count(&e->iton) == 0) { - // The default value of an enum (in the absence of an explicit default) is - // its first listed value. - upb_enumdef_setdefault(e, r->number); - } - upb_enumdef_addval(e, r->name, r->number); - free(r->name); - r->name = NULL; -} - -static upb_mhandlers *upb_enumdef_register_EnumValueDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumValueDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_enumdef_EnumValueDescriptorProto_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f; - f = upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_name); - - f = upb_mhandlers_newfhandlers(m, FNUM(NUMBER), FTYPE(NUMBER), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_number); - return m; -} -#undef FNUM -#undef FTYPE - -// google.protobuf.EnumDescriptorProto. -static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_r) { - upb_descreader *r = _r; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_enumdef_new())); - return UPB_CONTINUE; -} - -static void upb_enumdef_EnumDescriptorProto_endmsg(void *_r, upb_status *status) { - upb_descreader *r = _r; - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); - if (upb_descreader_last((upb_descreader*)_r)->fqname == NULL) { - upb_status_setf(status, UPB_ERROR, "Enum had no name."); - return; - } - if (upb_inttable_count(&e->iton) == 0) { - upb_status_setf(status, UPB_ERROR, "Enum had no values."); - return; - } -} - -static upb_flow_t upb_enumdef_EnumDescriptorProto_name(void *_r, - upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); - free(e->base.fqname); - e->base.fqname = upb_strref_dup(upb_value_getstrref(val)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_enumdef_EnumDescriptorProto_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumDescriptorProto_name); - - upb_mhandlers_newfhandlers_subm(m, FNUM(VALUE), FTYPE(VALUE), true, - upb_enumdef_register_EnumValueDescriptorProto(h)); - return m; -} -#undef FNUM -#undef FTYPE - -static upb_flow_t upb_fielddef_startmsg(void *_r) { - upb_descreader *r = _r; - r->f = upb_fielddef_new(); - return UPB_CONTINUE; -} - -// Converts the default value in string "str" into "d". Passes a ref on str. -// Returns true on success. -static bool upb_fielddef_parsedefault(char *str, upb_value *d, int type) { - bool success = true; - if (type == UPB_TYPE(STRING) || type == UPB_TYPE(BYTES) || type == UPB_TYPE(ENUM)) { - // We'll keep the ref we had on it. We include enums in this case because - // we need the enumdef to resolve the name, but we may not have it yet. - // We'll resolve it later. - if (!str) str = strdup(""); - upb_value_setptr(d, str); - } else if (type == UPB_TYPE(MESSAGE) || type == UPB_TYPE(GROUP)) { - // We don't expect to get a default value. - free(str); - if (str != NULL) success = false; - } else if (type == UPB_TYPE(BOOL)) { - if (!str || strcmp(str, "false") == 0) - upb_value_setbool(d, false); - else if (strcmp(str, "true") == 0) - upb_value_setbool(d, true); - else - success = false; - free(str); - } else { - // The strto* functions need the string to be NULL-terminated. - if (!str) str = strdup("0"); - char *end; - switch (type) { - case UPB_TYPE(INT32): - case UPB_TYPE(SINT32): - case UPB_TYPE(SFIXED32): { - long val = strtol(str, &end, 0); - if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) - success = false; - else - upb_value_setint32(d, val); - break; - } - case UPB_TYPE(INT64): - case UPB_TYPE(SINT64): - case UPB_TYPE(SFIXED64): - upb_value_setint64(d, strtoll(str, &end, 0)); - if (errno == ERANGE || *end) success = false; - break; - case UPB_TYPE(UINT32): - case UPB_TYPE(FIXED32): { - unsigned long val = strtoul(str, &end, 0); - if (val > UINT32_MAX || errno == ERANGE || *end) - success = false; - else - upb_value_setuint32(d, val); - break; - } - case UPB_TYPE(UINT64): - case UPB_TYPE(FIXED64): - upb_value_setuint64(d, strtoull(str, &end, 0)); - if (errno == ERANGE || *end) success = false; - break; - case UPB_TYPE(DOUBLE): - upb_value_setdouble(d, strtod(str, &end)); - if (errno == ERANGE || *end) success = false; - break; - case UPB_TYPE(FLOAT): - upb_value_setfloat(d, strtof(str, &end)); - if (errno == ERANGE || *end) success = false; - break; - } - free(str); - } - return success; -} - -static void upb_fielddef_endmsg(void *_r, upb_status *status) { - upb_descreader *r = _r; - upb_fielddef *f = r->f; - // TODO: verify that all required fields were present. - assert(f->number != -1 && f->name != NULL); - assert((f->def != NULL) == upb_hasdef(f)); - - // Field was successfully read, add it as a field of the msgdef. - upb_msgdef *m = upb_descreader_top(r); - upb_msgdef_addfield(m, f); - char *dstr = r->default_string; - r->default_string = NULL; - upb_value val; - if (!upb_fielddef_parsedefault(dstr, &val, f->type)) { - // We don't worry too much about giving a great error message since the - // compiler should have ensured this was correct. - upb_status_setf(status, UPB_ERROR, "Error converting default value."); - return; - } - upb_fielddef_setdefault(f, val); -} - -static upb_flow_t upb_fielddef_ontype(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_fielddef_settype(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_onlabel(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_fielddef_setlabel(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_onnumber(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - upb_fielddef_setnumber(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_onname(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - char *name = upb_strref_dup(upb_value_getstrref(val)); - upb_fielddef_setname(r->f, name); - free(name); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_ontypename(void *_r, upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - char *name = upb_strref_dup(upb_value_getstrref(val)); - upb_fielddef_settypename(r->f, name); - free(name); - return UPB_CONTINUE; -} - -static upb_flow_t upb_fielddef_ondefaultval(void *_r, upb_value fval, - upb_value val) { - (void)fval; - upb_descreader *r = _r; - // Have to convert from string to the correct type, but we might not know the - // type yet. - free(r->default_string); - r->default_string = upb_strref_dup(upb_value_getstrref(val)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_fielddef_register_FieldDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_fielddef_startmsg); - upb_mhandlers_setendmsg(m, &upb_fielddef_endmsg); - -#define FIELD(name, handler) \ - upb_fhandlers_setvalue( \ - upb_mhandlers_newfhandlers(m, \ - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDNUM, \ - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDTYPE, \ - false), \ - handler); - FIELD(TYPE, &upb_fielddef_ontype); - FIELD(LABEL, &upb_fielddef_onlabel); - FIELD(NUMBER, &upb_fielddef_onnumber); - FIELD(NAME, &upb_fielddef_onname); - FIELD(TYPE_NAME, &upb_fielddef_ontypename); - FIELD(DEFAULT_VALUE, &upb_fielddef_ondefaultval); - return m; -} -#undef FNUM -#undef FTYPE - - -// google.protobuf.DescriptorProto. -static upb_flow_t upb_msgdef_startmsg(void *_r) { - upb_descreader *r = _r; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_msgdef_new())); - upb_descreader_startcontainer(r); - return UPB_CONTINUE; -} - -static void upb_msgdef_endmsg(void *_r, upb_status *status) { - upb_descreader *r = _r; - upb_msgdef *m = upb_descreader_top(r); - if(!m->base.fqname) { - upb_status_setf(status, UPB_ERROR, "Encountered message with no name."); - return; - } - - upb_msgdef_layout(m); - upb_descreader_endcontainer(r); -} - -static upb_flow_t upb_msgdef_onname(void *_r, upb_value fval, upb_value val) { - (void)fval; - upb_descreader *r = _r; - assert(val.type == UPB_TYPE(STRING)); - upb_msgdef *m = upb_descreader_top(r); - free(m->base.fqname); - m->base.fqname = upb_strref_dup(upb_value_getstrref(val)); - upb_descreader_setscopename(r, strdup(m->base.fqname)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_msgdef_startmsg); - upb_mhandlers_setendmsg(m, &upb_msgdef_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_msgdef_onname); - - upb_mhandlers_newfhandlers_subm(m, FNUM(FIELD), FTYPE(FIELD), true, - upb_fielddef_register_FieldDescriptorProto(h)); - upb_mhandlers_newfhandlers_subm(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true, - upb_enumdef_register_EnumDescriptorProto(h)); - - // DescriptorProto is self-recursive, so we must link the definition. - upb_mhandlers_newfhandlers_subm( - m, FNUM(NESTED_TYPE), FTYPE(NESTED_TYPE), true, m); - - // TODO: extensions. - return m; -} -#undef FNUM -#undef FTYPE - |