From fa5710f1cad50ddd17605c73d4661acbf265a469 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 2 Jan 2010 15:30:51 -0800 Subject: upb_string* -> upb_strptr, to follow aliasing rules. --- src/upb.h | 43 ++++++++++++++++-- src/upb_data.c | 100 ++++++++++++++++++++++++------------------ src/upb_data.h | 133 +++++++++++++++++++++++++++----------------------------- src/upb_def.c | 74 ++++++++++++++++--------------- src/upb_def.h | 20 ++++----- src/upb_parse.c | 2 +- src/upb_parse.h | 4 +- src/upb_table.c | 14 +++--- src/upb_table.h | 4 +- src/upb_text.c | 4 +- src/upb_text.h | 4 +- 11 files changed, 224 insertions(+), 178 deletions(-) (limited to 'src') diff --git a/src/upb.h b/src/upb.h index e130dd8..ecd5637 100644 --- a/src/upb.h +++ b/src/upb.h @@ -125,15 +125,50 @@ struct upb_tag { // INTERNAL-ONLY: never refer to these types with a tag ("union", "struct"). // Always use the typedefs. -union _upb_string; union _upb_array; struct _upb_msg; -typedef union _upb_string upb_string; typedef union _upb_array upb_array; typedef struct _upb_msg upb_msg; typedef upb_atomic_refcount_t upb_data; +typedef uint32_t upb_strlen_t; + +// We have several different representations for string, depending on whether +// it has a refcount (and likely in the future, depending on whether it is a +// slice of another string). We could just have one representation with +// members that are sometimes unused, but this is wasteful in memory. The +// flags that are always part of the first word tell us which representation +// to use. +// +// In a way, this is like inheritance but instead of using a virtual pointer, +// we do switch/case in every "virtual" method. This may sound expensive but +// in many cases the different cases compile to exactly the same code, so there +// is no branch. + +typedef struct { + uint32_t byte_size_and_flags; + upb_strlen_t byte_len; + // We expect the data to be 8-bit clean (uint8_t), but char* is such an + // ingrained convention that we follow it. + char *ptr; +} upb_norefcount_string; + +// Used for a string with a refcount. +typedef struct { + upb_data base; + upb_strlen_t byte_len; + char *ptr; + uint32_t byte_size; +} upb_refcounted_string; + +typedef union { + // Must be first, for the UPB_STATIC_STRING_PTR_INIT() macro. + upb_norefcount_string *norefcount; + upb_data *base; + upb_refcounted_string *refcounted; +} upb_strptr; + // A single .proto value. The owner must have an out-of-band way of knowing // the type, so that it knows which union member to use. union upb_value { @@ -144,7 +179,7 @@ union upb_value { uint32_t uint32; uint64_t uint64; bool _bool; - upb_string *str; + upb_strptr str; upb_array *arr; upb_msg *msg; upb_data *data; @@ -161,7 +196,7 @@ union upb_value_ptr { uint32_t *uint32; uint64_t *uint64; bool *_bool; - upb_string **str; + upb_strptr *str; upb_array **arr; upb_msg **msg; upb_data **data; diff --git a/src/upb_data.c b/src/upb_data.c index e1aebdf..01acef8 100644 --- a/src/upb_data.c +++ b/src/upb_data.c @@ -57,65 +57,81 @@ static void check_not_frozen(upb_data *d) { /* upb_string *******************************************************************/ -upb_string *upb_string_new() { - upb_string *s = malloc(sizeof(upb_refcounted_string)); - data_init(&s->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED); - s->refcounted.byte_size = 0; - s->common.byte_len = 0; - s->common.ptr = NULL; +static char *_upb_string_setptr(upb_strptr s, char *ptr) { + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) + return s.refcounted->ptr = ptr; + else + return s.norefcount->ptr = ptr; +} + +static void _upb_string_set_bytelen(upb_strptr s, upb_strlen_t newlen) { + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) { + s.refcounted->byte_len = newlen; + } else { + s.norefcount->byte_len = newlen; + } +} + +upb_strptr upb_string_new() { + upb_strptr s; + s.refcounted = malloc(sizeof(upb_refcounted_string)); + data_init(s.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED); + s.refcounted->byte_size = 0; + s.refcounted->byte_len = 0; + s.refcounted->ptr = NULL; return s; } -static upb_strlen_t string_get_bytesize(upb_string *s) { - if(upb_data_hasflag(&s->common.base, UPB_DATA_REFCOUNTED)) { - return s->refcounted.byte_size; +static upb_strlen_t string_get_bytesize(upb_strptr s) { + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) { + return s.refcounted->byte_size; } else { - return (s->norefcount.byte_size_and_flags & 0xFFFFFFF8) >> 3; + return (s.norefcount->byte_size_and_flags & 0xFFFFFFF8) >> 3; } } -static void string_set_bytesize(upb_string *s, upb_strlen_t newsize) { - if(upb_data_hasflag(&s->common.base, UPB_DATA_REFCOUNTED)) { - s->refcounted.byte_size = newsize; +static void string_set_bytesize(upb_strptr s, upb_strlen_t newsize) { + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) { + s.refcounted->byte_size = newsize; } else { - s->norefcount.byte_size_and_flags &= 0x7; - s->norefcount.byte_size_and_flags |= (newsize << 3); + s.norefcount->byte_size_and_flags &= 0x7; + s.norefcount->byte_size_and_flags |= (newsize << 3); } } -void _upb_string_free(upb_string *s) +void _upb_string_free(upb_strptr s) { - if(string_get_bytesize(s) != 0) free(s->common.ptr); - free(s); + if(string_get_bytesize(s) != 0) free((void*)upb_string_getrobuf(s)); + free(s.base); } -void upb_string_resize(upb_string *s, upb_strlen_t byte_len) { - check_not_frozen(&s->common.base); +void upb_string_resize(upb_strptr s, upb_strlen_t byte_len) { + check_not_frozen(s.base); if(string_get_bytesize(s) < byte_len) { // Need to resize. size_t new_byte_size = round_up_to_pow2(byte_len); - s->common.ptr = realloc(s->common.ptr, new_byte_size); + _upb_string_setptr(s, realloc(_upb_string_getptr(s), new_byte_size)); string_set_bytesize(s, new_byte_size); } - s->common.byte_len = byte_len; + _upb_string_set_bytelen(s, byte_len); } -upb_string *upb_string_getref(upb_string *s, int ref_flags) { - if(_upb_data_incref(&s->common.base, ref_flags)) return s; - upb_string *copy = upb_strdup(s); +upb_strptr upb_string_getref(upb_strptr s, int ref_flags) { + if(_upb_data_incref(s.base, ref_flags)) return s; + upb_strptr copy = upb_strdup(s); if(ref_flags == UPB_REF_FROZEN) - upb_data_setflag(©->common.base, UPB_DATA_FROZEN); + upb_data_setflag(copy.base, UPB_DATA_FROZEN); return copy; } -upb_string *upb_strreadfile(const char *filename) { +upb_strptr upb_strreadfile(const char *filename) { FILE *f = fopen(filename, "rb"); - if(!f) return false; + if(!f) return UPB_STRING_NULL; if(fseek(f, 0, SEEK_END) != 0) goto error; long size = ftell(f); if(size < 0) goto error; if(fseek(f, 0, SEEK_SET) != 0) goto error; - upb_string *s = upb_string_new(); + upb_strptr s = upb_string_new(); char *buf = upb_string_getrwbuf(s, size); if(fread(buf, size, 1, f) != 1) goto error; fclose(f); @@ -123,18 +139,18 @@ upb_string *upb_strreadfile(const char *filename) { error: fclose(f); - return NULL; + return UPB_STRING_NULL; } -upb_string *upb_strdupc(const char *src) { - upb_string *copy = upb_string_new(); +upb_strptr upb_strdupc(const char *src) { + upb_strptr copy = upb_string_new(); upb_strlen_t len = strlen(src); char *buf = upb_string_getrwbuf(copy, len); memcpy(buf, src, len); return copy; } -void upb_strcat(upb_string *s, upb_string *append) { +void upb_strcat(upb_strptr s, upb_strptr append) { upb_strlen_t s_len = upb_strlen(s); upb_strlen_t append_len = upb_strlen(append); upb_strlen_t newlen = s_len + append_len; @@ -142,20 +158,20 @@ void upb_strcat(upb_string *s, upb_string *append) { upb_string_getrobuf(append), append_len); } -upb_string *upb_strslice(upb_string *s, int offset, int len) { - upb_string *slice = upb_string_new(); +upb_strptr upb_strslice(upb_strptr s, int offset, int len) { + upb_strptr slice = upb_string_new(); len = UPB_MIN((upb_strlen_t)len, upb_strlen(s) - (upb_strlen_t)offset); memcpy(upb_string_getrwbuf(slice, len), upb_string_getrobuf(s) + offset, len); return slice; } -upb_string *upb_strdup(upb_string *s) { - upb_string *copy = upb_string_new(); +upb_strptr upb_strdup(upb_strptr s) { + upb_strptr copy = upb_string_new(); upb_strcpy(copy, s); return copy; } -int upb_strcmp(upb_string *s1, upb_string *s2) { +int upb_strcmp(upb_strptr s1, upb_strptr s2) { upb_strlen_t common_length = UPB_MIN(upb_strlen(s1), upb_strlen(s2)); int common_diff = memcmp(upb_string_getrobuf(s1), upb_string_getrobuf(s2), common_length); @@ -315,8 +331,8 @@ static bool str_cb(void *udata, struct upb_msgdef *msgdef, union upb_value_ptr p = get_value_ptr(msg, f); upb_msg_sethas(msg, f); if(avail_len != total_len) abort(); /* TODO: support streaming. */ - if(!*p.str || !upb_data_only(*p.data)) { - if(*p.str) + if(upb_string_isnull(*p.str) || !upb_data_only(*p.data)) { + if(!upb_string_isnull(*p.str)) upb_string_unref(*p.str); *p.str = upb_string_new(); } @@ -373,7 +389,7 @@ void upb_msgparser_free(struct upb_msgparser *s) free(s); } -void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_string *str, +void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_strptr str, struct upb_status *status) { struct upb_msgparser *mp = upb_msgparser_new(md); @@ -383,7 +399,7 @@ void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_string *str, upb_msgparser_free(mp); } -size_t upb_msgparser_parse(struct upb_msgparser *s, upb_string *str, +size_t upb_msgparser_parse(struct upb_msgparser *s, upb_strptr str, struct upb_status *status) { return upb_cbparser_parse(s->s, str, status); diff --git a/src/upb_data.h b/src/upb_data.h index 6dc343b..9c55cee 100644 --- a/src/upb_data.h +++ b/src/upb_data.h @@ -165,88 +165,70 @@ INLINE bool _upb_data_unref(upb_data *d) { /* upb_string *****************************************************************/ -typedef uint32_t upb_strlen_t; - -// We have several different representations for string, depending on whether -// it has a refcount (and likely in the future, depending on whether it is a -// slice of another string). We could just have one representation with -// members that are sometimes unused, but this is wasteful in memory. The -// flags that are always part of the first word tell us which representation -// to use. -// -// upb_string_common is the members that are common to all representations. -typedef struct { - upb_data base; - upb_strlen_t byte_len; - // We expect the data to be 8-bit clean (uint8_t), but char* is such an - // ingrained convention that we follow it. - char *ptr; -} upb_string_common; - -// Used for a string without a refcount. -typedef struct { - uint32_t byte_size_and_flags; - upb_strlen_t byte_len; - char *ptr; -} upb_norefcount_string; - -// Used for a string with a refcount. -typedef struct { - upb_data base; - upb_strlen_t byte_len; - char *ptr; - uint32_t byte_size; -} upb_refcounted_string; - -union _upb_string { - upb_norefcount_string norefcount; - upb_string_common common; - upb_refcounted_string refcounted; -}; - // Returns a newly constructed, refcounted string which starts out empty. // Caller owns one ref on it. The returned string will not be frozen. -upb_string *upb_string_new(void); +upb_strptr upb_string_new(void); // INTERNAL-ONLY: // Frees the given string, alone with any memory the string owned. -void _upb_string_free(upb_string *s); +void _upb_string_free(upb_strptr s); // Returns a string to which caller owns a ref, and contains the same contents // as src. The returned value may be a copy of src, if the requested flags // were incompatible with src's. -upb_string *upb_string_getref(upb_string *s, int ref_flags); +upb_strptr upb_string_getref(upb_strptr s, int ref_flags); + +#define UPB_STRING_NULL_INITIALIZER {NULL} +static const upb_strptr UPB_STRING_NULL = UPB_STRING_NULL_INITIALIZER; +INLINE bool upb_string_isnull(upb_strptr s) { + return s.base == NULL; +} // The caller releases a ref on src, which it must previously have owned a ref // on. -INLINE void upb_string_unref(upb_string *s) { - if(_upb_data_unref(&s->common.base)) _upb_string_free(s); +INLINE void upb_string_unref(upb_strptr s) { + if(_upb_data_unref(s.base)) _upb_string_free(s); } // The string is resized to byte_len. The string must not be frozen. -void upb_string_resize(upb_string *s, upb_strlen_t len); +void upb_string_resize(upb_strptr s, upb_strlen_t len); // Returns a buffer to which the caller may write. The string is resized to // byte_len (which may or may not trigger a reallocation). The string must not // be frozen. -INLINE char *upb_string_getrwbuf(upb_string *s, upb_strlen_t byte_len) { +INLINE char *upb_string_getrwbuf(upb_strptr s, upb_strlen_t byte_len) { upb_string_resize(s, byte_len); - return s->common.ptr; + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) + return s.refcounted->ptr; + else + return s.norefcount->ptr; } -INLINE void upb_string_clear(upb_string *s) { +INLINE void upb_string_clear(upb_strptr s) { upb_string_getrwbuf(s, 0); } +// INTERNAL-ONLY: +// Gets/sets the pointer. +INLINE char *_upb_string_getptr(upb_strptr s) { + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) + return s.refcounted->ptr; + else + return s.norefcount->ptr; +} + // Returns a buffer that the caller may use to read the current contents of // the string. The number of bytes available is upb_strlen(s). -INLINE const char *upb_string_getrobuf(upb_string *s) { - return s->common.ptr; +INLINE const char *upb_string_getrobuf(upb_strptr s) { + return _upb_string_getptr(s); } // Returns the current length of the string. -INLINE upb_strlen_t upb_strlen(upb_string *s) { - return s->common.byte_len; +INLINE upb_strlen_t upb_strlen(upb_strptr s) { + if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED)) + return s.refcounted->byte_len; + else + return s.norefcount->byte_len; } /* upb_string library functions ***********************************************/ @@ -255,7 +237,7 @@ INLINE upb_strlen_t upb_strlen(upb_string *s) { // overflow. These only use the public upb_string interface. // More efficient than upb_strcmp if all you need is to test equality. -INLINE bool upb_streql(upb_string *s1, upb_string *s2) { +INLINE bool upb_streql(upb_strptr s1, upb_strptr s2) { upb_strlen_t len = upb_strlen(s1); if(len != upb_strlen(s2)) { return false; @@ -265,54 +247,65 @@ INLINE bool upb_streql(upb_string *s1, upb_string *s2) { } // Like strcmp(). -int upb_strcmp(upb_string *s1, upb_string *s2); +int upb_strcmp(upb_strptr s1, upb_strptr s2); // Like upb_strcpy, but copies from a buffer and length. -INLINE void upb_strcpylen(upb_string *dest, const void *src, upb_strlen_t len) { +INLINE void upb_strcpylen(upb_strptr dest, const void *src, upb_strlen_t len) { memcpy(upb_string_getrwbuf(dest, len), src, len); } // Replaces the contents of "dest" with the contents of "src". -INLINE void upb_strcpy(upb_string *dest, upb_string *src) { +INLINE void upb_strcpy(upb_strptr dest, upb_strptr src) { upb_strcpylen(dest, upb_string_getrobuf(src), upb_strlen(src)); } // Like upb_strcpy, but copies from a NULL-terminated string. -INLINE void upb_strcpyc(upb_string *dest, const char *src) { +INLINE void upb_strcpyc(upb_strptr dest, const char *src) { // This does two passes over src, but that is necessary unless we want to // repeatedly re-allocate dst, which seems worse. upb_strcpylen(dest, src, strlen(src)); } // Returns a new string whose contents are a copy of s. -upb_string *upb_strdup(upb_string *s); +upb_strptr upb_strdup(upb_strptr s); // Like upb_strdup(), but duplicates a C NULL-terminated string. -upb_string *upb_strdupc(const char *src); +upb_strptr upb_strdupc(const char *src); // Appends 'append' to 's' in-place, resizing s if necessary. -void upb_strcat(upb_string *s, upb_string *append); +void upb_strcat(upb_strptr s, upb_strptr append); // Returns a string that is a substring of the given string. Currently this // returns a copy, but in the future this may return an object that references // the original string data instead of copying it. Both now and in the future, // the caller owns a ref on whatever is returned. -upb_string *upb_strslice(upb_string *s, int offset, int len); +upb_strptr upb_strslice(upb_strptr s, int offset, int len); // Reads an entire file into a newly-allocated string (caller owns one ref). -upb_string *upb_strreadfile(const char *filename); +upb_strptr upb_strreadfile(const char *filename); // Typedef for a read-only string that is allocated statically or on the stack. // Initialize with the given macro, which must resolve to a const char*. You -// must not dynamically allocate this type. -typedef upb_string upb_static_string; -#define UPB_STRLIT_LEN(str, len) {0 | UPB_DATA_FROZEN, len, str} -#define UPB_STRLIT(str) {{0 | UPB_DATA_FROZEN, sizeof(str)-1, str}} +// must not dynamically allocate this type. Example usage: +// +// upb_static_string mystr = UPB_STATIC_STRING_INIT("biscuits"); +// upb_strptr mystr_ptr = UPB_STATIC_STRING_PTR_INIT(mystr); +// +// If C99 compund literals are available, the much nicer UPB_STRLIT macro is +// available instead: +// +// upb_strtr mystr_ptr = UPB_STRLIT("biscuits"); +// +typedef upb_norefcount_string upb_static_string; +#define UPB_STATIC_STRING_INIT_LEN(str, len) {0 | UPB_DATA_FROZEN, len, str} +#define UPB_STATIC_STRING_INIT(str) UPB_STATIC_STRING_INIT_LEN(str, sizeof(str)-1) +#define UPB_STATIC_STRING_PTR_INIT(static_string) {&static_string} +#define UPB_STRLIT(str) (upb_strptr){&(upb_static_string)UPB_STATIC_STRING_INIT(str)} // Allows using upb_strings in printf, ie: -// upb_string str = UPB_STRLIT("Hello, World!\n"); +// upb_strptr str = UPB_STRLIT("Hello, World!\n"); // printf("String is: " UPB_STRFMT, UPB_STRARG(str)); */ -#define UPB_STRARG(str) (str)->common.byte_len, (str)->common.ptr +#define UPB_STRARG(str) upb_strlen(str), upb_string_getrobuf(str) #define UPB_STRFMT "%.*s" /* upb_array ******************************************************************/ @@ -472,7 +465,7 @@ INLINE void upb_msg_clear(upb_msg *msg, struct upb_msgdef *md) { /* Parsing ********************************************************************/ -void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_string *str, +void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_strptr str, struct upb_status *status); struct upb_msgparser *upb_msgparser_new(struct upb_msgdef *def); @@ -480,7 +473,7 @@ void upb_msgparser_free(struct upb_msgparser *mp); void upb_msgparser_reset(struct upb_msgparser *mp, upb_msg *m); -size_t upb_msgparser_parse(struct upb_msgparser *mp, upb_string *str, +size_t upb_msgparser_parse(struct upb_msgparser *mp, upb_strptr str, struct upb_status *status); #endif diff --git a/src/upb_def.c b/src/upb_def.c index b1c4ab2..4f57407 100644 --- a/src/upb_def.c +++ b/src/upb_def.c @@ -150,7 +150,7 @@ void _upb_def_cyclic_ref(struct upb_def *def) { } static void upb_def_init(struct upb_def *def, enum upb_def_type type, - upb_string *fqname) { + upb_strptr fqname) { def->type = type; def->is_cyclic = 0; // We detect this later, after resolving refs. def->search_depth = 0; @@ -166,12 +166,12 @@ static void upb_def_uninit(struct upb_def *def) { struct upb_unresolveddef { struct upb_def base; - upb_string *name; + upb_strptr name; }; -static struct upb_unresolveddef *upb_unresolveddef_new(upb_string *str) { +static struct upb_unresolveddef *upb_unresolveddef_new(upb_strptr str) { struct upb_unresolveddef *def = malloc(sizeof(*def)); - upb_string *name = upb_string_getref(str, UPB_REF_THREADUNSAFE_READONLY); + upb_strptr name = upb_string_getref(str, UPB_REF_THREADUNSAFE_READONLY); upb_def_init(&def->base, UPB_DEF_UNRESOLVED, name); def->name = name; return def; @@ -273,7 +273,7 @@ static void fielddef_sort(struct upb_fielddef **defs, size_t num) static struct upb_msgdef *msgdef_new(struct upb_fielddef **fields, int num_fields, - upb_string *fqname, + upb_strptr fqname, struct upb_status *status) { if(num_fields > UPB_MAX_FIELDS) { @@ -356,11 +356,11 @@ struct ntoi_ent { struct iton_ent { struct upb_inttable_entry e; - upb_string *string; + upb_strptr string; }; static struct upb_enumdef *enumdef_new(google_protobuf_EnumDescriptorProto *ed, - upb_string *fqname) + upb_strptr fqname) { struct upb_enumdef *e = malloc(sizeof(*e)); upb_def_init(&e->base, UPB_DEF_ENUM, fqname); @@ -428,8 +428,8 @@ static int my_memrchr(char *data, char c, size_t len) /* Given a symbol and the base symbol inside which it is defined, find the * symbol's definition in t. */ static struct symtab_ent *resolve(struct upb_strtable *t, - upb_string *base, - upb_string *symbol) + upb_strptr base, + upb_strptr symbol) { if(upb_strlen(base) + upb_strlen(symbol) + 1 >= UPB_SYMBOL_MAXLEN || upb_strlen(symbol) == 0) return NULL; @@ -437,13 +437,13 @@ static struct symtab_ent *resolve(struct upb_strtable *t, if(upb_string_getrobuf(symbol)[0] == UPB_SYMBOL_SEPARATOR) { // Symbols starting with '.' are absolute, so we do a single lookup. // Slice to omit the leading '.' - upb_string *sym_str = upb_strslice(symbol, 1, INT_MAX); + upb_strptr sym_str = upb_strslice(symbol, 1, INT_MAX); struct symtab_ent *e = upb_strtable_lookup(t, sym_str); upb_string_unref(sym_str); return e; } else { // Remove components from base until we find an entry or run out. - upb_string *sym_str = upb_string_new(); + upb_strptr sym_str = upb_string_new(); int baselen = upb_strlen(base); while(1) { // sym_str = base[0...base_len] + UPB_SYMBOL_SEPARATOR + symbol @@ -466,8 +466,8 @@ static struct symtab_ent *resolve(struct upb_strtable *t, * join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" * join("", "Baz") -> "Baz" * Caller owns a ref on the returned string. */ -static upb_string *join(upb_string *base, upb_string *name) { - upb_string *joined = upb_strdup(base); +static upb_strptr join(upb_strptr base, upb_strptr name) { + upb_strptr joined = upb_strdup(base); upb_strlen_t len = upb_strlen(joined); if(len > 0) { upb_string_getrwbuf(joined, len + 1)[len] = UPB_SYMBOL_SEPARATOR; @@ -476,34 +476,34 @@ static upb_string *join(upb_string *base, upb_string *name) { return joined; } -static upb_string *try_define(struct upb_strtable *t, upb_string *base, - upb_string *name, struct upb_status *status) +static upb_strptr try_define(struct upb_strtable *t, upb_strptr base, + upb_strptr name, struct upb_status *status) { - if(!name) { + if(upb_string_isnull(name)) { upb_seterr(status, UPB_STATUS_ERROR, "symbol in context '" UPB_STRFMT "' does not have a name", UPB_STRARG(base)); - return NULL; + return UPB_STRING_NULL; } - upb_string *fqname = join(base, name); + upb_strptr fqname = join(base, name); if(upb_strtable_lookup(t, fqname)) { upb_seterr(status, UPB_STATUS_ERROR, "attempted to redefine symbol '" UPB_STRFMT "'", UPB_STRARG(fqname)); upb_string_unref(fqname); - return NULL; + return UPB_STRING_NULL; } return fqname; } static void insert_enum(struct upb_strtable *t, google_protobuf_EnumDescriptorProto *ed, - upb_string *base, + upb_strptr base, struct upb_status *status) { - upb_string *name = ed->set_flags.has.name ? ed->name : NULL; - upb_string *fqname = try_define(t, base, name, status); - if(!fqname) return; + upb_strptr name = ed->set_flags.has.name ? ed->name : UPB_STRING_NULL; + upb_strptr fqname = try_define(t, base, name, status); + if(upb_string_isnull(fqname)) return; struct symtab_ent e; e.e.key = fqname; @@ -514,12 +514,12 @@ static void insert_enum(struct upb_strtable *t, static void insert_message(struct upb_strtable *t, google_protobuf_DescriptorProto *d, - upb_string *base, bool sort, + upb_strptr base, bool sort, struct upb_status *status) { - upb_string *name = d->set_flags.has.name ? d->name : NULL; - upb_string *fqname = try_define(t, base, name, status); - if(!fqname) return; + upb_strptr name = d->set_flags.has.name ? d->name : UPB_STRING_NULL; + upb_strptr fqname = try_define(t, base, name, status); + if(upb_string_isnull(fqname)) return; int num_fields = d->set_flags.has.field ? d->field->len : 0; struct symtab_ent e; @@ -610,7 +610,7 @@ static void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs, google_protobuf_FileDescriptorProto *fd, bool sort, struct upb_status *status) { - upb_string *pkg; + upb_strptr pkg; if(fd->set_flags.has.package) { pkg = upb_string_getref(fd->package, UPB_REF_FROZEN); } else { @@ -639,11 +639,11 @@ static void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs, for(e = upb_strtable_begin(addto); e; e = upb_strtable_next(addto, &e->e)) { struct upb_msgdef *m = upb_dyncast_msgdef(e->def); if(!m) continue; - upb_string *base = e->e.key; + upb_strptr base = e->e.key; for(upb_field_count_t i = 0; i < m->num_fields; i++) { struct upb_fielddef *f = &m->fields[i]; if(!upb_hasdef(f)) continue; // No resolving necessary. - upb_string *name = upb_downcast_unresolveddef(f->def)->name; + upb_strptr name = upb_downcast_unresolveddef(f->def)->name; struct symtab_ent *found = resolve(existingdefs, base, name); if(!found) found = resolve(addto, base, name); upb_field_type_t expected = upb_issubmsg(f) ? UPB_DEF_MSG : UPB_DEF_ENUM; @@ -695,8 +695,10 @@ struct upb_symtab *upb_symtab_new() assert(false); return NULL; // Indicates that upb is buggy or corrupt. } - upb_string name = UPB_STRLIT("google.protobuf.FileDescriptorSet"); - struct symtab_ent *e = upb_strtable_lookup(&s->psymtab, &name); + upb_static_string name = + UPB_STATIC_STRING_INIT("google.protobuf.FileDescriptorSet"); + upb_strptr nameptr = UPB_STATIC_STRING_PTR_INIT(name); + struct symtab_ent *e = upb_strtable_lookup(&s->psymtab, nameptr); assert(e); s->fds_msgdef = upb_downcast_msgdef(e->def); return s; @@ -741,7 +743,7 @@ struct upb_def **upb_symtab_getdefs(struct upb_symtab *s, int *count, return defs; } -struct upb_def *upb_symtab_lookup(struct upb_symtab *s, upb_string *sym) +struct upb_def *upb_symtab_lookup(struct upb_symtab *s, upb_strptr sym) { upb_rwlock_rdlock(&s->lock); struct symtab_ent *e = upb_strtable_lookup(&s->symtab, sym); @@ -755,8 +757,8 @@ struct upb_def *upb_symtab_lookup(struct upb_symtab *s, upb_string *sym) } -struct upb_def *upb_symtab_resolve(struct upb_symtab *s, upb_string *base, - upb_string *symbol) { +struct upb_def *upb_symtab_resolve(struct upb_symtab *s, upb_strptr base, + upb_strptr symbol) { upb_rwlock_rdlock(&s->lock); struct symtab_ent *e = resolve(&s->symtab, base, symbol); struct upb_def *ret = NULL; @@ -818,7 +820,7 @@ void upb_symtab_addfds(struct upb_symtab *s, return; } -void upb_symtab_add_desc(struct upb_symtab *s, upb_string *desc, +void upb_symtab_add_desc(struct upb_symtab *s, upb_strptr desc, struct upb_status *status) { upb_msg *fds = upb_msg_new(s->fds_msgdef); diff --git a/src/upb_def.h b/src/upb_def.h index d44f879..15af25a 100644 --- a/src/upb_def.h +++ b/src/upb_def.h @@ -53,7 +53,7 @@ enum upb_def_type { typedef int8_t upb_def_type_t; struct upb_def { - upb_string *fqname; // Fully qualified. + upb_strptr fqname; // Fully qualified. upb_atomic_refcount_t refcount; upb_def_type_t type; @@ -121,7 +121,7 @@ struct upb_fielddef { upb_field_type_t type; upb_label_t label; upb_field_number_t number; - upb_string *name; + upb_strptr name; union upb_value default_value; // These are set only when this fielddef is part of a msgdef. @@ -206,7 +206,7 @@ INLINE struct upb_fielddef *upb_msg_itof(struct upb_msgdef *m, uint32_t num) { } INLINE struct upb_fielddef *upb_msg_ntof(struct upb_msgdef *m, - upb_string *name) { + upb_strptr name) { struct upb_ntof_ent *e; e = (struct upb_ntof_ent*)upb_strtable_lookup(&m->ntof, name); return e ? e->f : NULL; @@ -223,9 +223,9 @@ struct upb_enumdef { typedef int32_t upb_enumval_t; // Lookups from name to integer and vice-versa. -bool upb_enumdef_ntoi(struct upb_enumdef *e, upb_string *name, +bool upb_enumdef_ntoi(struct upb_enumdef *e, upb_strptr name, upb_enumval_t *num); -upb_string *upb_enumdef_iton(struct upb_enumdef *e, upb_enumval_t num); +upb_strptr upb_enumdef_iton(struct upb_enumdef *e, upb_enumval_t num); // Iteration over name/value pairs. The order is undefined. // struct upb_enumd_iter i; @@ -235,7 +235,7 @@ upb_string *upb_enumdef_iton(struct upb_enumdef *e, upb_enumval_t num); struct upb_enum_iter { struct upb_enumdef *e; void *state; // Internal iteration state. - upb_string *name; + upb_strptr name; upb_enumval_t val; }; void upb_enum_begin(struct upb_enum_iter *iter, struct upb_enumdef *e); @@ -279,12 +279,12 @@ INLINE void upb_symtab_unref(struct upb_symtab *s) { // // If a def is found, the caller owns one ref on the returned def. Otherwise // returns NULL. -struct upb_def *upb_symtab_resolve(struct upb_symtab *s, upb_string *base, - upb_string *symbol); +struct upb_def *upb_symtab_resolve(struct upb_symtab *s, upb_strptr base, + upb_strptr symbol); // 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. -struct upb_def *upb_symtab_lookup(struct upb_symtab *s, upb_string *sym); +struct upb_def *upb_symtab_lookup(struct upb_symtab *s, upb_strptr 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 @@ -298,7 +298,7 @@ struct upb_def **upb_symtab_getdefs(struct upb_symtab *s, int *count, // defined in desc). desc may not attempt to define any names that are already // defined in this symtab. Caller retains ownership of desc. status indicates // whether the operation was successful or not, and the error message (if any). -void upb_symtab_add_desc(struct upb_symtab *s, upb_string *desc, +void upb_symtab_add_desc(struct upb_symtab *s, upb_strptr desc, struct upb_status *status); #ifdef __cplusplus diff --git a/src/upb_parse.c b/src/upb_parse.c index 32332d9..c4790c6 100644 --- a/src/upb_parse.c +++ b/src/upb_parse.c @@ -416,7 +416,7 @@ static const void *pop(struct upb_cbparser *p, const uint8_t *start) } -size_t upb_cbparser_parse(struct upb_cbparser *p, upb_string *str, +size_t upb_cbparser_parse(struct upb_cbparser *p, upb_strptr str, struct upb_status *status) { // buf is our current offset, moves from start to end. diff --git a/src/upb_parse.h b/src/upb_parse.h index 7086204..056750f 100644 --- a/src/upb_parse.h +++ b/src/upb_parse.h @@ -80,7 +80,7 @@ void upb_cbparser_reset(struct upb_cbparser *p, void *udata); // // TODO: see if we can provide the following guarantee efficiently: // retval will always be >= len. */ -size_t upb_cbparser_parse(struct upb_cbparser *p, upb_string *str, +size_t upb_cbparser_parse(struct upb_cbparser *p, upb_strptr str, struct upb_status *status); /* Pick parser interface. ************************************************/ @@ -119,7 +119,7 @@ struct upb_pickparser *upb_pickparser_new(struct upb_msgdef *msgdef, upb_pp_str_cb str_cb); void upb_pickparser_free(struct upb_pickparser *p); void upb_pickparser_reset(struct upb_pickparser *p, void *udata); -size_t upb_pickparser_parse(struct upb_pickparser *p, upb_string *str, +size_t upb_pickparser_parse(struct upb_pickparser *p, upb_strptr str, struct upb_status *status); #ifdef __cplusplus diff --git a/src/upb_table.c b/src/upb_table.c index f6f6d22..14902df 100644 --- a/src/upb_table.c +++ b/src/upb_table.c @@ -57,19 +57,19 @@ void upb_strtable_free(struct upb_strtable *t) { upb_table_free(&t->t); } -static uint32_t strtable_bucket(struct upb_strtable *t, upb_string *key) +static uint32_t strtable_bucket(struct upb_strtable *t, upb_strptr key) { uint32_t hash = MurmurHash2(upb_string_getrobuf(key), upb_strlen(key), 0); return (hash & (upb_strtable_size(t)-1)) + 1; } -void *upb_strtable_lookup(struct upb_strtable *t, upb_string *key) +void *upb_strtable_lookup(struct upb_strtable *t, upb_strptr key) { uint32_t bucket = strtable_bucket(t, key); struct upb_strtable_entry *e; do { e = strent(t, bucket); - if(e->key && upb_streql(e->key, key)) return e; + if(!upb_string_isnull(e->key) && upb_streql(e->key, key)) return e; } while((bucket = e->next) != UPB_END_OF_CHAIN); return NULL; } @@ -149,7 +149,7 @@ static uint32_t empty_strbucket(struct upb_strtable *table) /* TODO: does it matter that this is biased towards the front of the table? */ for(uint32_t i = 1; i <= upb_strtable_size(table); i++) { struct upb_strtable_entry *e = strent(table, i); - if(e->key == NULL) return i; + if(upb_string_isnull(e->key)) return i; } assert(false); return 0; @@ -162,7 +162,7 @@ static void strinsert(struct upb_strtable *t, struct upb_strtable_entry *e) t->t.count++; uint32_t bucket = strtable_bucket(t, e->key); struct upb_strtable_entry *table_e = strent(t, bucket); - if(table_e->key != NULL) { /* Collision. */ + if(!upb_string_isnull(table_e->key)) { /* Collision. */ if(bucket == strtable_bucket(t, table_e->key)) { /* Existing element is in its main posisiton. Find an empty slot to * place our new element and append it to this key's chain. */ @@ -179,7 +179,7 @@ static void strinsert(struct upb_strtable *t, struct upb_strtable_entry *e) memcpy(strent(t, empty_bucket), table_e, t->t.entry_size); /* copies next */ struct upb_strtable_entry *evictee_e = strent(t, evictee_bucket); while(1) { - assert(evictee_e->key != NULL); + assert(!upb_string_isnull(evictee_e->key)); assert(evictee_e->next != UPB_END_OF_CHAIN); if(evictee_e->next == bucket) { evictee_e->next = empty_bucket; @@ -232,7 +232,7 @@ void *upb_strtable_next(struct upb_strtable *t, struct upb_strtable_entry *cur) do { cur = (void*)((char*)cur + t->t.entry_size); if(cur == end) return NULL; - } while(cur->key == NULL); + } while(upb_string_isnull(cur->key)); return cur; } diff --git a/src/upb_table.h b/src/upb_table.h index b89906d..f7f548b 100644 --- a/src/upb_table.h +++ b/src/upb_table.h @@ -38,7 +38,7 @@ struct upb_inttable_entry { // performance by letting us compare hashes before comparing lengths or the // strings themselves. struct upb_strtable_entry { - upb_string *key; // We own a frozen ref. + upb_strptr key; // We own a frozen ref. uint32_t next; // Internal chaining. }; @@ -116,7 +116,7 @@ INLINE void *upb_inttable_lookup(struct upb_inttable *t, uint32_t key) { return upb_inttable_fast_lookup(t, key, t->t.entry_size); } -void *upb_strtable_lookup(struct upb_strtable *t, upb_string *key); +void *upb_strtable_lookup(struct upb_strtable *t, upb_strptr key); /* Provides iteration over the table. The order in which the entries are * returned is undefined. Insertions invalidate iterators. The _next diff --git a/src/upb_text.c b/src/upb_text.c index 17efa9f..225b344 100644 --- a/src/upb_text.c +++ b/src/upb_text.c @@ -49,7 +49,7 @@ static void print_indent(struct upb_text_printer *p, FILE *stream) } void upb_text_printfield(struct upb_text_printer *p, - upb_string *name, + upb_strptr name, upb_field_type_t valtype, union upb_value val, FILE *stream) { @@ -63,7 +63,7 @@ void upb_text_printfield(struct upb_text_printer *p, } void upb_text_push(struct upb_text_printer *p, - upb_string *submsg_type, + upb_strptr submsg_type, FILE *stream) { print_indent(p, stream); diff --git a/src/upb_text.h b/src/upb_text.h index 6b2f4eb..bc15c3f 100644 --- a/src/upb_text.h +++ b/src/upb_text.h @@ -23,10 +23,10 @@ INLINE void upb_text_printer_init(struct upb_text_printer *p, bool single_line) p->single_line = single_line; } void upb_text_printval(upb_field_type_t type, union upb_value p, FILE *file); -void upb_text_printfield(struct upb_text_printer *p, upb_string *name, +void upb_text_printfield(struct upb_text_printer *p, upb_strptr name, upb_field_type_t valtype, union upb_value val, FILE *stream); -void upb_text_push(struct upb_text_printer *p, upb_string *submsg_type, +void upb_text_push(struct upb_text_printer *p, upb_strptr submsg_type, FILE *stream); void upb_text_pop(struct upb_text_printer *p, FILE *stream); -- cgit v1.2.3