Changeset 5550

Show
Ignore:
Timestamp:
06/01/08 22:21:40 (4 months ago)
Author:
morris
Message:

Copy wi-hash implementation to new name wi-dictionary

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • libwired/trunk/libwired/base/wi-base.c

    r5417 r5550  
    6565        wi_data_register(); 
    6666        wi_date_register(); 
     67        wi_dictionary_register(); 
    6768        wi_enumerator_register(); 
    6869        wi_error_register(); 
     
    116117 
    117118        wi_array_initialize(); 
     119        wi_dictionary_initialize(); 
    118120        wi_hash_initialize(); 
    119121        wi_set_initialize(); 
  • libwired/trunk/libwired/base/wi-private.h

    r5547 r5550  
    3434#include <wired/wi-array.h> 
    3535#include <wired/wi-base.h> 
     36#include <wired/wi-dictionary.h> 
    3637#include <wired/wi-enumerator.h> 
    3738#include <wired/wi-error.h> 
     
    6263WI_EXPORT void                                                  wi_data_register(void); 
    6364WI_EXPORT void                                                  wi_date_register(void); 
     65WI_EXPORT void                                                  wi_dictionary_register(void); 
    6466WI_EXPORT void                                                  wi_enumerator_register(void); 
    6567WI_EXPORT void                                                  wi_error_register(void); 
     
    98100WI_EXPORT void                                                  wi_data_initialize(void); 
    99101WI_EXPORT void                                                  wi_date_initialize(void); 
     102WI_EXPORT void                                                  wi_dictionary_initialize(void); 
    100103WI_EXPORT void                                                  wi_enumerator_initialize(void); 
    101104WI_EXPORT void                                                  wi_error_initialize(void); 
     
    145148WI_EXPORT void *                                                wi_enumerator_hash_key_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
    146149WI_EXPORT void *                                                wi_enumerator_hash_data_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
     150WI_EXPORT void *                                                wi_enumerator_dictionary_key_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
     151WI_EXPORT void *                                                wi_enumerator_dictionary_data_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
    147152WI_EXPORT void *                                                wi_enumerator_set_data_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
    148153 
  • libwired/trunk/libwired/collections/wi-dictionary.c

    r5549 r5550  
    3636#include <wired/wi-array.h> 
    3737#include <wired/wi-assert.h> 
    38 #include <wired/wi-hash.h> 
     38#include <wired/wi-dictionary.h> 
    3939#include <wired/wi-lock.h> 
    4040#include <wired/wi-macros.h> 
     
    4545#include <wired/wi-system.h> 
    4646 
    47 #define _WI_HASH_MIN_COUNT                            11 
    48 #define _WI_HASH_MAX_COUNT                            16777213 
    49  
    50 #define _WI_HASH_CHECK_RESIZE(hash)                                                                   \ 
    51         WI_STMT_START                                                                                                   
    52                 if((hash->buckets_count >= 3 * hash->key_count &&                     \ 
    53                     hash->buckets_count >  hash->min_count) ||                        \ 
    54                    (hash->key_count     >= 3 * hash->buckets_count &&         \ 
    55                         hash->buckets_count <  _WI_HASH_MAX_COUNT))                           \ 
    56                         _wi_hash_resize(hash);                                                                \ 
     47#define _WI_DICTIONARY_MIN_COUNT                              11 
     48#define _WI_DICTIONARY_MAX_COUNT                              16777213 
     49 
     50#define _WI_DICTIONARY_CHECK_RESIZE(dictionary)                                                               \ 
     51        WI_STMT_START                                                                                                                  
     52                if((dictionary->buckets_count >= 3 * dictionary->key_count &&         \ 
     53                    dictionary->buckets_count >  dictionary->min_count) ||                    \ 
     54                   (dictionary->key_count     >= 3 * dictionary->buckets_count &&     \ 
     55                        dictionary->buckets_count <  _WI_DICTIONARY_MAX_COUNT))                       \ 
     56                        _wi_dictionary_resize(dictionary);                                                            \ 
    5757        WI_STMT_END 
    5858 
    59 #define _WI_HASH_KEY_RETAIN(hash, key)                                                        \ 
    60         ((hash)->key_callbacks.retain                                                                 \ 
    61                 ? (*(hash)->key_callbacks.retain)((key))                                      \ 
     59#define _WI_DICTIONARY_KEY_RETAIN(dictionary, key)                                                    \ 
     60        ((dictionary)->key_callbacks.retain                                                                           \ 
     61                ? (*(dictionary)->key_callbacks.retain)((key))                                        \ 
    6262                : (key)) 
    6363 
    64 #define _WI_HASH_KEY_RELEASE(hash, key)                                                               \ 
    65         WI_STMT_START                                                                                                   
    66                 if((hash)->key_callbacks.release)                                                     \ 
    67                         (*(hash)->key_callbacks.release)((key));                              \ 
     64#define _WI_DICTIONARY_KEY_RELEASE(dictionary, key)                                                   \ 
     65        WI_STMT_START                                                                                                                  
     66                if((dictionary)->key_callbacks.release)                                                               \ 
     67                        (*(dictionary)->key_callbacks.release)((key));                                \ 
    6868        WI_STMT_END 
    6969 
    70 #define _WI_HASH_KEY_HASH(hash, key)                                                          \ 
    71         ((hash)->key_callbacks.hash                                                                           \ 
    72                 ? (*(hash)->key_callbacks.hash)((key))                                                \ 
     70#define _WI_DICTIONARY_KEY_HASH(dictionary, key)                                                      \ 
     71        ((dictionary)->key_callbacks.hash                                                                             \ 
     72                ? (*(dictionary)->key_callbacks.hash)((key))                                          \ 
    7373                : wi_hash_pointer((key))) 
    7474 
    75 #define _WI_HASH_KEY_IS_EQUAL(hash, key1, key2)                                               \ 
    76         (((hash)->key_callbacks.is_equal &&                                                           \ 
    77           (*(hash)->key_callbacks.is_equal)((key1), (key2))) ||                       \ 
    78          (!(hash)->key_callbacks.is_equal &&                                                  \ 
     75#define _WI_DICTIONARY_KEY_IS_EQUAL(dictionary, key1, key2)                                   \ 
     76        (((dictionary)->key_callbacks.is_equal &&                                                             \ 
     77          (*(dictionary)->key_callbacks.is_equal)((key1), (key2))) ||                 \ 
     78         (!(dictionary)->key_callbacks.is_equal &&                                                            \ 
    7979          (key1) == (key2))) 
    8080 
    81 #define _WI_HASH_VALUE_RETAIN(hash, value)                                                    \ 
    82         ((hash)->value_callbacks.retain                                                                       \ 
    83                 ? (*(hash)->value_callbacks.retain)((value))                          \ 
     81#define _WI_DICTIONARY_VALUE_RETAIN(dictionary, value)                                                \ 
     82        ((dictionary)->value_callbacks.retain                                                                 \ 
     83                ? (*(dictionary)->value_callbacks.retain)((value))                                    \ 
    8484                : (value)) 
    8585 
    86 #define _WI_HASH_VALUE_RELEASE(hash, value)                                                   \ 
    87         WI_STMT_START                                                                                                   
    88                 if((hash)->value_callbacks.release)                                                   \ 
    89                         (*(hash)->value_callbacks.release)((value));                  \ 
     86#define _WI_DICTIONARY_VALUE_RELEASE(dictionary, value)                                               \ 
     87        WI_STMT_START                                                                                                                  
     88                if((dictionary)->value_callbacks.release)                                                     \ 
     89                        (*(dictionary)->value_callbacks.release)((value));                            \ 
    9090        WI_STMT_END 
    9191 
    92 #define _WI_HASH_VALUE_IS_EQUAL(hash, value1, value2)                         \ 
    93         (((hash)->value_callbacks.is_equal &&                                                 \ 
    94           (*(hash)->value_callbacks.is_equal)((value1), (value2))) ||
    95          (!(hash)->value_callbacks.is_equal &&                                                        \ 
     92#define _WI_DICTIONARY_VALUE_IS_EQUAL(dictionary, value1, value2)                     \ 
     93        (((dictionary)->value_callbacks.is_equal &&                                                           \ 
     94          (*(dictionary)->value_callbacks.is_equal)((value1), (value2))) ||           \ 
     95         (!(dictionary)->value_callbacks.is_equal &&                                                  \ 
    9696          (value1) == (value2))) 
    9797 
    9898 
    99 struct _wi_hash_bucket { 
     99struct _wi_dictionary_bucket { 
    100100        void                                                            *key; 
    101101        void                                                            *data; 
    102102 
    103         struct _wi_hash_bucket                        *next, *link; 
     103        struct _wi_dictionary_bucket          *next, *link; 
    104104}; 
    105 typedef struct _wi_hash_bucket                 _wi_hash_bucket_t; 
    106  
    107  
    108 struct _wi_hash
     105typedef struct _wi_dictionary_bucket   _wi_dictionary_bucket_t; 
     106 
     107 
     108struct _wi_dictionary
    109109        wi_runtime_base_t                                       base; 
    110110         
    111         wi_hash_key_callbacks_t                               key_callbacks; 
    112         wi_hash_value_callbacks_t                     value_callbacks; 
    113  
    114         _wi_hash_bucket_t                                     **buckets; 
     111        wi_dictionary_key_callbacks_t         key_callbacks; 
     112        wi_dictionary_value_callbacks_t               value_callbacks; 
     113 
     114        _wi_dictionary_bucket_t                               **buckets; 
    115115        wi_uinteger_t                                           buckets_count; 
    116116        wi_uinteger_t                                           min_count; 
     
    119119        wi_rwlock_t                                                     *lock; 
    120120         
    121         _wi_hash_bucket_t                                     **bucket_chunks; 
     121        _wi_dictionary_bucket_t                               **bucket_chunks; 
    122122        wi_uinteger_t                                           bucket_chunks_count; 
    123123        wi_uinteger_t                                           bucket_chunks_offset; 
    124124 
    125         _wi_hash_bucket_t                                     *bucket_free_list; 
     125        _wi_dictionary_bucket_t                               *bucket_free_list; 
    126126}; 
    127127 
    128128 
    129 static void                                                             _wi_hash_dealloc(wi_runtime_instance_t *); 
    130 static wi_runtime_instance_t *                  _wi_hash_copy(wi_runtime_instance_t *); 
    131 static wi_boolean_t                                             _wi_hash_is_equal(wi_runtime_instance_t *, wi_runtime_instance_t *); 
    132 static wi_string_t *                                    _wi_hash_description(wi_runtime_instance_t *); 
    133 static wi_hash_code_t                                   _wi_hash_hash(wi_runtime_instance_t *); 
    134  
    135 static _wi_hash_bucket_t *                             _wi_enumerator_hash_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
    136  
    137 static void                                                             _wi_hash_resize(wi_hash_t *); 
    138  
    139 static _wi_hash_bucket_t *                             _wi_hash_bucket_create(wi_hash_t *); 
    140 static _wi_hash_bucket_t *                             _wi_hash_bucket_for_key(wi_hash_t *, void *, wi_uinteger_t); 
    141 static void                                                             _wi_hash_bucket_remove(wi_hash_t *, _wi_hash_bucket_t *); 
     129static void                                                             _wi_dictionary_dealloc(wi_runtime_instance_t *); 
     130static wi_runtime_instance_t *                  _wi_dictionary_copy(wi_runtime_instance_t *); 
     131static wi_boolean_t                                             _wi_dictionary_is_equal(wi_runtime_instance_t *, wi_runtime_instance_t *); 
     132static wi_string_t *                                    _wi_dictionary_description(wi_runtime_instance_t *); 
     133static wi_hash_code_t                                   _wi_dictionary_hash(wi_runtime_instance_t *); 
     134 
     135static _wi_dictionary_bucket_t *               _wi_enumerator_dictionary_enumerator(wi_runtime_instance_t *, wi_enumerator_context_t *); 
     136 
     137static void                                                             _wi_dictionary_resize(wi_dictionary_t *); 
     138 
     139static _wi_dictionary_bucket_t *               _wi_dictionary_bucket_create(wi_dictionary_t *); 
     140static _wi_dictionary_bucket_t *               _wi_dictionary_bucket_for_key(wi_dictionary_t *, void *, wi_uinteger_t); 
     141static void                                                             _wi_dictionary_bucket_remove(wi_dictionary_t *, _wi_dictionary_bucket_t *); 
    142142#ifdef HAVE_QSORT_R 
    143 static int                                                              _wi_hash_compare_buckets(void *, const void *, const void *); 
     143static int                                                              _wi_dictionary_compare_buckets(void *, const void *, const void *); 
    144144#else 
    145 static int                                                              _wi_hash_compare_buckets(const void *, const void *); 
     145static int                                                              _wi_dictionary_compare_buckets(const void *, const void *); 
    146146#endif 
    147147 
    148148 
    149 const wi_hash_key_callbacks_t                  wi_hash_default_key_callbacks = { 
     149const wi_dictionary_key_callbacks_t            wi_dictionary_default_key_callbacks = { 
    150150        wi_copy, 
    151151        wi_release, 
     
    155155}; 
    156156 
    157 const wi_hash_key_callbacks_t                  wi_hash_null_key_callbacks = { 
     157const wi_dictionary_key_callbacks_t            wi_dictionary_null_key_callbacks = { 
    158158        NULL, 
    159159        NULL, 
     
    163163}; 
    164164 
    165 const wi_hash_value_callbacks_t                        wi_hash_default_value_callbacks = { 
     165const wi_dictionary_value_callbacks_t  wi_dictionary_default_value_callbacks = { 
    166166        wi_retain, 
    167167        wi_release, 
     
    170170}; 
    171171 
    172 const wi_hash_value_callbacks_t                        wi_hash_null_value_callbacks = { 
     172const wi_dictionary_value_callbacks_t  wi_dictionary_null_value_callbacks = { 
    173173        NULL, 
    174174        NULL, 
     
    177177}; 
    178178 
    179 static wi_uinteger_t                                    _wi_hash_buckets_per_page; 
     179static wi_uinteger_t                                    _wi_dictionary_buckets_per_page; 
    180180 
    181181#ifndef HAVE_QSORT_R 
    182 static wi_lock_t                                                *_wi_hash_sort_lock; 
    183 static wi_compare_func_t                                *_wi_hash_sort_function; 
     182static wi_lock_t                                                *_wi_dictionary_sort_lock; 
     183static wi_compare_func_t                                *_wi_dictionary_sort_function; 
    184184#endif 
    185185 
    186 static wi_runtime_id_t                                  _wi_hash_runtime_id = WI_RUNTIME_ID_NULL; 
    187 static wi_runtime_class_t                               _wi_hash_runtime_class = { 
    188         "wi_hash_t", 
    189         _wi_hash_dealloc, 
    190         _wi_hash_copy, 
    191         _wi_hash_is_equal, 
    192         _wi_hash_description, 
    193         _wi_hash_hash 
     186static wi_runtime_id_t                                  _wi_dictionary_runtime_id = WI_RUNTIME_ID_NULL; 
     187static wi_runtime_class_t                               _wi_dictionary_runtime_class = { 
     188        "wi_dictionary_t", 
     189        _wi_dictionary_dealloc, 
     190        _wi_dictionary_copy, 
     191        _wi_dictionary_is_equal, 
     192        _wi_dictionary_description, 
     193        _wi_dictionary_hash 
    194194}; 
    195195 
    196196 
    197197 
    198 void wi_hash_register(void) { 
    199         _wi_hash_runtime_id = wi_runtime_register_class(&_wi_hash_runtime_class); 
    200 } 
    201  
    202  
    203  
    204 void wi_hash_initialize(void) { 
    205         _wi_hash_buckets_per_page = wi_page_size() / sizeof(_wi_hash_bucket_t); 
     198void wi_dictionary_register(void) { 
     199        _wi_dictionary_runtime_id = wi_runtime_register_class(&_wi_dictionary_runtime_class); 
     200} 
     201 
     202 
     203 
     204void wi_dictionary_initialize(void) { 
     205        _wi_dictionary_buckets_per_page = wi_page_size() / sizeof(_wi_dictionary_bucket_t); 
    206206 
    207207#ifndef HAVE_QSORT_R 
    208         _wi_hash_sort_lock = wi_lock_init(wi_lock_alloc()); 
     208        _wi_dictionary_sort_lock = wi_lock_init(wi_lock_alloc()); 
    209209#endif 
    210210} 
     
    214214#pragma mark - 
    215215 
    216 wi_runtime_id_t wi_hash_runtime_id(void) { 
    217         return _wi_hash_runtime_id; 
    218 } 
    219  
    220  
    221  
    222 #pragma mark - 
    223  
    224 wi_hash_t * wi_hash_with_data_and_keys(void *data0, void *key0, ...) { 
    225         wi_hash_t              *hash
    226         void                    *data, *key; 
    227         va_list                 ap; 
    228  
    229         hash = wi_hash_init_with_capacity(wi_hash_alloc(), 0); 
    230          
    231         wi_hash_set_data_for_key(hash, data0, key0); 
     216wi_runtime_id_t wi_dictionary_runtime_id(void) { 
     217        return _wi_dictionary_runtime_id; 
     218} 
     219 
     220 
     221 
     222#pragma mark - 
     223 
     224wi_dictionary_t * wi_dictionary_with_data_and_keys(void *data0, void *key0, ...) { 
     225        wi_dictionary_t                *dictionary
     226        void                           *data, *key; 
     227        va_list                        ap; 
     228 
     229        dictionary = wi_dictionary_init_with_capacity(wi_dictionary_alloc(), 0); 
     230         
     231        wi_dictionary_set_data_for_key(dictionary, data0, key0); 
    232232 
    233233        va_start(ap, key0); 
     
    235235                key = va_arg(ap, void *); 
    236236                 
    237                 wi_hash_set_data_for_key(hash, data, key);    
     237                wi_dictionary_set_data_for_key(dictionary, data, key);    
    238238        } 
    239239        va_end(ap); 
    240240         
    241         return wi_autorelease(hash); 
     241        return wi_autorelease(dictionary); 
    242242} 
    243243 
     
    246246#ifdef WI_LIBXML2 
    247247 
    248 wi_hash_t * wi_hash_with_plist_file(wi_string_t *path) { 
    249         return wi_autorelease(wi_hash_init_with_plist_file(wi_hash_alloc(), path)); 
     248wi_dictionary_t * wi_dictionary_with_plist_file(wi_string_t *path) { 
     249        return wi_autorelease(wi_dictionary_init_with_plist_file(wi_dictionary_alloc(), path)); 
    250250} 
    251251 
     
    256256#pragma mark - 
    257257 
    258 wi_hash_t * wi_hash_alloc(void) { 
    259         return wi_runtime_create_instance(_wi_hash_runtime_id, sizeof(wi_hash_t)); 
    260 
    261  
    262  
    263  
    264 wi_hash_t * wi_hash_init(wi_hash_t *hash) { 
    265         return wi_hash_init_with_capacity(hash, 0); 
    266 
    267  
    268  
    269  
    270 wi_hash_t * wi_hash_init_with_capacity(wi_hash_t *hash, wi_uinteger_t capacity) { 
    271         return wi_hash_init_with_capacity_and_callbacks(hash, capacity, wi_hash_default_key_callbacks, wi_hash_default_value_callbacks); 
    272 
    273  
    274  
    275  
    276 wi_hash_t * wi_hash_init_with_capacity_and_callbacks(wi_hash_t *hash, wi_uinteger_t capacity, wi_hash_key_callbacks_t key_callbacks, wi_hash_value_callbacks_t value_callbacks) { 
    277         hash->key_callbacks                     = key_callbacks; 
    278         hash->value_callbacks           = value_callbacks; 
    279         hash->bucket_chunks_offset      = _wi_hash_buckets_per_page; 
    280         hash->min_count                         = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_HASH_MIN_COUNT); 
    281         hash->buckets_count                     = hash->min_count; 
    282         hash->buckets                           = wi_malloc(hash->buckets_count * sizeof(_wi_hash_bucket_t *)); 
    283         hash->lock                                      = wi_rwlock_init(wi_rwlock_alloc()); 
    284          
    285         return hash; 
    286 
    287  
    288  
    289  
    290 wi_hash_t * wi_hash_init_with_data_and_keys(wi_hash_t *hash, ...) { 
     258wi_dictionary_t * wi_dictionary_alloc(void) { 
     259        return wi_runtime_create_instance(_wi_dictionary_runtime_id, sizeof(wi_dictionary_t)); 
     260
     261 
     262 
     263 
     264wi_dictionary_t * wi_dictionary_init(wi_dictionary_t *dictionary) { 
     265        return wi_dictionary_init_with_capacity(dictionary, 0); 
     266
     267 
     268 
     269 
     270wi_dictionary_t * wi_dictionary_init_with_capacity(wi_dictionary_t *dictionary, wi_uinteger_t capacity) { 
     271        return wi_dictionary_init_with_capacity_and_callbacks(dictionary, capacity, 
     272                wi_dictionary_default_key_callbacks, wi_dictionary_default_value_callbacks); 
     273
     274 
     275 
     276 
     277wi_dictionary_t * wi_dictionary_init_with_capacity_and_callbacks(wi_dictionary_t *dictionary, wi_uinteger_t capacity, wi_dictionary_key_callbacks_t key_callbacks, wi_dictionary_value_callbacks_t value_callbacks) { 
     278        dictionary->key_callbacks                       = key_callbacks; 
     279        dictionary->value_callbacks                     = value_callbacks; 
     280        dictionary->bucket_chunks_offset        = _wi_dictionary_buckets_per_page; 
     281        dictionary->min_count                           = WI_MAX(wi_exp2m1(wi_log2(capacity) + 1), _WI_DICTIONARY_MIN_COUNT); 
     282        dictionary->buckets_count                       = dictionary->min_count; 
     283        dictionary->buckets                                     = wi_malloc(dictionary->buckets_count * sizeof(_wi_dictionary_bucket_t *)); 
     284        dictionary->lock                                        = wi_rwlock_init(wi_rwlock_alloc()); 
     285         
     286        return dictionary; 
     287
     288 
     289 
     290 
     291wi_dictionary_t * wi_dictionary_init_with_data_and_keys(wi_dictionary_t *dictionary, ...) { 
    291292        void                    *data, *key; 
    292293        va_list                 ap; 
    293294 
    294         hash = wi_hash_init_with_capacity(hash, 0); 
    295  
    296         va_start(ap, hash); 
     295        dictionary = wi_dictionary_init_with_capacity(dictionary, 0); 
     296 
     297        va_start(ap, dictionary); 
    297298        while((data = va_arg(ap, void *))) { 
    298299                key = va_arg(ap, void *); 
    299300                 
    300                 wi_hash_set_data_for_key(hash, data, key);    
     301                wi_dictionary_set_data_for_key(dictionary, data, key);    
    301302        } 
    302303        va_end(ap); 
    303304         
    304         return hash
     305        return dictionary
    305306} 
    306307 
     
    309310#ifdef WI_LIBXML2 
    310311 
    311 wi_hash_t * wi_hash_init_with_plist_file(wi_hash_t *hash, wi_string_t *path) { 
     312wi_dictionary_t * wi_dictionary_init_with_plist_file(wi_dictionary_t *dictionary, wi_string_t *path) { 
    312313        wi_runtime_instance_t   *instance; 
    313314         
    314         wi_release(hash); 
     315        wi_release(dictionary); 
    315316         
    316317        instance = wi_plist_read_instance_from_file(path); 
     
    319320                return NULL; 
    320321         
    321         if(wi_runtime_id(instance) != wi_hash_runtime_id()) 
     322        if(wi_runtime_id(instance) != wi_dictionary_runtime_id()) 
    322323                return NULL; 
    323324         
     
    329330 
    330331 
    331 static wi_runtime_instance_t * _wi_hash_copy(wi_runtime_instance_t *instance) { 
    332         wi_hash_t                       *hash = instance, *hash_copy; 
    333         _wi_hash_bucket_t       *bucket; 
     332static wi_runtime_instance_t * _wi_dictionary_copy(wi_runtime_instance_t *instance) { 
     333        wi_dictionary_t                         *dictionary = instance, *dictionary_copy; 
     334        _wi_dictionary_bucket_t         *bucket; 
     335        wi_uinteger_t                           i; 
     336         
     337        dictionary_copy = wi_dictionary_init_with_capacity_and_callbacks(wi_dictionary_alloc(), dictionary->key_count, 
     338                dictionary->key_callbacks, dictionary->value_callbacks); 
     339         
     340        for(i = 0; i < dictionary->buckets_count; i++) { 
     341                for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) 
     342                        wi_dictionary_set_data_for_key(dictionary_copy, bucket->data, bucket->key); 
     343        } 
     344         
     345        return dictionary_copy; 
     346
     347 
     348 
     349 
     350static void _wi_dictionary_dealloc(wi_runtime_instance_t *instance) { 
     351        wi_dictionary_t         *dictionary = instance; 
    334352        wi_uinteger_t           i; 
    335          
    336         hash_copy = wi_hash_init_with_capacity_and_callbacks(wi_hash_alloc(), hash->key_count, hash->key_callbacks, hash->value_callbacks); 
    337          
    338         for(i = 0; i < hash->buckets_count; i++) { 
    339                 for(bucket = hash->buckets[i]; bucket; bucket = bucket->next) 
    340                         wi_hash_set_data_for_key(hash_copy, bucket->data, bucket->key); 
    341         } 
    342          
    343         return hash_copy; 
    344 
    345  
    346  
    347  
    348 static void _wi_hash_dealloc(wi_runtime_instance_t *instance) { 
    349         wi_hash_t               *hash = instance; 
    350         wi_uinteger_t   i; 
    351  
    352         wi_hash_remove_all_data(hash); 
    353  
    354         if(hash->bucket_chunks) { 
    355                 for(i = 0; i < hash->bucket_chunks_count; i++) 
    356                         wi_free(hash->bucket_chunks[i]); 
    357  
    358                 wi_free(hash->bucket_chunks); 
    359         } 
    360          
    361         wi_free(hash->buckets); 
    362  
    363         wi_release(hash->lock); 
    364 
    365  
    366  
    367  
    368 static wi_boolean_t _wi_hash_is_equal(wi_runtime_instance_t *instance1, wi_runtime_instance_t *instance2) { 
    369         wi_hash_t                       *hash1 = instance1; 
    370         wi_hash_t                       *hash2 = instance2; 
    371         _wi_hash_bucket_t       *bucket; 
    372         wi_uinteger_t           i; 
    373  
    374         if(hash1->key_count != hash2->key_count) 
     353 
     354        wi_dictionary_remove_all_data(dictionary); 
     355 
     356        if(dictionary->bucket_chunks) { 
     357                for(i = 0; i < dictionary->bucket_chunks_count; i++) 
     358                        wi_free(dictionary->bucket_chunks[i]); 
     359 
     360                wi_free(dictionary->bucket_chunks); 
     361        } 
     362         
     363        wi_free(dictionary->buckets); 
     364 
     365        wi_release(dictionary->lock); 
     366
     367 
     368 
     369 
     370static wi_boolean_t _wi_dictionary_is_equal(wi_runtime_instance_t *instance1, wi_runtime_instance_t *instance2) { 
     371        wi_dictionary_t                         *dictionary1 = instance1; 
     372        wi_dictionary_t                         *dictionary2 = instance2; 
     373        _wi_dictionary_bucket_t         *bucket; 
     374        wi_uinteger_t                           i; 
     375 
     376        if(dictionary1->key_count != dictionary2->key_count) 
    375377                return false; 
    376378         
    377         if(hash1->value_callbacks.is_equal != hash2->value_callbacks.is_equal) 
     379        if(dictionary1->value_callbacks.is_equal != dictionary2->value_callbacks.is_equal) 
    378380                return false; 
    379381         
    380         for(i = 0; i < hash1->buckets_count; i++) { 
    381                 for(bucket = hash1->buckets[i]; bucket; bucket = bucket->next) { 
    382                         if(!_WI_HASH_VALUE_IS_EQUAL(hash1, bucket->data, wi_hash_data_for_key(hash2, bucket->key))) { 
    383                                 wi_log_info(WI_STR("%@ %@ != %@"), bucket->key, bucket->data, wi_hash_data_for_key(hash2, bucket->key)); 
     382        for(i = 0; i < dictionary1->buckets_count; i++) { 
     383                for(bucket = dictionary1->buckets[i]; bucket; bucket = bucket->next) { 
     384                        if(!_WI_DICTIONARY_VALUE_IS_EQUAL(dictionary1, bucket->data, wi_dictionary_data_for_key(dictionary2, bucket->key))) 
    384385                                return false; 
    385                         } 
    386386                } 
    387387        } 
     
    392392 
    393393 
    394 static wi_string_t * _wi_hash_description(wi_runtime_instance_t *instance) { 
    395         wi_hash_t                      *hash = instance; 
    396         _wi_hash_bucket_t     *bucket; 
    397         wi_string_t                     *string, *key_description, *value_description; 
    398         wi_uinteger_t           i; 
     394static wi_string_t * _wi_dictionary_description(wi_runtime_instance_t *instance) { 
     395        wi_dictionary_t                                *dictionary = instance; 
     396        _wi_dictionary_bucket_t               *bucket; 
     397        wi_string_t                                    *string, *key_description, *value_description; 
     398        wi_uinteger_t                          i; 
    399399 
    400400        string = wi_string_with_format(WI_STR("<%@ %p>{count = %lu, values = (\n"), 
    401                 wi_runtime_class_name(hash), 
    402                 hash
    403                 hash->key_count); 
    404  
    405         for(i = 0; i < hash->buckets_count; i++) { 
    406                 for(bucket = hash->buckets[i]; bucket; bucket = bucket->next) { 
    407                         if(hash->key_callbacks.description) 
    408                                 key_description = (*hash->key_callbacks.description)(bucket->key); 
     401                wi_runtime_class_name(dictionary), 
     402                dictionary
     403                dictionary->key_count); 
     404 
     405        for(i = 0; i < dictionary->buckets_count; i++) { 
     406                for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) { 
     407                        if(dictionary->key_callbacks.description) 
     408                                key_description = (*dictionary->key_callbacks.description)(bucket->key); 
    409409                        else 
    410410                                key_description = wi_string_with_format(WI_STR("%p"), bucket->key); 
    411411 
    412                         if(hash->value_callbacks.description) 
    413                                 value_description = (*hash->value_callbacks.description)(bucket->data); 
     412                        if(dictionary->value_callbacks.description) 
     413                                value_description = (*dictionary->value_callbacks.description)(bucket->data); 
    414414                        else 
    415415                                value_description = wi_string_with_format(WI_STR("%p"), bucket->data); 
     
    426426 
    427427 
    428 static wi_hash_code_t _wi_hash_hash(wi_runtime_instance_t *instance) { 
    429         wi_hash_t              *hash = instance; 
    430          
    431         return hash->key_count; 
    432 } 
    433  
    434  
    435 #pragma mark - 
    436  
    437 void wi_hash_wrlock(wi_hash_t *hash) { 
    438         wi_rwlock_wrlock(hash->lock); 
    439 } 
    440  
    441  
    442  
    443 void wi_hash_rdlock(wi_hash_t *hash) { 
    444         wi_rwlock_rdlock(hash->lock); 
    445 } 
    446  
    447  
    448  
    449 void wi_hash_unlock(wi_hash_t *hash) { 
    450         wi_rwlock_unlock(hash->lock); 
    451 } 
    452  
    453  
    454  
    455 #pragma mark - 
    456  
    457 wi_uinteger_t wi_hash_count(wi_hash_t *hash) { 
    458         return hash->key_count; 
    459 } 
    460  
    461  
    462  
    463 wi_array_t * wi_hash_all_keys(wi_hash_t *hash) { 
    464         wi_array_t                              *array; 
    465         _wi_hash_bucket_t             *bucket; 
    466         wi_array_callbacks_t    callbacks; 
    467         wi_uinteger_t                   i; 
    468          
    469         callbacks.retain                = hash->key_callbacks.retain; 
    470         callbacks.release               = hash->key_callbacks.release; 
    471         callbacks.is_equal              = hash->key_callbacks.is_equal; 
    472         callbacks.description   = hash->key_callbacks.description; 
    473         array                                   = wi_array_init_with_capacity_and_callbacks(wi_array_alloc(), hash->key_count, callbacks); 
    474  
    475         for(i = 0; i < hash->buckets_count; i++) { 
    476                 for(bucket = hash->buckets[i]; bucket; bucket = bucket->next) 
     428static wi_hash_code_t _wi_dictionary_hash(wi_runtime_instance_t *instance) { 
     429        wi_dictionary_t                *dictionary = instance; 
     430         
     431        return dictionary->key_count; 
     432} 
     433 
     434 
     435#pragma mark - 
     436 
     437void wi_dictionary_wrlock(wi_dictionary_t *dictionary) { 
     438        wi_rwlock_wrlock(dictionary->lock); 
     439} 
     440 
     441 
     442 
     443void wi_dictionary_rdlock(wi_dictionary_t *dictionary) { 
     444        wi_rwlock_rdlock(dictionary->lock); 
     445} 
     446 
     447 
     448 
     449void wi_dictionary_unlock(wi_dictionary_t *dictionary) { 
     450        wi_rwlock_unlock(dictionary->lock); 
     451} 
     452 
     453 
     454 
     455#pragma mark - 
     456 
     457wi_uinteger_t wi_dictionary_count(wi_dictionary_t *dictionary) { 
     458        return dictionary->key_count; 
     459} 
     460 
     461 
     462 
     463wi_array_t * wi_dictionary_all_keys(wi_dictionary_t *dictionary) { 
     464        wi_array_t                                     *array; 
     465        _wi_dictionary_bucket_t               *bucket; 
     466        wi_array_callbacks_t           callbacks; 
     467        wi_uinteger_t                          i; 
     468         
     469        callbacks.retain                = dictionary->key_callbacks.retain; 
     470        callbacks.release               = dictionary->key_callbacks.release; 
     471        callbacks.is_equal              = dictionary->key_callbacks.is_equal; 
     472        callbacks.description   = dictionary->key_callbacks.description; 
     473        array                                   = wi_array_init_with_capacity_and_callbacks(wi_array_alloc(), dictionary->key_count, callbacks); 
     474 
     475        for(i = 0; i < dictionary->buckets_count; i++) { 
     476                for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) 
    477477                        wi_array_add_data(array, bucket->key); 
    478478        } 
     
    483483 
    484484 
    485 wi_array_t * wi_hash_all_values(wi_hash_t *hash) { 
    486         wi_array_t                              *array; 
    487         _wi_hash_bucket_t             *bucket; 
    488         wi_array_callbacks_t    callbacks; 
    489         wi_uinteger_t                   i; 
    490          
    491         callbacks.retain                = hash->value_callbacks.retain; 
    492         callbacks.release               = hash->value_callbacks.release; 
    493         callbacks.is_equal              = hash->value_callbacks.is_equal; 
    494         callbacks.description   = hash->value_callbacks.description; 
    495         array                                   = wi_array_init_with_capacity_and_callbacks(wi_array_alloc(), hash->key_count, callbacks); 
    496  
    497         for(i = 0; i < hash->buckets_count; i++) { 
    498                 for(bucket = hash->buckets[i]; bucket; bucket = bucket->next) 
     485wi_array_t * wi_dictionary_all_values(wi_dictionary_t *dictionary) { 
     486        wi_array_t                                     *array; 
     487        _wi_dictionary_bucket_t               *bucket; 
     488        wi_array_callbacks_t           callbacks; 
     489        wi_uinteger_t                          i; 
     490         
     491        callbacks.retain                = dictionary->value_callbacks.retain; 
     492        callbacks.release               = dictionary->value_callbacks.release; 
     493        callbacks.is_equal              = dictionary->value_callbacks.is_equal; 
     494        callbacks.description   = dictionary->value_callbacks.description; 
     495        array                                   = wi_array_init_with_capacity_and_callbacks(wi_array_alloc(), dictionary->key_count, callbacks); 
     496 
     497        for(i = 0; i < dictionary->buckets_count; i++) { 
     498                for(bucket = dictionary->buckets[i]; bucket; bucket = bucket->next) 
    499499                        wi_array_add_data(array, bucket->data); 
    500500        } 
     
    505505 
    506506 
    507 wi_array_t * wi_hash_keys_sorted_by_value(wi_hash_t *hash, wi_compare_func_t *compare) { 
    508         wi_array_t                              *array, *buckets; 
    509         _wi_hash_bucket_t             *bucket; 
    510         wi_array_callbacks_t    callbacks; 
    511         void                                    **data; 
    512         wi_uinteger_t                   i; 
    513          
    514         if(hash->key_count == 0) 
     507wi_array_t * wi_dictionary_keys_sorted_by_value(wi_dictionary_t *dictionary, wi_compare_func_t *compare) { 
     508        wi_array_t                                     *array, *buckets; 
     509        _wi_dictionary_bucket_t               *bucket; 
     510        wi_array_callbacks_t           callbacks; 
     511      &nbs