diff options
Diffstat (limited to 'upb')
-rw-r--r-- | upb/bytestream.h | 13 | ||||
-rw-r--r-- | upb/def.c | 129 | ||||
-rw-r--r-- | upb/def.h | 58 | ||||
-rw-r--r-- | upb/descriptor.c | 4 | ||||
-rw-r--r-- | upb/msg.h | 9 | ||||
-rw-r--r-- | upb/upb.h | 2 |
6 files changed, 149 insertions, 66 deletions
diff --git a/upb/bytestream.h b/upb/bytestream.h index 2a6f7d2..6090d6a 100644 --- a/upb/bytestream.h +++ b/upb/bytestream.h @@ -119,16 +119,17 @@ typedef struct _upb_strref { // the actual pointers). const char *ptr; - // Bytesrc from which this string data comes. This is only guaranteed to be - // alive from inside the callback; however if the handler knows more about - // its type and how to prolong its life, it may do so. - upb_bytesrc *bytesrc; + // Length of the string. + uint32_t len; // Offset in the bytesrc that represents the beginning of this string. uint32_t stream_offset; - // Length of the string. - uint32_t len; + // Bytesrc from which this string data comes. May be NULL if ptr is set. If + // non-NULL, the bytesrc is only guaranteed to be alive from inside the + // callback; however if the handler knows more about its type and how to + // prolong its life, it may do so. + upb_bytesrc *bytesrc; // Possibly add optional members here like start_line, start_column, etc. } upb_strref; @@ -38,9 +38,14 @@ static void upb_msgdef_free(upb_msgdef *m); static void upb_enumdef_free(upb_enumdef *e); static void upb_unresolveddef_free(struct _upb_unresolveddef *u); -#ifndef NDEBUG -static bool upb_def_ismutable(upb_def *def) { return def->symtab == NULL; } -#endif +bool upb_def_ismutable(upb_def *def) { return def->symtab == NULL; } + +bool upb_def_setfqname(upb_def *def, const char *fqname) { + assert(upb_def_ismutable(def)); + free(def->fqname); + def->fqname = strdup(fqname); + return true; // TODO: check for acceptable characters. +} static void upb_def_free(upb_def *def) { switch (def->type) { @@ -73,7 +78,7 @@ void upb_def_ref(upb_def *def) { static void upb_def_movetosymtab(upb_def *d, upb_symtab *s) { assert(upb_atomic_read(&d->refcount) > 0); d->symtab = s; - if (!upb_atomic_unref(&d->refcount)) upb_symtab_ref(s); + upb_symtab_ref(s); upb_msgdef *m = upb_dyncast_msgdef(d); if (m) upb_inttable_compact(&m->itof); } @@ -216,6 +221,7 @@ upb_fielddef *upb_fielddef_new() { f->hasbit = 0; f->offset = 0; f->number = 0; // not a valid field number. + f->hasdefault = false; f->name = NULL; f->accessor = NULL; upb_value_setfielddef(&f->fval, f); @@ -260,6 +266,17 @@ upb_fielddef *upb_fielddef_dup(upb_fielddef *f) { return f; } +bool upb_fielddef_ismutable(upb_fielddef *f) { + return !f->msgdef || upb_def_ismutable(UPB_UPCAST(f->msgdef)); +} + +upb_def *upb_fielddef_subdef(upb_fielddef *f) { + if (upb_hassubdef(f) && !upb_fielddef_ismutable(f)) + return f->def; + else + return NULL; +} + static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { assert(upb_dyncast_unresolveddef(f->def)); upb_def_unref(f->def); @@ -286,25 +303,30 @@ static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { return true; } -void upb_fielddef_setnumber(upb_fielddef *f, int32_t number) { +bool upb_fielddef_setnumber(upb_fielddef *f, int32_t number) { assert(f->msgdef == NULL); f->number = number; + return true; } -void upb_fielddef_setname(upb_fielddef *f, const char *name) { +bool upb_fielddef_setname(upb_fielddef *f, const char *name) { assert(f->msgdef == NULL); f->name = strdup(name); + return true; } -void upb_fielddef_settype(upb_fielddef *f, uint8_t type) { +bool upb_fielddef_settype(upb_fielddef *f, uint8_t type) { assert(!f->finalized); f->type = type; + return true; } -void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label) { +bool upb_fielddef_setlabel(upb_fielddef *f, uint8_t label) { assert(!f->finalized); f->label = label; + return true; } + void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) { assert(!f->finalized); // TODO: string ownership? @@ -322,9 +344,10 @@ void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl) f->accessor = vtbl; } -void upb_fielddef_settypename(upb_fielddef *f, const char *name) { +bool upb_fielddef_settypename(upb_fielddef *f, const char *name) { upb_def_unref(f->def); f->def = UPB_UPCAST(upb_unresolveddef_new(name)); + return true; } // Returns an ordering of fields based on: @@ -363,8 +386,8 @@ upb_msgdef *upb_msgdef_new() { upb_strtable_init(&m->ntof, 4, sizeof(upb_ntof_ent)); m->size = 0; m->hasbit_bytes = 0; - m->extension_start = 0; - m->extension_end = 0; + m->extstart = 0; + m->extend = 0; return m; } @@ -382,11 +405,12 @@ upb_msgdef *upb_msgdef_dup(upb_msgdef *m) { upb_msgdef *newm = upb_msgdef_new(); newm->size = m->size; newm->hasbit_bytes = m->hasbit_bytes; - newm->extension_start = m->extension_start; - newm->extension_end = m->extension_end; + newm->extstart = m->extstart; + newm->extend = m->extend; upb_msg_iter i; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) + for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { upb_msgdef_addfield(newm, upb_fielddef_dup(upb_msg_iter_field(i))); + } return newm; } @@ -400,28 +424,38 @@ void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes) { m->hasbit_bytes = bytes; } -void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start) { +bool upb_msgdef_setextrange(upb_msgdef *m, uint32_t start, uint32_t end) { assert(upb_def_ismutable(UPB_UPCAST(m))); - m->extension_start = start; + if (start == 0 && end == 0) { + // Clearing the extension range -- ok to fall through. + } else if (start >= end || start < 1 || end > UPB_MAX_FIELDNUMBER) { + return false; + } + m->extstart = start; + m->extend = start; + return true; } -void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end) { - assert(upb_def_ismutable(UPB_UPCAST(m))); - m->extension_end = end; -} +bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef **fields, int n) { + // Check constraints for all fields before performing any action. + for (int i = 0; i < n; i++) { + upb_fielddef *f = fields[i]; + assert(upb_atomic_read(&f->refcount) > 0); + if (f->name == NULL || f->number == 0 || + upb_msgdef_itof(m, f->number) || upb_msgdef_ntof(m, f->name)) + return false; + } -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f) { - assert(upb_atomic_read(&f->refcount) > 0); - if (!upb_atomic_unref(&f->refcount)) upb_msgdef_ref(m); - if (upb_msgdef_itof(m, f->number) || upb_msgdef_ntof(m, f->name)) { - upb_fielddef_unref(f); - return false; + // Constraint checks ok, perform the action. + for (int i = 0; i < n; i++) { + upb_fielddef *f = fields[i]; + upb_msgdef_ref(m); + assert(f->msgdef == NULL); + f->msgdef = m; + upb_itof_ent itof_ent = {0, f}; + upb_inttable_insert(&m->itof, f->number, &itof_ent); + upb_strtable_insert(&m->ntof, f->name, &f); } - assert(f->msgdef == NULL); - f->msgdef = m; - upb_itof_ent itof_ent = {0, f}; - upb_inttable_insert(&m->itof, f->number, &itof_ent); - upb_strtable_insert(&m->ntof, f->name, &f); return true; } @@ -608,7 +642,7 @@ bool upb_symtab_dfs(upb_def *def, upb_def **open_defs, int n, open_defs[n++] = def; for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { upb_fielddef *f = upb_msg_iter_field(i); - if (!upb_hasdef(f)) continue; + if (!upb_hassubdef(f)) continue; needcopy |= upb_symtab_dfs(f->def, open_defs, n, addtab); } } @@ -664,7 +698,36 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) { upb_msg_iter j; for(j = upb_msg_begin(m); !upb_msg_done(j); j = upb_msg_next(m, j)) { upb_fielddef *f = upb_msg_iter_field(j); - if(!upb_hasdef(f)) continue; // No resolving necessary. + if (f->type == 0) { + upb_status_setf(status, UPB_ERROR, "Field type was not set."); + return false; + } + + // Set default default if none was set explicitly. + if (!f->hasdefault) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE(DOUBLE): upb_value_setdouble(&f->defaultval, 0); break; + case UPB_TYPE(FLOAT): upb_value_setfloat(&f->defaultval, 0); break; + case UPB_TYPE(UINT64): + case UPB_TYPE(FIXED64): upb_value_setuint64(&f->defaultval, 0); break; + case UPB_TYPE(INT64): + case UPB_TYPE(SFIXED64): + case UPB_TYPE(SINT64): upb_value_setint64(&f->defaultval, 0); break; + case UPB_TYPE(INT32): + case UPB_TYPE(SINT32): + case UPB_TYPE(ENUM): + case UPB_TYPE(SFIXED32): upb_value_setint32(&f->defaultval, 0); break; + case UPB_TYPE(UINT32): + case UPB_TYPE(FIXED32): upb_value_setuint32(&f->defaultval, 0); break; + case UPB_TYPE(BOOL): upb_value_setbool(&f->defaultval, false); break; + case UPB_TYPE(STRING): + case UPB_TYPE(BYTES): + case UPB_TYPE(GROUP): + case UPB_TYPE(MESSAGE): break; // do nothing for now. + } + } + + if (!upb_hassubdef(f)) continue; // No resolving necessary. const char *name = upb_downcast_unresolveddef(f->def)->name; // Resolve from either the addtab (pending adds) or symtab (existing @@ -14,6 +14,10 @@ * These defs are mutable (and not thread-safe) when first created. * Once they are added to a defbuilder (and later its symtab) they become * immutable. + * + * TODO: consider making thread-safe even when first created by using mutexes + * internally. Would also have to change any methods returning pointers to + * return copies instead. */ #ifndef UPB_DEF_H_ @@ -58,6 +62,11 @@ void upb_def_ref(upb_def *def); void upb_def_unref(upb_def *def); upb_def *upb_def_dup(upb_def *def); +// A def is mutable until it has been added to a symtab. +bool upb_def_ismutable(upb_def *def); +INLINE const char *upb_def_fqname(upb_def *def) { return def->fqname; } +bool upb_def_setfqname(upb_def *def, const char *fqname); // Only if mutable. + #define UPB_UPCAST(ptr) (&(ptr)->base) @@ -77,6 +86,8 @@ typedef struct _upb_fielddef { uint8_t label; // Use UPB_LABEL() constants. int16_t hasbit; uint16_t offset; + bool hasdefault; + bool active; int32_t number; char *name; upb_value defaultval; // Only meaningful for non-repeated scalars and strings. @@ -89,6 +100,9 @@ void upb_fielddef_ref(upb_fielddef *f); void upb_fielddef_unref(upb_fielddef *f); upb_fielddef *upb_fielddef_dup(upb_fielddef *f); +// A fielddef is mutable until its msgdef has been added to a symtab. +bool upb_fielddef_ismutable(upb_fielddef *f); + // Read accessors. May be called any time. INLINE uint8_t upb_fielddef_type(upb_fielddef *f) { return f->type; } INLINE uint8_t upb_fielddef_label(upb_fielddef *f) { return f->label; } @@ -113,18 +127,18 @@ upb_def *upb_fielddef_subdef(upb_fielddef *f); // Write accessors. "Number" and "name" must be set before the fielddef is // added to a msgdef. For the moment we do not allow these to be set once // the fielddef is added to a msgdef -- this could be relaxed in the future. -void upb_fielddef_setnumber(upb_fielddef *f, int32_t number); -void upb_fielddef_setname(upb_fielddef *f, const char *name); +bool upb_fielddef_setnumber(upb_fielddef *f, int32_t number); +bool upb_fielddef_setname(upb_fielddef *f, const char *name); // These writers may be called at any time prior to being put in a symtab. -void upb_fielddef_settype(upb_fielddef *f, uint8_t type); -void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label); +bool upb_fielddef_settype(upb_fielddef *f, uint8_t type); +bool upb_fielddef_setlabel(upb_fielddef *f, uint8_t label); void upb_fielddef_setdefault(upb_fielddef *f, upb_value value); void upb_fielddef_setfval(upb_fielddef *f, upb_value fval); void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl); // The name of the message or enum this field is referring to. Must be found -// at name resolution time (when the symtabtxn is committed to the symtab). -void upb_fielddef_settypename(upb_fielddef *f, const char *name); +// at name resolution time (when upb_symtab_add() is called). +bool upb_fielddef_settypename(upb_fielddef *f, const char *name); // A variety of tests about the type of a field. INLINE bool upb_issubmsgtype(upb_fieldtype_t type) { @@ -141,7 +155,7 @@ INLINE bool upb_isstring(upb_fielddef *f) { return upb_isstringtype(f->type); } INLINE bool upb_isseq(upb_fielddef *f) { return f->label == UPB_LABEL(REPEATED); } // Does the type of this field imply that it should contain an associated def? -INLINE bool upb_hasdef(upb_fielddef *f) { +INLINE bool upb_hassubdef(upb_fielddef *f) { return upb_issubmsg(f) || f->type == UPB_TYPE(ENUM); } @@ -160,8 +174,7 @@ typedef struct _upb_msgdef { uint16_t size; uint8_t hasbit_bytes; // The range of tag numbers used to store extensions. - uint32_t extension_start; - uint32_t extension_end; + uint32_t extstart, extend; } upb_msgdef; // Hash table entries for looking up fields by name or number. @@ -170,7 +183,6 @@ typedef struct { upb_fielddef *f; } upb_itof_ent; typedef struct { - upb_strtable_entry e; upb_fielddef *f; } upb_ntof_ent; @@ -189,25 +201,23 @@ INLINE uint16_t upb_msgdef_size(upb_msgdef *m) { return m->size; } INLINE uint8_t upb_msgdef_hasbit_bytes(upb_msgdef *m) { return m->hasbit_bytes; } -INLINE uint32_t upb_msgdef_extension_start(upb_msgdef *m) { - return m->extension_start; -} -INLINE uint32_t upb_msgdef_extension_end(upb_msgdef *m) { - return m->extension_end; -} +INLINE uint32_t upb_msgdef_extstart(upb_msgdef *m) { return m->extstart; } +INLINE uint32_t upb_msgdef_extend(upb_msgdef *m) { return m->extend; } // Write accessors. May only be called before the msgdef is in a symtab. void upb_msgdef_setsize(upb_msgdef *m, uint16_t size); void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes); -void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start); -void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end); +bool upb_msgdef_setextrange(upb_msgdef *m, uint32_t start, uint32_t end); -// Adds a fielddef to a msgdef, and passes a ref on the field to the msgdef. +// Adds a fielddef to a msgdef. Caller retains its ref on the fielddef. // May only be done before the msgdef is in a symtab. The fielddef's name and // number must be set, and the message may not already contain any field with -// this name or number -- if it does, the fielddef is unref'd and false is -// returned. The fielddef may not already belong to another message. -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f); +// this name or number, and this fielddef may not be part of another message, +// otherwise false is returned and no action is performed. +bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef **f, int n); +INLINE bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f) { + return upb_msgdef_addfields(m, &f, 1); +} // Sets the layout of all fields according to default rules: // 1. Hasbits for required fields come first, then optional fields. @@ -374,8 +384,8 @@ upb_def **upb_symtab_getdefs(upb_symtab *s, int *n, upb_deftype_t type); // Adds the given defs to the symtab, resolving all symbols. Only one def per // name may be in the list, but defs can replace existing defs in the symtab. // The entire operation either succeeds or fails. If the operation fails, the -// symtab is unchanged, false is returned, and status indicates the error. A -// ref on the defs is passed to the symtab iff the operation succeeds. +// symtab is unchanged, false is returned, and status indicates the error. The +// caller retains its ref on all defs in all cases. bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status); // Frees defs that are no longer active in the symtab and are no longer diff --git a/upb/descriptor.c b/upb/descriptor.c index 568a0d2..fbaef29 100644 --- a/upb/descriptor.c +++ b/upb/descriptor.c @@ -367,11 +367,13 @@ static void upb_fielddef_endmsg(void *_r, upb_status *status) { 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)); + assert((f->def != NULL) == upb_hassubdef(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); + upb_fielddef_unref(f); + r->f = NULL; char *dstr = r->default_string; r->default_string = NULL; upb_value val; @@ -92,12 +92,17 @@ INLINE bool upb_msg_has(void *m, upb_fielddef *f) { return f->accessor && f->accessor->has(m, f->fval); } -// May only be called for fields that are known to be set. +// May only be called for fields that have accessors. INLINE upb_value upb_msg_get(void *m, upb_fielddef *f) { - assert(upb_msg_has(m, f)); + assert(f->accessor); return f->accessor->get(m, f->fval); } +INLINE void upb_msg_set(void *m, upb_fielddef *f, upb_value val) { + assert(f->accessor); + f->accessor->set(m, f->fval, val); +} + INLINE void *upb_seq_begin(void *s, upb_fielddef *f) { assert(f->accessor); return f->accessor->seqbegin(s); @@ -64,6 +64,8 @@ INLINE size_t upb_align_up(size_t val, size_t align) { // An individual string or array is unaffected by this 16k byte limit. #define UPB_MAX_FIELDS (2048) +#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) + // Nested type names are separated by periods. #define UPB_SYMBOL_SEPARATOR '.' |