From 2282d2489bd8db3cd4ddbe0dd813732bffcf6452 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 12 Aug 2009 13:47:24 -0700 Subject: Refactoring: unify upb_msg. The cost is that a upb_msg will now always have an overhead of 2*sizeof(void*). This is comparable to proto2 overhead. The benefit is that upb_msg is now self-describing, and read-only algorithms can now operate on a upb_msg regardless of the memory-management scheme. Also, upb_array and upb_string now know inherently if they own their associated memory, and upb_array has a generic pointer for memory management purposes like upb_msg does. --- src/upb_string.h | 78 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 21 deletions(-) (limited to 'src/upb_string.h') diff --git a/src/upb_string.h b/src/upb_string.h index 528c8c8..7b63f1c 100644 --- a/src/upb_string.h +++ b/src/upb_string.h @@ -37,6 +37,7 @@ extern "C" { #define INLINE static inline #endif +#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) #define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) struct upb_string { @@ -44,45 +45,80 @@ struct upb_string { * ingrained convention that we follow it. */ char *ptr; uint32_t byte_len; + uint32_t byte_size; /* How many bytes of ptr we own. */ }; +INLINE void upb_strinit(struct upb_string *str) +{ + str->ptr = NULL; + str->byte_len = 0; + str->byte_size = 0; +} + +INLINE void upb_struninit(struct upb_string *str) +{ + if(str->byte_size) free(str->ptr); +} + +INLINE struct upb_string *upb_strnew() +{ + struct upb_string *str = (struct upb_string*)malloc(sizeof(*str)); + upb_strinit(str); + return str; +} + +INLINE void upb_strfree(struct upb_string *str) +{ + upb_struninit(str); + free(str); +} + +INLINE void upb_stralloc(struct upb_string *str, uint32_t size) +{ + if(str->byte_size < size) { + /* Need to resize. */ + str->byte_size = size; + void *oldptr = str->byte_size == 0 ? NULL : str->ptr; + str->ptr = (char*)realloc(oldptr, str->byte_size); + } +} + +INLINE void upb_strdrop(struct upb_string *str) +{ + upb_struninit(str); +} + INLINE bool upb_streql(struct upb_string *s1, struct upb_string *s2) { return s1->byte_len == s2->byte_len && memcmp(s1->ptr, s2->ptr, s1->byte_len) == 0; } -INLINE int upb_strcmp(struct upb_string s1, struct upb_string s2) { - size_t common_length = UPB_MIN(s1.byte_len, s2.byte_len); - int common_diff = memcmp(s1.ptr, s2.ptr, common_length); - if(common_diff == 0) return s1.byte_len - s2.byte_len; - else return common_diff; +INLINE int upb_strcmp(struct upb_string *s1, struct upb_string *s2) { + size_t common_length = UPB_MIN(s1->byte_len, s2->byte_len); + int common_diff = memcmp(s1->ptr, s2->ptr, common_length); + return common_diff == 0 ? (int)s1->byte_len - (int)s2->byte_len : common_diff; } INLINE void upb_strcpy(struct upb_string *dest, struct upb_string *src) { - memcpy(dest->ptr, src->ptr, src->byte_len); dest->byte_len = src->byte_len; + upb_stralloc(dest, dest->byte_len); + memcpy(dest->ptr, src->ptr, src->byte_len); } -INLINE struct upb_string upb_strdup(struct upb_string s) { - struct upb_string copy; - copy.ptr = (char*)malloc(s.byte_len); - copy.byte_len = s.byte_len; - memcpy(copy.ptr, s.ptr, s.byte_len); +INLINE struct upb_string *upb_strdup(struct upb_string *s) { + struct upb_string *copy = upb_strnew(); + upb_strcpy(copy, s); return copy; } -INLINE struct upb_string upb_strdupc(char *s) { - struct upb_string copy; - copy.byte_len = strlen(s); - copy.ptr = (char*)malloc(copy.byte_len); - memcpy(copy.ptr, s, copy.byte_len); +INLINE struct upb_string *upb_strdupc(char *s) { + struct upb_string *copy = upb_strnew(); + copy->byte_len = strlen(s); + upb_stralloc(copy, copy->byte_len); + memcpy(copy->ptr, s, copy->byte_len); return copy; } -INLINE void upb_strfree(struct upb_string s) { - free(s.ptr); -} - /* Reads an entire file into a newly-allocated string. */ bool upb_strreadfile(const char *filename, struct upb_string *data); @@ -95,7 +131,7 @@ bool upb_strreadfile(const char *filename, struct upb_string *data); /* Allows using upb_strings in printf, ie: * struct upb_string str = UPB_STRLIT("Hello, World!\n"); * printf("String is: " UPB_STRFMT, UPB_STRARG(str)); */ -#define UPB_STRARG(str) (str).byte_len, (str).ptr +#define UPB_STRARG(str) (str)->byte_len, (str)->ptr #define UPB_STRFMT "%.*s" #ifdef __cplusplus -- cgit v1.2.3