From: Behdad Esfahbod Date: Thu, 28 Apr 2011 01:22:32 +0000 (-0400) Subject: Add initial implementation of user_data to objects X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=29c67d3f70b081766a6c01353980f457f38aeb12;p=platform%2Fupstream%2FlibHarfBuzzSharp.git Add initial implementation of user_data to objects --- diff --git a/src/hb-common.h b/src/hb-common.h index e6f5f2b..74030f4 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -68,8 +68,6 @@ typedef union _hb_var_int_t { int8_t i8[4]; } hb_var_int_t; -typedef void (*hb_destroy_func_t) (void *user_data); - /* hb_tag_t */ @@ -287,6 +285,15 @@ hb_direction_t hb_script_get_horizontal_direction (hb_script_t script); +/* User data */ + +typedef struct _hb_user_data_key_t { + char unused; +} hb_user_data_key_t; + +typedef void (*hb_destroy_func_t) (void *user_data); + + HB_END_DECLS #endif /* HB_COMMON_H */ diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh index 8fbddd4..7bc6b46 100644 --- a/src/hb-object-private.hh +++ b/src/hb-object-private.hh @@ -44,10 +44,172 @@ HB_BEGIN_DECLS #endif +/* user_data */ + +HB_END_DECLS + + +template +struct hb_static_array_t { + + unsigned int len; + unsigned int allocated; + Type *array; + Type static_array[StaticSize]; + + void finish (void) { for (unsigned i = 0; i < len; i++) array[i].finish (); } + + inline Type& operator [] (unsigned int i) + { + return array[i]; + } + + inline Type *push (void) + { + if (!array) { + array = static_array; + allocated = ARRAY_LENGTH (static_array); + } + if (likely (len < allocated)) + return &array[len++]; + /* Need to reallocate */ + unsigned int new_allocated = allocated + (allocated >> 1) + 8; + Type *new_array; + if (array == static_array) { + new_array = (Type *) calloc (new_allocated, sizeof (Type)); + if (new_array) { + memcpy (new_array, array, len * sizeof (Type)); + array = new_array; + } + } else { + bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (Type); + if (unlikely (overflows)) + new_array = NULL; + else + new_array = (Type *) realloc (array, new_allocated * sizeof (Type)); + if (new_array) { + free (array); + array = new_array; + } + } + if ((len < allocated)) + return &array[len++]; + else + return NULL; + } + + inline void pop (void) + { + len--; + /* TODO: shrink array if needed */ + } +}; + +template +struct hb_array_t : hb_static_array_t {}; + + +template +struct hb_map_t +{ + struct item_t { + Key key; + /* unsigned int hash; */ + Value value; + + void finish (void) { value.finish (); } + }; + + hb_array_t items; + + private: + + inline item_t *find (Key key) { + if (unlikely (!key)) return NULL; + for (unsigned int i = 0; i < items.len; i++) + if (key == items[i].key) + return &items[i]; + return NULL; + } + + public: + + inline bool set (Key key, + Value &value) + { + if (unlikely (!key)) return NULL; + item_t *item; + item = find (key); + if (item) + item->finish (); + else + item = items.push (); + if (unlikely (!item)) return false; + item->key = key; + item->value = value; + return true; + } + + inline void unset (Key &key) + { + item_t *item; + item = find (key); + if (!item) return; + + item->finish (); + items[items.len - 1] = *item; + items.pop (); + } + + inline Value *get (Key key) + { + item_t *item = find (key); + return item ? &item->value : NULL; + } + + void finish (void) { items.finish (); } +}; + + +HB_BEGIN_DECLS + +typedef struct { + void *data; + hb_destroy_func_t destroy; + + void finish (void) { if (destroy) destroy (data); } +} hb_user_data_t; + +struct hb_user_data_array_t { + + hb_map_t map; + + inline bool set (hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy) + { + if (!data && !destroy) { + map.unset (key); + return true; + } + hb_user_data_t user_data = {data, destroy}; + return map.set (key, user_data); + } + + inline void *get (hb_user_data_key_t *key) { + return map.get (key); + } + + void finish (void) { map.finish (); } +}; + + + typedef struct _hb_object_header_t hb_object_header_t; struct _hb_object_header_t { hb_reference_count_t ref_count; + hb_user_data_array_t user_data; #define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID} @@ -64,7 +226,9 @@ struct _hb_object_header_t { ref_count.init (1); } - inline bool is_inert (void) const { return unlikely (ref_count.is_invalid ()); } + inline bool is_inert (void) const { + return unlikely (ref_count.is_invalid ()); + } inline void reference (void) { if (unlikely (!this || this->is_inert ())) @@ -75,7 +239,25 @@ struct _hb_object_header_t { inline bool destroy (void) { if (unlikely (!this || this->is_inert ())) return false; - return ref_count.dec () == 1; + if (ref_count.dec () != 1) + return false; + + user_data.finish (); + + return true; + } + + inline bool set_user_data (hb_user_data_key_t *key, + void * data, + hb_destroy_func_t destroy) { + if (unlikely (!this || this->is_inert ())) + return false; + + return user_data.set (key, data, destroy); + } + + inline void *get_user_data (hb_user_data_key_t *key) { + return user_data.get (key); } inline void trace (const char *function) const {