/src/wrappers/glib/partially-implemented/g_hash_table.e
Specman e | 517 lines | 169 code | 109 blank | 239 comment | 5 complexity | 2188b1c9988478f8eaf1abaf909c8be6 MD5 | raw file
1indexing 2 description: "Hash Tables associations between keys and values so that given a key the value can be found quickly." 3 copyright: "(C) 2005 Paolo Redaelli " 4 license: "LGPL v2 or later" 5 date: "$Date:$" 6 revision: "$REvision:$" 7 8class G_HASH_TABLE [VALUE->SHARED_C_STRUCT, KEY->COMPARABLE_SHARED_C_STRUCT] 9 -- A G_HASH_TABLE provides associations between keys and values 10 -- which is optimized so that given a key, the associated value can 11 -- be found very quickly. 12 13 -- TODO: provide non-fast features, i.e. features that compare 14 -- keys by their content, not by their address. 15 16 -- TODO: Eiffellize the following documentation. 17 18 -- Note: the following note, valid for the manual memory management 19 -- of the C world is not true anymore in an Eiffel program, if a 20 -- caching wrapper factory is used... "Note that neither keys nor 21 -- values are copied when inserted into the G_HASH_TABLE, so they 22 -- must exist for the lifetime of the G_HASH_TABLE. This means that 23 -- the use of static strings is OK, but temporary strings 24 -- (i.e. those created in buffers and those returned by GTK+ 25 -- widgets) should be copied with g_strdup() before being 26 -- inserted". 27 28 -- If keys or values are dynamically allocated, you must be careful 29 -- to ensure that they are freed when they are removed from the 30 -- G_HASH_TABLE, and also when they are overwritten by new 31 -- insertions into the G_HASH_TABLE. It is also not advisable to 32 -- mix static strings and dynamically-allocated strings in a 33 -- GHashTable, because it then becomes difficult to determine 34 -- whether the string should be freed. 35 36 -- To create a GHashTable, use g_hash_table_new(). 37 38 -- To insert a key and value into a GHashTable, use 39 -- g_hash_table_insert(). 40 41 -- To lookup a value corresponding to a given key, use 42 -- g_hash_table_lookup() and g_hash_table_lookup_extended(). 43 44 -- To remove a key and value, use g_hash_table_remove(). 45 46 -- To call a function for each key and value pair use 47 -- g_hash_table_foreach(). 48 49 -- To destroy a GHashTable use g_hash_table_destroy(). 50 51inherit 52 WRAPPER_DICTIONARY [VALUE, KEY] 53 redefine 54 dispose 55 end 56 57insert 58 G_HASH_TABLE_EXTERNALS 59 60creation from_external 61 62feature {} -- Creation 63 from_external (a_pointer: POINTER; a_factory: WRAPPER_FACTORY[VALUE]) is 64 require factory_not_void: a_factory/=Void 65 do 66 factory := a_factory 67 from_external_pointer(a_pointer) 68 end 69 70 71 with_factory (a_factory: WRAPPER_FACTORY[VALUE]) is 72 require factory_not_void: a_factory/=Void 73 do 74 factory := a_factory 75 from_external_pointer 76 (g_hash_table_new 77 (default_pointer, -- Using g_direct_hash as hash function; 78 default_pointer, -- Direct comparison of address, like using g_direct_equal as key equal function but with no overhead 79 ),a_factory) 80 81 -- g_hash_table_new creates a new GHashTable. 82 83 -- hash_func : a function to create a hash value from a 84 -- key. Hash values are used to determine where keys are 85 -- stored within the GHashTable data structure. The 86 -- g_direct_hash(), g_int_hash() and g_str_hash() functions 87 -- are provided for some common types of keys. If hash_func 88 -- is NULL, g_direct_hash() is used. 89 90 -- key_equal_func : a function to check two keys for 91 -- equality. This is used when looking up keys in the 92 -- GHashTable. The g_direct_equal(), g_int_equal() and 93 -- g_str_equal() functions are provided for the most common 94 -- types of keys. If key_equal_func is NULL, keys are 95 -- compared directly in a similar fashion to 96 -- g_direct_equal(), but without the overhead of a function 97 -- call. 98 end 99 100 -- TODO: GHashTable* g_hash_table_new_full (GHashFunc hash_func, 101 -- GEqualFunc key_equal_func, GDestroyNotify key_destroy_func, 102 -- GDestroyNotify value_destroy_func); 103 104 -- Creates a new GHashTable like g_hash_table_new() and allows to 105 -- specify functions to free the memory allocated for the key and 106 -- value that get called when removing the entry from the 107 -- GHashTable. 108 109 -- hash_func : a function to create a hash value from a key. 110 -- key_equal_func : a function to check two keys for equality. 111 -- key_destroy_func : a function to free the memory allocated for the key used when removing the entry from the GHashTable or NULL if you don't want to supply such a function. 112 -- value_destroy_func : a function to free the memory allocated for the value used when removing the entry from the GHashTable or NULL if you don't want to supply such a function. 113 -- Returns : a new GHashTable. 114 115 -- TODO: feature {} -- Implement manifest generic creation: 116 -- manifest_make (needed_capacity: INTEGER) is 117 -- -- Manifest creation of a dictionary. 118 -- do 119 -- allocate 120 -- end 121 122feature {ANY} -- Basic access: 123 has (a_key: KEY): BOOLEAN is 124 local orig_key_ptr, value_ptr: POINTER 125 do 126 Result:=(g_hash_table_lookup_extended 127 (handle, a_key.handle, orig_key_ptr, value_ptr)).to_boolean 128 end 129 130 at (a_key: KEY): VALUE is 131 -- Looks up `a_key' in a GHashTable. 132 local ptr: POINTER 133 do 134 ptr := g_hash_table_lookup (handle, a_key.handle) 135 if ptr.is_not_null then 136 Result:=factory.wrapper(ptr) 137 end 138 end 139 140 reference_at (a_key: KEY): VALUE is 141 -- The value associated to `a_key'. Void if there is no value 142 -- for `a_key'. 143 local ptr: POINTER 144 do 145 ptr := g_hash_table_lookup (handle, a_key.handle) 146 if ptr.is_not_null then 147 Result:=factory.wrapper(ptr) 148 end 149 150 -- Looks up a key in the GHashTable, returning the original 151 -- key and the associated value and a gboolean which is TRUE 152 -- if the key was found. This is useful if you need to free 153 -- the memory allocated for the original key, for example 154 -- before calling `remove'. 155 156 -- `a_key': the key to look up. 157 158 -- orig_key : returns the original key. 159 -- value : returns the value associated with the key. 160 -- Returns : TRUE if the key was found in the GHashTable. 161 -- gboolean g_hash_table_lookup_extended (GHashTable 162 -- *hash_table, gconstpointer lookup_key, gpointer *orig_key, 163 -- gpointer *value); 164 end 165 166 fast_has (k: KEY): BOOLEAN is 167 do 168 debug 169 print_no_fast_notice 170 print(fast_fallback_notice) 171 end 172 Result:=has(k) 173 end 174 175 fast_at (k: KEY): VALUE is 176 do 177 debug 178 print_no_fast_notice 179 print(fast_fallback_notice) 180 end 181 Result:=at(k) 182 end 183 184 fast_reference_at (k: KEY): VALUE is 185 do 186 debug 187 print_no_fast_notice 188 print(fast_fallback_notice) 189 end 190 Result:=reference_at(k) 191 end 192 193feature {ANY} 194 put (a_value: VALUE; a_key: KEY) is 195 -- Inserts a new key and value into a GHashTable. 196 197 -- If the key already exists in the GHashTable its current 198 -- value is replaced with the new value. If you supplied a 199 -- value_destroy_func when creating the GHashTable, the old 200 -- value is freed using that function. If you supplied a 201 -- key_destroy_func when creating the GHashTable, the passed 202 -- key is freed using that function. 203 204 -- hash_table : a GHashTable. 205 -- key : a key to insert. 206 -- value : the value to associate with the key. 207 require else value_not_void: a_value /= Void 208 do 209 g_hash_table_insert (handle, a_key.handle, a_value.handle) 210 end 211 212 fast_put (v: VALUE; k: KEY) is 213 require else value_not_void: v /= Void 214 do 215 debug 216 print_no_fast_notice 217 print(fast_fallback_notice) 218 end 219 put(v,k) 220 end 221 222 add (v: VALUE; k: KEY) is 223 require else value_not_void: v /= Void 224 do 225 put(v,k) 226 end 227 228feature {ANY} -- Removing: 229 remove (a_key: KEY) is 230 -- Removes a key and its associated value from a GHashTable. 231 232 -- `is_successful' will be True if the key was found and 233 -- removed from the GHashTable. 234 do 235 -- TODO: Translate/implement this C-ism: If the GHashTable 236 -- was created using `make_full', the key and value are freed 237 -- using the supplied destroy functions, otherwise you have 238 -- to make sure that any dynamically allocated values are 239 -- freed yourself. 240 is_successful := (g_hash_table_remove (handle, a_key.handle)).to_boolean 241 end 242 243 fast_remove (k: KEY) is 244 do 245 debug 246 print_no_fast_notice 247 print(fast_fallback_notice) 248 end 249 remove(k) 250 end 251 252 clear_count is 253 do 254 g_hash_table_remove_all(handle) 255 end 256 257 clear_count_and_capacity is 258 do 259 dispose 260 make 261 end 262 263 capacity: INTEGER is 264 do 265 Result:=g_hash_table_size(handle) 266 end 267 268feature {ANY} -- To provide iterating facilities: 269 item (index: INTEGER): VALUE is 270 do 271 ensure then implemented: False 272 end 273 274 key (index: INTEGER): KEY is 275 do 276 ensure then implemented: False 277 end 278 279 get_new_iterator_on_keys: ITERATOR[KEY] is 280 do 281 ensure then implemented: False 282 end 283 284feature {ANY} -- Other features: 285 internal_key (k: KEY): KEY is 286 do 287 ensure then implemented: False 288 end 289 290 -- GHashFunc () 291 292 -- guint (*GHashFunc) (gconstpointer key); 293 294 -- Specifies the type of the hash function which is passed to 295 -- g_hash_table_new() when a GHashTable is created. 296 297 -- The function is passed a key and should return a guint hash 298 -- value. The functions g_direct_hash(), g_int_hash() and 299 -- g_str_hash() provide hash functions which can be used when the 300 -- key is a gpointer, gint, and gchar* respectively. 301 302 -- FIXME: Need more here. The hash values should be evenly 303 -- distributed over a fairly large range? The modulus is taken with 304 -- the hash table size (a prime number) to find the 'bucket' to 305 -- place each key into. The function should also be very fast, 306 -- since it is called for each key lookup. key : a key. Returns : 307 -- the hash value corresponding to the key. GEqualFunc () 308 309 -- gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b); 310 311 -- Specifies the type of a function used to test two values for 312 -- equality. The function should return TRUE if both values are 313 -- equal and FALSE otherwise. 314 315 -- a : a value. 316 -- b : a value to compare with. 317 -- Returns : TRUE if a = b; FALSE otherwise. 318 -- g_hash_table_insert () 319 320feature 321 322 count: INTEGER is 323 -- the number of elements (key/value pairs) contained in the 324 -- GHashTable. 325 do 326 Result := g_hash_table_size (handle) 327 end 328 329 -- g_hash_table_foreach () 330 331 -- void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, 332 -- gpointer user_data); 333 334 -- Calls the given function for each of the key/value pairs in the 335 -- GHashTable. The function is passed the key and value of each 336 -- pair, and the given user_data parameter. The hash table may not 337 -- be modified while iterating over it (you can't add/remove 338 -- items). To remove all items matching a predicate, use 339 -- g_hash_table_foreach_remove(). 340 341 -- hash_table : a GHashTable. 342 -- func : the function to call for each key/value pair. 343 -- user_data : user data to pass to the function. 344 345 -- g_hash_table_find () 346 347 -- gpointer g_hash_table_find (GHashTable *hash_table, GHRFunc 348 -- predicate, gpointer user_data); 349 350 -- Calls the given function for key/value pairs in the GHashTable 351 -- until predicate returns TRUE. The function is passed the key and 352 -- value of each pair, and the given user_data parameter. The hash 353 -- table may not be modified while iterating over it (you can't 354 -- add/remove items). 355 356 -- hash_table : a GHashTable. 357 -- predicate : function to test the key/value pairs for a certain property. 358 -- user_data : user data to pass to the function. 359 -- Returns : The value of the first key/value pair is returned, for which func evaluates to TRUE. If no pair with the requested property is found, NULL is returned. 360 361 362 -- GHFunc () 363 364 -- void (*GHFunc) (gpointer key, gpointer value, gpointer 365 -- user_data); 366 367 -- Specifies the type of the function passed to g_hash_table_foreach(). It is called with each key/value pair, together with the user_data parameter which is passed to g_hash_table_foreach(). 368 -- key : a key. 369 -- value : the value corresponding to the key. 370 -- user_data : user data passed to g_hash_table_foreach(). 371 372 is_successful: BOOLEAN 373 374 -- g_hash_table_foreach_remove () 375 376 -- guint g_hash_table_foreach_remove (GHashTable *hash_table, 377 -- GHRFunc func, 378 -- gpointer user_data); 379 380 -- Calls the given function for each key/value pair in the GHashTable. If the function returns TRUE, then the key/value pair is removed from the GHashTable. If you supplied key or value destroy functions when creating the GHashTable, they are used to free the memory allocated for the removed keys and values. 381 382 -- hash_table : a GHashTable. 383 -- func : the function to call for each key/value pair. 384 -- user_data : user data to pass to the function. 385 -- Returns : the number of key/value pairs removed. 386 -- g_hash_table_foreach_steal () 387 388 -- guint g_hash_table_foreach_steal (GHashTable *hash_table, 389 -- GHRFunc func, 390 -- gpointer user_data); 391 392 -- Calls the given function for each key/value pair in the GHashTable. If the function returns TRUE, then the key/value pair is removed from the GHashTable, but no key or value destroy functions are called. 393 394 -- hash_table : a GHashTable. 395 -- func : the function to call for each key/value pair. 396 -- user_data : user data to pass to the function. 397 -- Returns : the number of key/value pairs removed. 398 -- GHRFunc () 399 400 -- gboolean (*GHRFunc) (gpointer key, 401 -- gpointer value, 402 -- gpointer user_data); 403 404 -- Specifies the type of the function passed to g_hash_table_foreach_remove(). It is called with each key/value pair, together with the user_data parameter passed to g_hash_table_foreach_remove(). It should return TRUE if the key/value pair should be removed from the GHashTable. 405 -- key : a key. 406 -- value : the value associated with the key. 407 -- user_data : user data passed to g_hash_table_remove(). 408 -- Returns : TRUE if the key/value pair should be removed from the GHashTable. 409 410 dispose is 411 -- Destroys the GHashTable. If keys and/or values are 412 -- dynamically allocated, you should either free them first 413 -- or create the GHashTable using g_hash_table_new_full(). In 414 -- the latter case the destroy functions you supplied will be 415 -- called on all keys and values before destroying the 416 -- GHashTable. 417 do 418 g_hash_table_destroy (handle) 419 end 420 421feature {} 422 -- g_direct_equal () 423 424 -- Compares two gpointer arguments and returns TRUE if they 425 -- are equal. It can be passed to `g_hash_table_new' as the 426 -- key_equal_func parameter, when using pointers as keys in a 427 -- GHashTable. 428 429 -- g_direct_hash () 430 431 -- guint g_direct_hash (gconstpointer v); 432 433 -- Converts a gpointer to a hash value. It can be passed to g_hash_table_new() as the hash_func parameter, when using pointers as keys in a GHashTable. 434 435 -- v : a gpointer key 436 -- Returns : a hash value corresponding to the key. 437 -- g_int_equal () 438 439 -- gboolean g_int_equal (gconstpointer v1, 440 -- gconstpointer v2); 441 442 -- Compares the two gint values being pointed to and returns TRUE if they are equal. It can be passed to g_hash_table_new() as the key_equal_func parameter, when using pointers to integers as keys in a GHashTable. 443 444 -- v1 : a pointer to a gint key. 445 -- v2 : a pointer to a gint key to compare with v1. 446 -- Returns : TRUE if the two keys match. 447 -- g_int_hash () 448 449 -- guint g_int_hash (gconstpointer v); 450 451 -- Converts a pointer to a gint to a hash value. It can be passed to g_hash_table_new() as the hash_func parameter, when using pointers to integers values as keys in a GHashTable. 452 453 -- v : a pointer to a gint key 454 -- Returns : a hash value corresponding to the key. 455 -- g_str_equal () 456 457 -- gboolean g_str_equal (gconstpointer v1, 458 -- gconstpointer v2); 459 460 -- Compares two strings and returns TRUE if they are equal. It can be passed to g_hash_table_new() as the key_equal_func parameter, when using strings as keys in a GHashTable. 461 462 -- v1 : a key. 463 -- v2 : a key to compare with v1. 464 -- Returns : TRUE if the two keys match. 465 -- g_str_hash () 466 467 -- guint g_str_hash (gconstpointer v); 468 469 -- Converts a string to a hash value. It can be passed to g_hash_table_new() as the hash_func parameter, when using strings as keys in a GHashTable. 470 471 -- v : a string key. 472 -- Returns : a hash value corresponding to the key. 473feature -- size 474 475 struct_size: INTEGER is 476 external "C inline use <glib.h>" 477 alias "sizeof(GHashTable)" 478 end 479 480feature {} -- Low level implementation 481 print_no_fast_notice is 482 once 483 print(no_fast_notice) 484 end 485 486 no_fast_notice: STRING is 487 "Original C GHashTable implementation does not offer functions equivalent to `fast_has,' `fast_at', `fast_reference_at', `fast_put' and `fast_remove'. An eventual implementation of those features would require to manipulate directly GHashTable data-structure, skipping the Glib abstraction. Paolo 2007-07-15%N" 488 489 fast_fallback_notice: STRING is 490 "Fast_[has|at|reference_at|put|remove] feature not available. Falling back to non-fast features.%N" 491 492 493 -- steal (a_key: KEY): VALUE is 494 -- Removes a key and its associated value from a GHashTable 495 -- without calling the key and value destroy functions. 496 497 -- `is_successful' is True if the key was found and removed 498 -- from the GHashTable. 499 -- require key_not_void: a_key /= Void 500 501 -- do is_successful := (g_hash_table_steal (handle, 502 -- a_key.handle)).to_boolean end 503 504 -- replace (a_key: KEY; a_value: VALUE) is Inserts a new key and 505 -- value into a GHashTable similar to g_hash_table_insert(). The 506 -- difference is that if the key already exists in the 507 -- GHashTable, it gets replaced by the new key. If you supplied 508 -- a value_destroy_func when creating the GHashTable, the old 509 -- value is freed using that function. If you supplied a 510 -- key_destroy_func when creating the GHashTable, the old key is 511 -- freed using that function. hash_table : a GHashTable. key : 512 -- a key to insert. value : the value to associate with the 513 -- key. require key_not_void: a_key /= Void value_not_void: 514 -- a_value /= Void do g_hash_table_replace (handle, 515 -- a_key.handle, a_value.handle) end 516 517end