From 621c0cdcb5efc4f7c2382031becded018ef0b62b Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sun, 4 Sep 2011 19:29:36 -0700 Subject: Const invasion: large parts of upb made const-correct. --- upb/atomic.h | 20 +++--- upb/bytestream.c | 11 ++-- upb/bytestream.h | 10 +-- upb/def.c | 71 ++++++++++++-------- upb/def.h | 172 ++++++++++++++++++++++++++++-------------------- upb/handlers.c | 4 +- upb/handlers.h | 14 ++-- upb/msg.c | 31 ++++----- upb/msg.h | 24 +++---- upb/pb/decoder_x86.dasc | 4 +- upb/pb/glue.c | 27 ++++---- upb/pb/glue.h | 23 +++++-- upb/pb/textprinter.c | 14 ++-- upb/pb/textprinter.h | 2 +- upb/table.c | 27 ++++---- upb/table.h | 24 +++---- upb/upb.c | 5 +- upb/upb.h | 13 ++-- 18 files changed, 280 insertions(+), 216 deletions(-) (limited to 'upb') diff --git a/upb/atomic.h b/upb/atomic.h index e82ad8f..2478fe4 100644 --- a/upb/atomic.h +++ b/upb/atomic.h @@ -130,11 +130,11 @@ INLINE bool upb_atomic_only(upb_atomic_t *a) { typedef struct { } upb_rwlock_t; -INLINE void upb_rwlock_init(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_destroy(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_rdlock(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_wrlock(upb_rwlock_t *l) { (void)l; } -INLINE void upb_rwlock_unlock(upb_rwlock_t *l) { (void)l; } +INLINE void upb_rwlock_init(const upb_rwlock_t *l) { (void)l; } +INLINE void upb_rwlock_destroy(const upb_rwlock_t *l) { (void)l; } +INLINE void upb_rwlock_rdlock(const upb_rwlock_t *l) { (void)l; } +INLINE void upb_rwlock_wrlock(const upb_rwlock_t *l) { (void)l; } +INLINE void upb_rwlock_unlock(const upb_rwlock_t *l) { (void)l; } #elif defined(UPB_USE_PTHREADS) @@ -144,27 +144,27 @@ typedef struct { pthread_rwlock_t lock; } upb_rwlock_t; -INLINE void upb_rwlock_init(upb_rwlock_t *l) { +INLINE void upb_rwlock_init(const upb_rwlock_t *l) { /* TODO: check return value. */ pthread_rwlock_init(&l->lock, NULL); } -INLINE void upb_rwlock_destroy(upb_rwlock_t *l) { +INLINE void upb_rwlock_destroy(const upb_rwlock_t *l) { /* TODO: check return value. */ pthread_rwlock_destroy(&l->lock); } -INLINE void upb_rwlock_rdlock(upb_rwlock_t *l) { +INLINE void upb_rwlock_rdlock(const upb_rwlock_t *l) { /* TODO: check return value. */ pthread_rwlock_rdlock(&l->lock); } -INLINE void upb_rwlock_wrlock(upb_rwlock_t *l) { +INLINE void upb_rwlock_wrlock(const upb_rwlock_t *l) { /* TODO: check return value. */ pthread_rwlock_wrlock(&l->lock); } -INLINE void upb_rwlock_unlock(upb_rwlock_t *l) { +INLINE void upb_rwlock_unlock(const upb_rwlock_t *l) { /* TODO: check return value. */ pthread_rwlock_unlock(&l->lock); } diff --git a/upb/bytestream.c b/upb/bytestream.c index 09a1fb9..36be4b1 100644 --- a/upb/bytestream.c +++ b/upb/bytestream.c @@ -14,7 +14,7 @@ // We can make this configurable if necessary. #define BUF_SIZE 32768 -char *upb_strref_dup(struct _upb_strref *r) { +char *upb_strref_dup(const struct _upb_strref *r) { char *ret = (char*)malloc(r->len + 1); upb_bytesrc_read(r->bytesrc, r->stream_offset, r->len, ret); ret[r->len] = '\0'; @@ -38,7 +38,7 @@ int upb_stdio_cmpbuf(const void *_key, const void *_elem) { return (*ofs / BUF_SIZE) - (buf->ofs / BUF_SIZE); } -static upb_stdio_buf *upb_stdio_findbuf(upb_stdio *s, uint64_t ofs) { +static upb_stdio_buf *upb_stdio_findbuf(const upb_stdio *s, uint64_t ofs) { // TODO: it is probably faster to linear search short lists, and to // special-case the last one or two bufs. return bsearch(&ofs, s->bufs, s->nbuf, sizeof(*s->bufs), &upb_stdio_cmpbuf); @@ -86,7 +86,7 @@ size_t upb_stdio_fetch(void *src, uint64_t ofs, upb_status *s) { return buf->ofs + buf->len; } -void upb_stdio_read(void *src, uint64_t src_ofs, size_t len, char *dst) { +void upb_stdio_read(const void *src, uint64_t src_ofs, size_t len, char *dst) { upb_stdio_buf *buf = upb_stdio_findbuf(src, src_ofs); src_ofs -= buf->ofs; memcpy(dst, &buf->data[src_ofs], BUF_SIZE - src_ofs); @@ -203,8 +203,9 @@ size_t upb_stringsrc_fetch(void *_src, uint64_t ofs, upb_status *s) { return src->len - ofs; } -void upb_stringsrc_read(void *_src, uint64_t src_ofs, size_t len, char *dst) { - upb_stringsrc *src = _src; +void upb_stringsrc_read(const void *_src, uint64_t src_ofs, + size_t len, char *dst) { + const upb_stringsrc *src = _src; memcpy(dst, src->str + src_ofs, len); } diff --git a/upb/bytestream.h b/upb/bytestream.h index 0a744f6..96d840c 100644 --- a/upb/bytestream.h +++ b/upb/bytestream.h @@ -36,7 +36,7 @@ extern "C" { // data around for later use, without requiring a copy out of the input // buffers. typedef size_t upb_bytesrc_fetch_func(void*, uint64_t, upb_status*); -typedef void upb_bytesrc_read_func(void*, uint64_t, size_t, char*); +typedef void upb_bytesrc_read_func(const void*, uint64_t, size_t, char*); typedef const char *upb_bytesrc_getptr_func(void*, uint64_t, size_t*); typedef void upb_bytesrc_refregion_func(void*, uint64_t, size_t); typedef void upb_bytesrc_ref_func(void*); @@ -74,8 +74,8 @@ INLINE size_t upb_bytesrc_fetch(upb_bytesrc *src, uint64_t ofs, upb_status *s) { // Copies "len" bytes of data from offset src_ofs to "dst", which must be at // least "len" bytes long. The caller must own a ref on the given region. -INLINE void upb_bytesrc_read(upb_bytesrc *src, uint64_t src_ofs, size_t len, - char *dst) { +INLINE void upb_bytesrc_read(const upb_bytesrc *src, uint64_t src_ofs, + size_t len, char *dst) { src->vtbl->read(src, src_ofs, len, dst); } @@ -149,9 +149,9 @@ typedef struct _upb_strref { // Copies the contents of the strref into a newly-allocated, NULL-terminated // string. -char *upb_strref_dup(struct _upb_strref *r); +char *upb_strref_dup(const struct _upb_strref *r); -INLINE void upb_strref_read(struct _upb_strref *r, char *buf) { +INLINE void upb_strref_read(const struct _upb_strref *r, char *buf) { if (r->ptr) { memcpy(buf, r->ptr, r->len); } else { diff --git a/upb/def.c b/upb/def.c index ee793a9..555d763 100644 --- a/upb/def.c +++ b/upb/def.c @@ -38,7 +38,7 @@ 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); -bool upb_def_ismutable(upb_def *def) { return def->symtab == NULL; } +bool upb_def_ismutable(const upb_def *def) { return def->symtab == NULL; } bool upb_def_setfqname(upb_def *def, const char *fqname) { assert(upb_def_ismutable(def)); @@ -58,10 +58,12 @@ static void upb_def_free(upb_def *def) { } } -upb_def *upb_def_dup(upb_def *def) { +upb_def *upb_def_dup(const upb_def *def) { switch (def->type) { - case UPB_DEF_MSG: return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef(def))); - case UPB_DEF_ENUM: return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef(def))); + case UPB_DEF_MSG: + return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef_const(def))); + case UPB_DEF_ENUM: + return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef_const(def))); default: assert(false); return NULL; } } @@ -70,7 +72,8 @@ upb_def *upb_def_dup(upb_def *def) { // def itself. If the refcount falls to zero, the def is deleted. Once the // def belongs to a symtab, the def is owned by the symtab and its refcount // determines whether the def owns a ref on the symtab or not. -void upb_def_ref(upb_def *def) { +void upb_def_ref(const upb_def *_def) { + upb_def *def = (upb_def*)_def; // Need to modify refcount. if (upb_atomic_ref(&def->refcount) && def->symtab) upb_symtab_ref(def->symtab); } @@ -83,7 +86,8 @@ static void upb_def_movetosymtab(upb_def *d, upb_symtab *s) { if (m) upb_inttable_compact(&m->itof); } -void upb_def_unref(upb_def *def) { +void upb_def_unref(const upb_def *_def) { + upb_def *def = (upb_def*)_def; // Need to modify refcount. if (!def) return; if (upb_atomic_unref(&def->refcount)) { if (def->symtab) { @@ -152,7 +156,7 @@ static void upb_enumdef_free(upb_enumdef *e) { free(e); } -upb_enumdef *upb_enumdef_dup(upb_enumdef *e) { +upb_enumdef *upb_enumdef_dup(const upb_enumdef *e) { upb_enumdef *new_e = upb_enumdef_new(); upb_enum_iter i; for(i = upb_enum_begin(e); !upb_enum_done(i); i = upb_enum_next(e, i)) { @@ -176,12 +180,12 @@ void upb_enumdef_setdefault(upb_enumdef *e, int32_t val) { e->defaultval = val; } -upb_enum_iter upb_enum_begin(upb_enumdef *e) { +upb_enum_iter upb_enum_begin(const upb_enumdef *e) { // We could iterate over either table here; the choice is arbitrary. return upb_inttable_begin(&e->iton); } -upb_enum_iter upb_enum_next(upb_enumdef *e, upb_enum_iter iter) { +upb_enum_iter upb_enum_next(const upb_enumdef *e, upb_enum_iter iter) { return upb_inttable_next(&e->iton, iter); } @@ -267,11 +271,11 @@ upb_fielddef *upb_fielddef_dup(upb_fielddef *f) { return f; } -bool upb_fielddef_ismutable(upb_fielddef *f) { +bool upb_fielddef_ismutable(const upb_fielddef *f) { return !f->msgdef || upb_def_ismutable(UPB_UPCAST(f->msgdef)); } -upb_def *upb_fielddef_subdef(upb_fielddef *f) { +upb_def *upb_fielddef_subdef(const upb_fielddef *f) { if (upb_hassubdef(f) && !upb_fielddef_ismutable(f)) return f->def; else @@ -403,7 +407,7 @@ static void upb_msgdef_free(upb_msgdef *m) { free(m); } -upb_msgdef *upb_msgdef_dup(upb_msgdef *m) { +upb_msgdef *upb_msgdef_dup(const upb_msgdef *m) { upb_msgdef *newm = upb_msgdef_new(); newm->size = m->size; newm->hasbit_bytes = m->hasbit_bytes; @@ -512,31 +516,24 @@ void upb_msgdef_layout(upb_msgdef *m) { free(sorted_fields); } -upb_msg_iter upb_msg_begin(upb_msgdef *m) { +upb_msg_iter upb_msg_begin(const upb_msgdef *m) { return upb_inttable_begin(&m->itof); } -upb_msg_iter upb_msg_next(upb_msgdef *m, upb_msg_iter iter) { +upb_msg_iter upb_msg_next(const upb_msgdef *m, upb_msg_iter iter) { return upb_inttable_next(&m->itof, iter); } /* upb_symtab *****************************************************************/ -struct _upb_symtab { - upb_atomic_t refcount; - upb_rwlock_t lock; // Protects all members except the refcount. - upb_strtable symtab; // The symbol table. - upb_deflist olddefs; -}; - typedef struct { upb_def *def; } upb_symtab_ent; // Given a symbol and the base symbol inside which it is defined, find the // symbol's definition in t. -static upb_symtab_ent *upb_resolve(upb_strtable *t, +static upb_symtab_ent *upb_resolve(const upb_strtable *t, const char *base, const char *sym) { if(strlen(sym) == 0) return NULL; if(sym[0] == UPB_SYMBOL_SEPARATOR) { @@ -575,9 +572,13 @@ static void upb_symtab_free(upb_symtab *s) { free(s); } -void upb_symtab_ref(upb_symtab *s) { upb_atomic_ref(&s->refcount); } +void upb_symtab_ref(const upb_symtab *_s) { + upb_symtab *s = (upb_symtab*)_s; + upb_atomic_ref(&s->refcount); +} -void upb_symtab_unref(upb_symtab *s) { +void upb_symtab_unref(const upb_symtab *_s) { + upb_symtab *s = (upb_symtab*)_s; if(s && upb_atomic_unref(&s->refcount)) { upb_symtab_free(s); } @@ -592,12 +593,13 @@ upb_symtab *upb_symtab_new() { return s; } -upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type) { +const upb_def **upb_symtab_getdefs(const upb_symtab *s, int *count, + upb_deftype_t type) { upb_rwlock_rdlock(&s->lock); int total = upb_strtable_count(&s->symtab); // We may only use part of this, depending on how many symbols are of the // correct type. - upb_def **defs = malloc(sizeof(*defs) * total); + const upb_def **defs = malloc(sizeof(*defs) * total); upb_strtable_iter iter; upb_strtable_begin(&iter, &s->symtab); int i = 0; @@ -614,7 +616,7 @@ upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type) { return defs; } -upb_def *upb_symtab_lookup(upb_symtab *s, const char *sym) { +const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) { upb_rwlock_rdlock(&s->lock); upb_symtab_ent *e = upb_strtable_lookup(&s->symtab, sym); upb_def *ret = NULL; @@ -626,7 +628,20 @@ upb_def *upb_symtab_lookup(upb_symtab *s, const char *sym) { return ret; } -upb_def *upb_symtab_resolve(upb_symtab *s, const char *base, const char *sym) { +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { + upb_rwlock_rdlock(&s->lock); + upb_symtab_ent *e = upb_strtable_lookup(&s->symtab, sym); + upb_msgdef *ret = NULL; + if(e && e->def->type == UPB_DEF_MSG) { + ret = upb_downcast_msgdef(e->def); + upb_def_ref(UPB_UPCAST(ret)); + } + upb_rwlock_unlock(&s->lock); + return ret; +} + +const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, + const char *sym) { upb_rwlock_rdlock(&s->lock); upb_symtab_ent *e = upb_resolve(&s->symtab, base, sym); upb_def *ret = NULL; diff --git a/upb/def.h b/upb/def.h index 4dc9c16..361753c 100644 --- a/upb/def.h +++ b/upb/def.h @@ -11,13 +11,36 @@ * - upb_enumdef: describes an enum. * (TODO: definitions of services). * - * 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. + * Defs go through two distinct phases of life: + * + * 1. MUTABLE: when first created, the properties of the def can be set freely + * (for example a message's name, its list of fields, the name/number of + * fields, etc). During this phase the def is *not* thread-safe, and may + * not be used for any purpose except to set its properties (it can't be + * used to parse anything, create any messages in memory, etc). + * + * 2. IMMUTABLE: after being added to a symtab (which links the defs together) + * the defs become thread-safe and immutable. Programs may only access defs + * through a CONST POINTER during this stage -- upb_symtab will help you out + * with this requirement by only vending const pointers, but you need to + * make sure not to use any non-const pointers you still have sitting + * around. In practice this means that you may not call any setters on the + * defs (or functions that themselves call the setters). If you want to + * modify an existing immutable def, copy it with upb_*_dup(), modify the + * copy, and add the modified def to the symtab (replacing the existing + * def). + * + * You can test for which stage of life a def is in by calling + * upb_def_ismutable(). This is particularly useful for dynamic language + * bindings, which must properly guarantee that the dynamic language cannot + * break the rules laid out above. + * + * It would be possible to make the defs thread-safe during stage 1 by using + * mutexes internally and changing any methods returning pointers to return + * copies instead. This could be important if we are integrating with a VM or + * interpreter that does not naturally serialize access to wrapped objects (for + * example, in the case of Python this is not necessary because of the GIL). */ #ifndef UPB_DEF_H_ @@ -58,13 +81,13 @@ typedef struct { // until the def is in a symtab. While a def is in a symtab, everything // reachable from that def (the symtab and all defs in the symtab) are // guaranteed to be alive. -void upb_def_ref(upb_def *def); -void upb_def_unref(upb_def *def); -upb_def *upb_def_dup(upb_def *def); +void upb_def_ref(const upb_def *def); +void upb_def_unref(const upb_def *def); +upb_def *upb_def_dup(const 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_ismutable(const upb_def *def); +INLINE const char *upb_def_fqname(const 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) @@ -103,7 +126,7 @@ 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); +bool upb_fielddef_ismutable(const upb_fielddef *f); // Read accessors. May be called any time. INLINE uint8_t upb_fielddef_type(upb_fielddef *f) { return f->type; } @@ -127,7 +150,7 @@ INLINE const char *upb_fielddef_typename(upb_fielddef *f) { // submessage, group, and enum fields (ie. when upb_hassubdef(f) is true). // Since defs are not linked together until they are in a symtab, this // will return NULL until the msgdef is in a symtab. -upb_def *upb_fielddef_subdef(upb_fielddef *f); +upb_def *upb_fielddef_subdef(const 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 @@ -155,12 +178,12 @@ INLINE bool upb_isstringtype(upb_fieldtype_t type) { INLINE bool upb_isprimitivetype(upb_fieldtype_t type) { return !upb_issubmsgtype(type) && !upb_isstringtype(type); } -INLINE bool upb_issubmsg(upb_fielddef *f) { return upb_issubmsgtype(f->type); } -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); } +INLINE bool upb_issubmsg(const upb_fielddef *f) { return upb_issubmsgtype(f->type); } +INLINE bool upb_isstring(const upb_fielddef *f) { return upb_isstringtype(f->type); } +INLINE bool upb_isseq(const 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_hassubdef(upb_fielddef *f) { +INLINE bool upb_hassubdef(const upb_fielddef *f) { return upb_issubmsg(f) || f->type == UPB_TYPE(ENUM); } @@ -192,22 +215,22 @@ typedef struct { } upb_ntof_ent; upb_msgdef *upb_msgdef_new(void); -INLINE void upb_msgdef_unref(upb_msgdef *md) { upb_def_unref(UPB_UPCAST(md)); } -INLINE void upb_msgdef_ref(upb_msgdef *md) { upb_def_ref(UPB_UPCAST(md)); } +INLINE void upb_msgdef_unref(const upb_msgdef *md) { upb_def_unref(UPB_UPCAST(md)); } +INLINE void upb_msgdef_ref(const upb_msgdef *md) { upb_def_ref(UPB_UPCAST(md)); } // Returns a new msgdef that is a copy of the given msgdef (and a copy of all // the fields) but with any references to submessages broken and replaced with // just the name of the submessage. This can be put back into another symtab // and the names will be re-resolved in the new context. -upb_msgdef *upb_msgdef_dup(upb_msgdef *m); +upb_msgdef *upb_msgdef_dup(const upb_msgdef *m); // Read accessors. May be called at any time. -INLINE uint16_t upb_msgdef_size(upb_msgdef *m) { return m->size; } -INLINE uint8_t upb_msgdef_hasbit_bytes(upb_msgdef *m) { +INLINE uint16_t upb_msgdef_size(const upb_msgdef *m) { return m->size; } +INLINE uint8_t upb_msgdef_hasbit_bytes(const upb_msgdef *m) { return m->hasbit_bytes; } -INLINE uint32_t upb_msgdef_extstart(upb_msgdef *m) { return m->extstart; } -INLINE uint32_t upb_msgdef_extend(upb_msgdef *m) { return m->extend; } +INLINE uint32_t upb_msgdef_extstart(const upb_msgdef *m) { return m->extstart; } +INLINE uint32_t upb_msgdef_extend(const 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); @@ -248,7 +271,7 @@ INLINE upb_fielddef *upb_msgdef_ntof(upb_msgdef *m, const char *name) { return e ? e->f : NULL; } -INLINE int upb_msgdef_numfields(upb_msgdef *m) { +INLINE int upb_msgdef_numfields(const upb_msgdef *m) { return upb_strtable_count(&m->ntof); } @@ -262,8 +285,8 @@ INLINE int upb_msgdef_numfields(upb_msgdef *m) { // } typedef upb_inttable_iter upb_msg_iter; -upb_msg_iter upb_msg_begin(upb_msgdef *m); -upb_msg_iter upb_msg_next(upb_msgdef *m, upb_msg_iter iter); +upb_msg_iter upb_msg_begin(const upb_msgdef *m); +upb_msg_iter upb_msg_next(const upb_msgdef *m, upb_msg_iter iter); INLINE bool upb_msg_done(upb_msg_iter iter) { return upb_inttable_done(iter); } // Iterator accessor. @@ -292,9 +315,9 @@ typedef struct { } upb_iton_ent; upb_enumdef *upb_enumdef_new(void); -INLINE void upb_enumdef_ref(upb_enumdef *e) { upb_def_ref(UPB_UPCAST(e)); } -INLINE void upb_enumdef_unref(upb_enumdef *e) { upb_def_unref(UPB_UPCAST(e)); } -upb_enumdef *upb_enumdef_dup(upb_enumdef *e); +INLINE void upb_enumdef_ref(const upb_enumdef *e) { upb_def_ref(UPB_UPCAST(e)); } +INLINE void upb_enumdef_unref(const upb_enumdef *e) { upb_def_unref(UPB_UPCAST(e)); } +upb_enumdef *upb_enumdef_dup(const upb_enumdef *e); INLINE int32_t upb_enumdef_default(upb_enumdef *e) { return e->defaultval; } @@ -320,8 +343,8 @@ const char *upb_enumdef_iton(upb_enumdef *e, int32_t num); // } typedef upb_inttable_iter upb_enum_iter; -upb_enum_iter upb_enum_begin(upb_enumdef *e); -upb_enum_iter upb_enum_next(upb_enumdef *e, upb_enum_iter iter); +upb_enum_iter upb_enum_begin(const upb_enumdef *e); +upb_enum_iter upb_enum_next(const upb_enumdef *e, upb_enum_iter iter); INLINE bool upb_enum_done(upb_enum_iter iter) { return upb_inttable_done(iter); } // Iterator accessors. @@ -334,15 +357,36 @@ INLINE int32_t upb_enum_iter_number(upb_enum_iter iter) { } +/* upb_deflist ****************************************************************/ + +// upb_deflist is an internal-only dynamic array for storing a growing list of +// upb_defs. +typedef struct { + upb_def **defs; + uint32_t len; + uint32_t size; +} upb_deflist; + +void upb_deflist_init(upb_deflist *l); +void upb_deflist_uninit(upb_deflist *l); +void upb_deflist_push(upb_deflist *l, upb_def *d); + + /* upb_symtab *****************************************************************/ // A symtab (symbol table) is where upb_defs live. It is empty when first // constructed. Clients add definitions to the symtab (or replace existing // definitions) by calling upb_symtab_add(). +struct _upb_symtab { + upb_atomic_t refcount; + upb_rwlock_t lock; // Protects all members except the refcount. + upb_strtable symtab; // The symbol table. + upb_deflist olddefs; +}; upb_symtab *upb_symtab_new(void); -void upb_symtab_ref(upb_symtab *s); -void upb_symtab_unref(upb_symtab *s); +void upb_symtab_ref(const upb_symtab *s); +void upb_symtab_unref(const upb_symtab *s); // Resolves the given symbol using the rules described in descriptor.proto, // namely: @@ -354,20 +398,19 @@ void upb_symtab_unref(upb_symtab *s); // // If a def is found, the caller owns one ref on the returned def. Otherwise // returns NULL. -// TODO: make return const -upb_def *upb_symtab_resolve(upb_symtab *s, const char *base, const char *sym); +const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, + const char *sym); // Find an entry in the symbol table with this exact name. If a def is found, // the caller owns one ref on the returned def. Otherwise returns NULL. -// TODO: make return const -upb_def *upb_symtab_lookup(upb_symtab *s, const char *sym); +const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym); +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); // Gets an array of pointers to all currently active defs in this symtab. The // caller owns the returned array (which is of length *count) as well as a ref // to each symbol inside. If type is UPB_DEF_ANY then defs of all types are // returned, otherwise only defs of the required type are returned. -// TODO: make return const -upb_def **upb_symtab_getdefs(upb_symtab *s, int *n, upb_deftype_t type); +const upb_def **upb_symtab_getdefs(const 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. @@ -385,46 +428,31 @@ void upb_symtab_gc(upb_symtab *s); /* upb_def casts **************************************************************/ // Dynamic casts, for determining if a def is of a particular type at runtime. -#define UPB_DYNAMIC_CAST_DEF(lower, upper) \ +// Downcasts, for when some wants to assert that a def is of a particular type. +// These are only checked if we are building debug. +#define UPB_DEF_CASTS(lower, upper) \ struct _upb_ ## lower; /* Forward-declare. */ \ INLINE struct _upb_ ## lower *upb_dyncast_ ## lower(upb_def *def) { \ if(def->type != UPB_DEF_ ## upper) return NULL; \ return (struct _upb_ ## lower*)def; \ - } -UPB_DYNAMIC_CAST_DEF(msgdef, MSG); -UPB_DYNAMIC_CAST_DEF(enumdef, ENUM); -UPB_DYNAMIC_CAST_DEF(svcdef, SERVICE); -UPB_DYNAMIC_CAST_DEF(unresolveddef, UNRESOLVED); -#undef UPB_DYNAMIC_CAST_DEF - -// Downcasts, for when some wants to assert that a def is of a particular type. -// These are only checked if we are building debug. -#define UPB_DOWNCAST_DEF(lower, upper) \ - struct _upb_ ## lower; /* Forward-declare. */ \ + } \ + INLINE const struct _upb_ ## lower *upb_dyncast_ ## lower ## _const(const upb_def *def) { \ + if(def->type != UPB_DEF_ ## upper) return NULL; \ + return (const struct _upb_ ## lower*)def; \ + } \ INLINE struct _upb_ ## lower *upb_downcast_ ## lower(upb_def *def) { \ assert(def->type == UPB_DEF_ ## upper); \ return (struct _upb_ ## lower*)def; \ + } \ + INLINE const struct _upb_ ## lower *upb_downcast_ ## lower ## _const(const upb_def *def) { \ + assert(def->type == UPB_DEF_ ## upper); \ + return (const struct _upb_ ## lower*)def; \ } -UPB_DOWNCAST_DEF(msgdef, MSG); -UPB_DOWNCAST_DEF(enumdef, ENUM); -UPB_DOWNCAST_DEF(svcdef, SERVICE); -UPB_DOWNCAST_DEF(unresolveddef, UNRESOLVED); -#undef UPB_DOWNCAST_DEF - - -/* upb_deflist ****************************************************************/ - -// upb_deflist is an internal-only dynamic array for storing a growing list of -// upb_defs. -typedef struct { - upb_def **defs; - uint32_t len; - uint32_t size; -} upb_deflist; - -void upb_deflist_init(upb_deflist *l); -void upb_deflist_uninit(upb_deflist *l); -void upb_deflist_push(upb_deflist *l, upb_def *d); +UPB_DEF_CASTS(msgdef, MSG); +UPB_DEF_CASTS(enumdef, ENUM); +UPB_DEF_CASTS(svcdef, SERVICE); +UPB_DEF_CASTS(unresolveddef, UNRESOLVED); +#undef UPB_DEF_CASTS #ifdef __cplusplus } /* extern "C" */ diff --git a/upb/handlers.c b/upb/handlers.c index b2d9f94..0af09ef 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -107,7 +107,7 @@ typedef struct { upb_mhandlers *mh; } upb_mtab_ent; -static upb_mhandlers *upb_regmsg_dfs(upb_handlers *h, upb_msgdef *m, +static upb_mhandlers *upb_regmsg_dfs(upb_handlers *h, const upb_msgdef *m, upb_onmsgreg *msgreg_cb, upb_onfieldreg *fieldreg_cb, void *closure, upb_strtable *mtab) { @@ -139,7 +139,7 @@ static upb_mhandlers *upb_regmsg_dfs(upb_handlers *h, upb_msgdef *m, return mh; } -upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m, +upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, const upb_msgdef *m, upb_onmsgreg *msgreg_cb, upb_onfieldreg *fieldreg_cb, void *closure) { diff --git a/upb/handlers.h b/upb/handlers.h index a7c1d9d..c127741 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -166,7 +166,7 @@ void upb_fhandlers_unref(upb_fhandlers *m); // upb_fhandlers accessors #define UPB_FHANDLERS_ACCESSORS(name, type) \ INLINE void upb_fhandlers_set ## name(upb_fhandlers *f, type v){f->name = v;} \ - INLINE type upb_fhandlers_get ## name(upb_fhandlers *f) { return f->name; } + INLINE type upb_fhandlers_get ## name(const upb_fhandlers *f) { return f->name; } UPB_FHANDLERS_ACCESSORS(fval, upb_value) UPB_FHANDLERS_ACCESSORS(value, upb_value_handler*) UPB_FHANDLERS_ACCESSORS(startsubmsg, upb_startfield_handler*) @@ -257,9 +257,9 @@ upb_mhandlers *upb_handlers_getmhandlers(upb_handlers *h, int index); // with "fieldreg_cb" // // See upb_handlers_reghandlerset() below for an example. -typedef void upb_onmsgreg(void *closure, upb_mhandlers *mh, upb_msgdef *m); -typedef void upb_onfieldreg(void *closure, upb_fhandlers *mh, upb_fielddef *m); -upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m, +typedef void upb_onmsgreg(void *closure, upb_mhandlers *mh, const upb_msgdef *m); +typedef void upb_onfieldreg(void *closure, upb_fhandlers *mh, const upb_fielddef *m); +upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, const upb_msgdef *m, upb_onmsgreg *msgreg_cb, upb_onfieldreg *fieldreg_cb, void *closure); @@ -278,13 +278,13 @@ typedef struct { upb_endfield_handler *endseq; } upb_handlerset; -INLINE void upb_onmreg_hset(void *c, upb_mhandlers *mh, upb_msgdef *m) { +INLINE void upb_onmreg_hset(void *c, upb_mhandlers *mh, const upb_msgdef *m) { (void)m; upb_handlerset *hs = (upb_handlerset*)c; if (hs->startmsg) upb_mhandlers_setstartmsg(mh, hs->startmsg); if (hs->endmsg) upb_mhandlers_setendmsg(mh, hs->endmsg); } -INLINE void upb_onfreg_hset(void *c, upb_fhandlers *fh, upb_fielddef *f) { +INLINE void upb_onfreg_hset(void *c, upb_fhandlers *fh, const upb_fielddef *f) { upb_handlerset *hs = (upb_handlerset*)c; if (hs->value) upb_fhandlers_setvalue(fh, hs->value); if (hs->startsubmsg) upb_fhandlers_setstartsubmsg(fh, hs->startsubmsg); @@ -295,7 +295,7 @@ INLINE void upb_onfreg_hset(void *c, upb_fhandlers *fh, upb_fielddef *f) { upb_value_setfielddef(&val, f); upb_fhandlers_setfval(fh, val); } -INLINE upb_mhandlers *upb_handlers_reghandlerset(upb_handlers *h, upb_msgdef *m, +INLINE upb_mhandlers *upb_handlers_reghandlerset(upb_handlers *h, const upb_msgdef *m, upb_handlerset *hs) { return upb_handlers_regmsgdef(h, m, &upb_onmreg_hset, &upb_onfreg_hset, hs); } diff --git a/upb/msg.c b/upb/msg.c index 65c358e..ece22ab 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -10,7 +10,7 @@ #include "upb/upb.h" #include "upb/msg.h" -void upb_msg_clear(void *msg, upb_msgdef *md) { +void upb_msg_clear(void *msg, const upb_msgdef *md) { assert(msg != NULL); memset(msg, 0, md->hasbit_bytes); // TODO: set primitive fields to defaults? @@ -85,14 +85,14 @@ void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h, void upb_stdmsg_sethas(void *_m, upb_value fval) { assert(_m != NULL); char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); + const 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); + const upb_fielddef *f = upb_value_getfielddef(fval); return f->hasbit < 0 || (m[f->hasbit / 8] & (1 << (f->hasbit % 8))); } @@ -100,7 +100,7 @@ bool upb_stdmsg_has(void *_m, upb_value fval) { 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); \ + const upb_fielddef *f = upb_value_getfielddef(fval); \ uint8_t *m = _m; \ /* Hasbit is set automatically by the handlers. */ \ *(ctype*)&m[f->offset] = upb_value_get ## type(val); \ @@ -119,7 +119,7 @@ bool upb_stdmsg_has(void *_m, upb_value fval) { 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); \ + const upb_fielddef *f = upb_value_getfielddef(fval); \ upb_value ret; \ upb_value_set ## type(&ret, *(ctype*)&m[f->offset]); \ return ret; \ @@ -151,7 +151,7 @@ static void _upb_stdmsg_setstr(void *_dst, upb_value src) { *dstp = dst; } dst->len = 0; - upb_strref *ref = upb_value_getstrref(src); + const upb_strref *ref = upb_value_getstrref(src); if (ref->len > dst->size) { dst->size = ref->len; dst->ptr = realloc(dst->ptr, dst->size); @@ -163,7 +163,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); + const upb_fielddef *f = upb_value_getfielddef(fval); // Hasbit automatically set by the handlers. _upb_stdmsg_setstr(&m[f->offset], val); return UPB_CONTINUE; @@ -186,7 +186,7 @@ upb_value upb_stdmsg_seqgetstr(void *i) { return upb_stdmsg_seqgetptr(i); } -void *upb_stdmsg_new(upb_msgdef *md) { +void *upb_stdmsg_new(const upb_msgdef *md) { void *m = malloc(md->size); memset(m, 0, md->size); upb_msg_clear(m, md); @@ -211,7 +211,7 @@ void upb_stdseq_free(void *s, upb_fielddef *f) { free(a); } -void upb_stdmsg_free(void *m, upb_msgdef *md) { +void upb_stdmsg_free(void *m, const upb_msgdef *md) { if (m == NULL) return; upb_msg_iter i; for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) { @@ -234,7 +234,7 @@ void upb_stdmsg_free(void *m, upb_msgdef *md) { upb_sflow_t upb_stdmsg_startseq(void *_m, upb_value fval) { char *m = _m; - upb_fielddef *f = upb_value_getfielddef(fval); + const upb_fielddef *f = upb_value_getfielddef(fval); upb_stdarray **arr = (void*)&m[f->offset]; if (!upb_stdmsg_has(_m, fval)) { if (!*arr) { @@ -248,7 +248,7 @@ upb_sflow_t upb_stdmsg_startseq(void *_m, upb_value fval) { return UPB_CONTINUE_WITH(*arr); } -void upb_stdmsg_recycle(void **m, upb_msgdef *md) { +void upb_stdmsg_recycle(void **m, const upb_msgdef *md) { if (*m) upb_msg_clear(*m, md); else @@ -258,7 +258,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); + const upb_fielddef *f = upb_value_getfielddef(fval); void **subm = (void*)&m[f->offset]; if (!upb_stdmsg_has(m, fval)) { upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def)); @@ -269,7 +269,7 @@ upb_sflow_t upb_stdmsg_startsubmsg(void *_m, upb_value fval) { upb_sflow_t upb_stdmsg_startsubmsg_r(void *a, upb_value fval) { assert(a != NULL); - upb_fielddef *f = upb_value_getfielddef(fval); + const upb_fielddef *f = upb_value_getfielddef(fval); void **subm = upb_stdarray_append((upb_stdarray*)a, sizeof(void*)); upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def)); return UPB_CONTINUE_WITH(*subm); @@ -329,7 +329,8 @@ upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f) { return NULL; } -static void upb_accessors_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) { +static void upb_accessors_onfreg(void *c, upb_fhandlers *fh, + const upb_fielddef *f) { (void)c; if (f->accessor) { upb_fhandlers_setfval(fh, f->fval); @@ -345,6 +346,6 @@ static void upb_accessors_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) { } } -upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, upb_msgdef *m) { +upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, const upb_msgdef *m) { return upb_handlers_regmsgdef(h, m, NULL, &upb_accessors_onfreg, NULL); } diff --git a/upb/msg.h b/upb/msg.h index 7ad97d0..fa53056 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -69,7 +69,7 @@ typedef struct _upb_accessor_vtbl { } upb_accessor_vtbl; // Registers handlers for writing into a message of the given type. -upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, upb_msgdef *m); +upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, const upb_msgdef *m); // Returns an stdmsg accessor for the given fielddef. upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f); @@ -85,9 +85,9 @@ upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f); // Clears all hasbits. // TODO: Add a separate function for setting primitive values back to their // defaults (but not strings, submessages, or arrays). -void upb_msg_clear(void *msg, upb_msgdef *md); +void upb_msg_clear(void *msg, const upb_msgdef *md); -INLINE void upb_msg_clearbit(void *msg, upb_fielddef *f) { +INLINE void upb_msg_clearbit(void *msg, const upb_fielddef *f) { ((char*)msg)[f->hasbit / 8] &= ~(1 << (f->hasbit % 8)); } @@ -97,37 +97,37 @@ INLINE void upb_msg_clearbit(void *msg, upb_fielddef *f) { // or arrays. Also this could be desired to provide proto2 operations on // generated messages. -INLINE bool upb_msg_has(void *m, upb_fielddef *f) { +INLINE bool upb_msg_has(void *m, const upb_fielddef *f) { return f->accessor && f->accessor->has(m, f->fval); } // May only be called for fields that have accessors. -INLINE upb_value upb_msg_get(void *m, upb_fielddef *f) { +INLINE upb_value upb_msg_get(void *m, const upb_fielddef *f) { assert(f->accessor && !upb_isseq(f)); return f->accessor->get(m, f->fval); } // May only be called for fields that have accessors. -INLINE upb_value upb_msg_getseq(void *m, upb_fielddef *f) { +INLINE upb_value upb_msg_getseq(void *m, const upb_fielddef *f) { assert(f->accessor && upb_isseq(f)); return f->accessor->getseq(m, f->fval); } -INLINE void upb_msg_set(void *m, upb_fielddef *f, upb_value val) { +INLINE void upb_msg_set(void *m, const 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) { +INLINE void *upb_seq_begin(void *s, const upb_fielddef *f) { assert(f->accessor); return f->accessor->seqbegin(s); } -INLINE void *upb_seq_next(void *s, void *iter, upb_fielddef *f) { +INLINE void *upb_seq_next(void *s, void *iter, const upb_fielddef *f) { assert(f->accessor); assert(!upb_seq_done(iter)); return f->accessor->seqnext(s, iter); } -INLINE upb_value upb_seq_get(void *iter, upb_fielddef *f) { +INLINE upb_value upb_seq_get(void *iter, const upb_fielddef *f) { assert(f->accessor); assert(!upb_seq_done(iter)); return f->accessor->seqget(iter); @@ -175,10 +175,10 @@ void upb_msgvisitor_visit(upb_msgvisitor *v, upb_status *status); /* Standard writers. **********************************************************/ // Allocates a new stdmsg. -void *upb_stdmsg_new(upb_msgdef *md); +void *upb_stdmsg_new(const upb_msgdef *md); // Recursively frees any strings or submessages that the message refers to. -void upb_stdmsg_free(void *m, upb_msgdef *md); +void upb_stdmsg_free(void *m, const upb_msgdef *md); void upb_stdmsg_sethas(void *_m, upb_value fval); diff --git a/upb/pb/decoder_x86.dasc b/upb/pb/decoder_x86.dasc index fe15174..0657af6 100644 --- a/upb/pb/decoder_x86.dasc +++ b/upb/pb/decoder_x86.dasc @@ -413,7 +413,7 @@ static void upb_decoder_jit_doappend(upb_decoder *d, uint8_t size, #endif static void upb_decoder_jit_callcb(upb_decoder *d, upb_fhandlers *f) { - upb_fielddef *fd = upb_value_getfielddef(f->fval); + const upb_fielddef *fd = upb_value_getfielddef(f->fval); // Call callbacks. if (upb_issubmsgtype(f->type)) { // Load closure and fval into arg registers. @@ -439,7 +439,7 @@ static void upb_decoder_jit_callcb(upb_decoder *d, upb_fhandlers *f) { } | pushframe f, rdx, esi, false - upb_mhandlers *sub_m = upb_fhandlers_getsubmsg(f); + const upb_mhandlers *sub_m = upb_fhandlers_getsubmsg(f); if (sub_m->jit_parent_field_done_pclabel != UPB_MULTIPLE) { | jmp =>sub_m->jit_startmsg_pclabel; } else { diff --git a/upb/pb/glue.c b/upb/pb/glue.c index 6981aa2..b364a6d 100644 --- a/upb/pb/glue.c +++ b/upb/pb/glue.c @@ -12,7 +12,7 @@ #include "upb/pb/glue.h" #include "upb/pb/textprinter.h" -void upb_strtomsg(const char *str, size_t len, void *msg, upb_msgdef *md, +void upb_strtomsg(const char *str, size_t len, void *msg, const upb_msgdef *md, upb_status *status) { upb_stringsrc strsrc; upb_stringsrc_init(&strsrc); @@ -56,8 +56,8 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md, #endif // TODO: read->load. -upb_def **upb_load_descriptor(const char *str, size_t len, int *n, - upb_status *status) { +upb_def **upb_load_defs_from_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); @@ -98,13 +98,15 @@ upb_def **upb_load_descriptor(const char *str, size_t len, int *n, return defscopy; } -void upb_read_descriptor(upb_symtab *s, const char *str, size_t len, - upb_status *status) { +bool upb_load_descriptor_into_symtab(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); + upb_def **defs = upb_load_defs_from_descriptor(str, len, &n, status); + if (!defs) return false; + bool success = upb_symtab_add(s, defs, n, status); for(int i = 0; i < n; i++) upb_def_unref(defs[i]); free(defs); + return success; } char *upb_readfile(const char *filename, size_t *len) { @@ -125,14 +127,15 @@ error: return NULL; } -void upb_read_descriptorfile(upb_symtab *symtab, const char *fname, - upb_status *status) { +bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, + upb_status *status) { size_t len; char *data = upb_readfile(fname, &len); if (!data) { - upb_status_seterrf(status, "Couldn't read file: %s", fname); - return; + if (status) upb_status_seterrf(status, "Couldn't read file: %s", fname); + return false; } - upb_read_descriptor(symtab, data, len, status); + bool success = upb_load_descriptor_into_symtab(symtab, data, len, status); free(data); + return success; } diff --git a/upb/pb/glue.h b/upb/pb/glue.h index a2a478c..7aa4a5f 100644 --- a/upb/pb/glue.h +++ b/upb/pb/glue.h @@ -42,20 +42,29 @@ struct _upb_symtab; // Decodes the given string, which must be in protobuf binary format, to the // given upb_msg with msgdef "md", storing the status of the operation in "s". void upb_strtomsg(const char *str, size_t len, void *msg, - struct _upb_msgdef *md, upb_status *s); + const struct _upb_msgdef *md, upb_status *s); //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); +// Loads all defs from the given protobuf binary descriptor, setting default +// accessors and a default layout on all messages. The caller owns the +// returned array of defs, which will be of length *n. On error NULL is +// returned and status is set (if non-NULL). +upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n, + upb_status *status); -void upb_read_descriptorfile(struct _upb_symtab *symtab, const char *fname, - upb_status *status); +// Like the previous but also adds the loaded defs to the given symtab. +bool upb_load_descriptor_into_symtab(struct _upb_symtab *symtab, const char *str, + size_t len, upb_status *status); +// Like the previous but also reads the descriptor from the given filename. +bool upb_load_descriptor_file_into_symtab(struct _upb_symtab *symtab, + const char *fname, upb_status *status); + +// Reads the given filename into a character string, returning NULL if there +// was an error. char *upb_readfile(const char *filename, size_t *len); #ifdef __cplusplus diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index 37f5699..434a482 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -35,7 +35,7 @@ err: return -1; } -static int upb_textprinter_putescaped(upb_textprinter *p, upb_strref *strref, +static int upb_textprinter_putescaped(upb_textprinter *p, const upb_strref *strref, bool preserve_utf8) { // Based on CEscapeInternal() from Google's protobuf release. // TODO; we could read directly from a bytesrc's buffer instead. @@ -90,7 +90,7 @@ err: static upb_flow_t upb_textprinter_put ## member(void *_p, upb_value fval, \ upb_value val) { \ upb_textprinter *p = _p; \ - upb_fielddef *f = upb_value_getfielddef(fval); \ + const upb_fielddef *f = upb_value_getfielddef(fval); \ uint64_t start_ofs = upb_bytesink_getoffset(p->sink); \ CHECK(upb_textprinter_indent(p)); \ CHECK(upb_bytesink_writestr(p->sink, f->name)); \ @@ -120,7 +120,7 @@ static upb_flow_t upb_textprinter_putenum(void *_p, upb_value fval, upb_textprinter *p = _p; uint64_t start_ofs = upb_bytesink_getoffset(p->sink); - upb_fielddef *f = upb_value_getfielddef(fval); + const upb_fielddef *f = upb_value_getfielddef(fval); upb_enumdef *enum_def = upb_downcast_enumdef(f->def); const char *label = upb_enumdef_iton(enum_def, upb_value_getint32(val)); if (label) { @@ -138,7 +138,7 @@ static upb_flow_t upb_textprinter_putstr(void *_p, upb_value fval, upb_value val) { upb_textprinter *p = _p; uint64_t start_ofs = upb_bytesink_getoffset(p->sink); - upb_fielddef *f = upb_value_getfielddef(fval); + const upb_fielddef *f = upb_value_getfielddef(fval); CHECK(upb_bytesink_putc(p->sink, '"')); CHECK(upb_textprinter_putescaped(p, upb_value_getstrref(val), f->type == UPB_TYPE(STRING))); @@ -152,7 +152,7 @@ err: static upb_sflow_t upb_textprinter_startsubmsg(void *_p, upb_value fval) { upb_textprinter *p = _p; uint64_t start_ofs = upb_bytesink_getoffset(p->sink); - upb_fielddef *f = upb_value_getfielddef(fval); + const upb_fielddef *f = upb_value_getfielddef(fval); CHECK(upb_textprinter_indent(p)); CHECK(upb_bytesink_printf(p->sink, "%s {", f->name)); if (!p->single_line) @@ -192,7 +192,7 @@ void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink, p->indent_depth = 0; } -static void upb_textprinter_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) { +static void upb_textprinter_onfreg(void *c, upb_fhandlers *fh, const upb_fielddef *f) { (void)c; upb_fhandlers_setstartsubmsg(fh, &upb_textprinter_startsubmsg); upb_fhandlers_setendsubmsg(fh, &upb_textprinter_endsubmsg); @@ -207,7 +207,7 @@ static void upb_textprinter_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) upb_fhandlers_setfval(fh, fval); } -upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, upb_msgdef *m) { +upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, const upb_msgdef *m) { return upb_handlers_regmsgdef( h, m, NULL, &upb_textprinter_onfreg, NULL); } diff --git a/upb/pb/textprinter.h b/upb/pb/textprinter.h index 9455208..25f364e 100644 --- a/upb/pb/textprinter.h +++ b/upb/pb/textprinter.h @@ -22,7 +22,7 @@ upb_textprinter *upb_textprinter_new(); void upb_textprinter_free(upb_textprinter *p); void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink, bool single_line); -upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, upb_msgdef *m); +upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, const upb_msgdef *m); #ifdef __cplusplus } /* extern "C" */ diff --git a/upb/table.c b/upb/table.c index 71aca16..f0d8d3e 100644 --- a/upb/table.c +++ b/upb/table.c @@ -25,9 +25,9 @@ static uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed); /* Base table (shared code) ***************************************************/ -static uint32_t upb_table_size(upb_table *t) { return 1 << t->size_lg2; } -static size_t upb_table_entrysize(upb_table *t) { return t->entry_size; } -static size_t upb_table_valuesize(upb_table *t) { return t->value_size; } +static uint32_t upb_table_size(const upb_table *t) { return 1 << t->size_lg2; } +static size_t upb_table_entrysize(const upb_table *t) { return t->entry_size; } +static size_t upb_table_valuesize(const upb_table *t) { return t->value_size; } void upb_table_init(upb_table *t, uint32_t size, uint16_t entry_size) { t->count = 0; @@ -43,12 +43,12 @@ void upb_table_free(upb_table *t) { free(t->entries); } /* upb_inttable ***************************************************************/ -static upb_inttable_entry *intent(upb_inttable *t, int32_t i) { +static upb_inttable_entry *intent(const upb_inttable *t, int32_t i) { //printf("looking up int entry %d, size of entry: %d\n", i, t->t.entry_size); return UPB_INDEX(t->t.entries, i, t->t.entry_size); } -static uint32_t upb_inttable_hashtablesize(upb_inttable *t) { +static uint32_t upb_inttable_hashtablesize(const upb_inttable *t) { return upb_table_size(&t->t); } @@ -219,12 +219,13 @@ void upb_inttable_compact(upb_inttable *t) { *t = new_table; } -upb_inttable_iter upb_inttable_begin(upb_inttable *t) { +upb_inttable_iter upb_inttable_begin(const upb_inttable *t) { upb_inttable_iter iter = {-1, NULL, true}; // -1 will overflow to 0 on the first iteration. return upb_inttable_next(t, iter); } -upb_inttable_iter upb_inttable_next(upb_inttable *t, upb_inttable_iter iter) { +upb_inttable_iter upb_inttable_next(const upb_inttable *t, + upb_inttable_iter iter) { const size_t hdrsize = sizeof(upb_inttable_header); const size_t entsize = upb_table_entrysize(&t->t); if (iter.array_part) { @@ -259,13 +260,13 @@ upb_inttable_iter upb_inttable_next(upb_inttable *t, upb_inttable_iter iter) { /* upb_strtable ***************************************************************/ -static upb_strtable_entry *strent(upb_strtable *t, int32_t i) { +static upb_strtable_entry *strent(const upb_strtable *t, int32_t i) { //fprintf(stderr, "i: %d, table_size: %d\n", i, upb_table_size(&t->t)); assert(i <= (int32_t)upb_table_size(&t->t)); return UPB_INDEX(t->t.entries, i, t->t.entry_size); } -static uint32_t upb_strtable_size(upb_strtable *t) { +static uint32_t upb_strtable_size(const upb_strtable *t) { return upb_table_size(&t->t); } @@ -288,12 +289,12 @@ void upb_strtable_free(upb_strtable *t) { upb_table_free(&t->t); } -static uint32_t strtable_bucket(upb_strtable *t, const char *key) { +static uint32_t strtable_bucket(const upb_strtable *t, const char *key) { uint32_t hash = MurmurHash2(key, strlen(key), 0); return (hash & t->t.mask); } -void *upb_strtable_lookup(upb_strtable *t, const char *key) { +void *upb_strtable_lookup(const upb_strtable *t, const char *key) { uint32_t bucket = strtable_bucket(t, key); upb_strtable_entry *e; do { @@ -303,7 +304,7 @@ void *upb_strtable_lookup(upb_strtable *t, const char *key) { return NULL; } -void *upb_strtable_lookupl(upb_strtable *t, const char *key, size_t len) { +void *upb_strtable_lookupl(const upb_strtable *t, const char *key, size_t len) { // TODO: improve. char key2[len+1]; memcpy(key2, key, len); @@ -383,7 +384,7 @@ void upb_strtable_insert(upb_strtable *t, const char *key, const void *val) { strinsert(t, key, val); } -void upb_strtable_begin(upb_strtable_iter *i, upb_strtable *t) { +void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { i->e = strent(t, -1); i->t = t; upb_strtable_next(i); diff --git a/upb/table.h b/upb/table.h index 4a44a6f..a8c2015 100644 --- a/upb/table.h +++ b/upb/table.h @@ -90,11 +90,11 @@ void upb_strtable_init(upb_strtable *table, uint32_t size, uint16_t value_size); void upb_strtable_free(upb_strtable *table); // Number of values in the hash table. -INLINE uint32_t upb_table_count(upb_table *t) { return t->count; } -INLINE uint32_t upb_inttable_count(upb_inttable *t) { +INLINE uint32_t upb_table_count(const upb_table *t) { return t->count; } +INLINE uint32_t upb_inttable_count(const upb_inttable *t) { return t->array_count + upb_table_count(&t->t); } -INLINE uint32_t upb_strtable_count(upb_strtable *t) { +INLINE uint32_t upb_strtable_count(const upb_strtable *t) { return upb_table_count(&t->t); } @@ -111,14 +111,14 @@ void upb_inttable_insert(upb_inttable *t, uint32_t key, const void *val); void upb_strtable_insert(upb_strtable *t, const char *key, const void *val); void upb_inttable_compact(upb_inttable *t); -INLINE uint32_t _upb_inttable_bucket(upb_inttable *t, uint32_t k) { +INLINE uint32_t _upb_inttable_bucket(const upb_inttable *t, uint32_t k) { uint32_t bucket = k & t->t.mask; // Identity hash for ints. assert(bucket != UPB_END_OF_CHAIN); return bucket; } // Returns true if this key belongs in the array part of the table. -INLINE bool _upb_inttable_isarrkey(upb_inttable *t, uint32_t k) { +INLINE bool _upb_inttable_isarrkey(const upb_inttable *t, uint32_t k) { return (k < t->array_size); } @@ -126,7 +126,7 @@ INLINE bool _upb_inttable_isarrkey(upb_inttable *t, uint32_t k) { // We have the caller specify the entry_size because fixing this as a literal // (instead of reading table->entry_size) gives the compiler more ability to // optimize. -INLINE void *_upb_inttable_fastlookup(upb_inttable *t, uint32_t key, +INLINE void *_upb_inttable_fastlookup(const upb_inttable *t, uint32_t key, size_t entry_size, size_t value_size) { upb_inttable_value *arrval = (upb_inttable_value*)UPB_INDEX(t->array, key, value_size); @@ -158,8 +158,8 @@ INLINE void *upb_inttable_lookup(upb_inttable *t, uint32_t key) { return _upb_inttable_fastlookup(t, key, t->t.entry_size, t->t.value_size); } -void *upb_strtable_lookupl(upb_strtable *t, const char *key, size_t len); -void *upb_strtable_lookup(upb_strtable *t, const char *key); +void *upb_strtable_lookupl(const upb_strtable *t, const char *key, size_t len); +void *upb_strtable_lookup(const upb_strtable *t, const char *key); /* upb_strtable_iter **********************************************************/ @@ -172,11 +172,11 @@ void *upb_strtable_lookup(upb_strtable *t, const char *key); // // ... // } typedef struct { - upb_strtable *t; + const upb_strtable *t; upb_strtable_entry *e; } upb_strtable_iter; -void upb_strtable_begin(upb_strtable_iter *i, upb_strtable *t); +void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); void upb_strtable_next(upb_strtable_iter *i); INLINE bool upb_strtable_done(upb_strtable_iter *i) { return i->e == NULL; } INLINE const char *upb_strtable_iter_key(upb_strtable_iter *i) { @@ -200,8 +200,8 @@ typedef struct { bool array_part; } upb_inttable_iter; -upb_inttable_iter upb_inttable_begin(upb_inttable *t); -upb_inttable_iter upb_inttable_next(upb_inttable *t, upb_inttable_iter iter); +upb_inttable_iter upb_inttable_begin(const upb_inttable *t); +upb_inttable_iter upb_inttable_next(const upb_inttable *t, upb_inttable_iter iter); INLINE bool upb_inttable_done(upb_inttable_iter iter) { return iter.value == NULL; } INLINE uint32_t upb_inttable_iter_key(upb_inttable_iter iter) { return iter.key; diff --git a/upb/upb.c b/upb/upb.c index bb85afc..a7c4ea0 100644 --- a/upb/upb.c +++ b/upb/upb.c @@ -87,7 +87,10 @@ void upb_status_copy(upb_status *to, upb_status *from) { } } -const char *upb_status_getstr(upb_status *status) { +const char *upb_status_getstr(const upb_status *_status) { + // Function is logically const but can modify internal state to materialize + // the string. + upb_status *status = (upb_status*)_status; if (status->str == NULL && status->space && status->space->code_to_string) { status->space->code_to_string(status->code, status->buf, status->bufsize); status->str = status->buf; diff --git a/upb/upb.h b/upb/upb.h index 708de7c..b79ca6d 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -144,8 +144,8 @@ typedef struct { int64_t int64; uint32_t uint32; bool _bool; - struct _upb_strref *strref; - struct _upb_fielddef *fielddef; + const struct _upb_strref *strref; + const struct _upb_fielddef *fielddef; void *_void; } val; @@ -178,10 +178,13 @@ UPB_VALUE_ACCESSORS(int64, int64, int64_t, UPB_TYPE(INT64)); UPB_VALUE_ACCESSORS(uint32, uint32, uint32_t, UPB_TYPE(UINT32)); UPB_VALUE_ACCESSORS(uint64, uint64, uint64_t, UPB_TYPE(UINT64)); UPB_VALUE_ACCESSORS(bool, _bool, bool, UPB_TYPE(BOOL)); -UPB_VALUE_ACCESSORS(strref, strref, struct _upb_strref*, UPB_TYPE(STRING)); -UPB_VALUE_ACCESSORS(fielddef, fielddef, struct _upb_fielddef*, UPB_VALUETYPE_FIELDDEF); UPB_VALUE_ACCESSORS(ptr, _void, void*, UPB_VALUETYPE_PTR); +// upb_fielddef and upb_strref should never be modified from a callback +// (ie. when they're getting passed through a upb_value). +UPB_VALUE_ACCESSORS(strref, strref, const struct _upb_strref*, UPB_TYPE(STRING)); +UPB_VALUE_ACCESSORS(fielddef, fielddef, const struct _upb_fielddef*, UPB_VALUETYPE_FIELDDEF); + extern upb_value UPB_NO_VALUE; @@ -223,7 +226,7 @@ void upb_status_seterrliteral(upb_status *status, const char *msg); void upb_status_seterrf(upb_status *s, const char *msg, ...); void upb_status_setcode(upb_status *s, upb_errorspace *space, int code); // The returned string is invalidated by any other call into the status. -const char *upb_status_getstr(upb_status *s); +const char *upb_status_getstr(const upb_status *s); void upb_status_copy(upb_status *to, upb_status *from); extern upb_errorspace upb_posix_errorspace; -- cgit v1.2.3