PageRenderTime 28ms CodeModel.GetById 17ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 1ms

/src/wrappers/glib/partially-implemented/g_tree.e

http://github.com/tybor/Liberty
Specman e | 448 lines | 216 code | 73 blank | 159 comment | 6 complexity | bc5895ad0e6ac833a605ba298c9f27af MD5 | raw file
  1indexing
  2	description: "Balanced Binary Trees, a sorted collection of key/value pairs optimized for searching and traversing in order."
  3	copyright: "[
  4					Copyright (C) 2005,2007 Paolo Redaelli, Glib team
  5					
  6					This library is free software; you can redistribute it and/or
  7					modify it under the terms of the GNU Lesser General Public License
  8					as published by the Free Software Foundation; either version 2.1 of
  9					the License, or (at your option) any later version.
 10					
 11					This library is distributed in the hopeOA that it will be useful, but
 12					WITHOUT ANY WARRANTY; without even the implied warranty of
 13					MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14					Lesser General Public License for more details.
 15
 16					You should have received a copy of the GNU Lesser General Public
 17					License along with this library; if not, write to the Free Software
 18					Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19					02110-1301 USA
 20			]"
 21	license: "LGPL v2 or later"
 22
 23class G_TREE [VALUE->SHARED_C_STRUCT, KEY->COMPARABLE_SHARED_C_STRUCT]
 24	-- A sorted collection of key/value pairs optimized for searching
 25	-- and traversing in order.
 26
 27inherit
 28	DICTIONARY[VALUE, KEY]
 29		undefine
 30			is_equal, copy -- using the definition given by SHARED_C_STRUCT
 31		redefine
 32			get_new_iterator_on_items,
 33			manifest_make,
 34			do_all, for_all, exists
 35		end
 36
 37	SHARED_C_STRUCT redefine dispose end
 38	
 39insert
 40	G_TREE_EXTERNALS
 41		--	GLIB_TYPE_CONVERSION_MACROS -- Temporary
 42	
 43creation  with_comparer, from_external_pointer
 44
 45feature {} -- Creation
 46	make (a_key_factory: CACHING_FACTORY[KEY]; a_value_factory: CACHING_FACTORY[VALUE]) is
 47			-- Creates a new G_TREE; comparison is made using KEY's 
 48			-- `compare' feature.
 49		require
 50			key_factory_not_void: a_key_factory/=Void
 51			value_factory_not_void: a_value_factory/=Void
 52		do
 53			key_factory   := a_key_factory
 54			value_factory := a_value_factory
 55			create comparator.make(agent {KEY}.compare)
 56			from_external_pointer(g_tree_new_with_data
 57										 (comparator.callback_address,
 58										  comparator.to_pointer))
 59		end
 60	
 61	with_comparer (a_comparison_function: FUNCTION[ANY,TUPLE[KEY,KEY],INTEGER];
 62						a_key_factory: CACHING_FACTORY[KEY]; a_value_factory: CACHING_FACTORY[VALUE]) is
 63			-- Creates a new GTree.
 64		require
 65			comparison_function_not_void: a_comparison_function /= Void
 66			key_factory_not_void: a_key_factory/=Void
 67			value_factory_not_void: a_value_factory/=Void
 68		do
 69			create comparator.make (a_comparison_function)
 70			from_external_pointer(g_tree_new_with_data
 71										 (comparator.callback_address,
 72										  comparator.to_pointer))
 73		end
 74
 75	-- TODO: if necessary g_tree_new_full ()
 76	
 77	-- GTree* g_tree_new_full (GCompareDataFunc key_compare_func,
 78	-- gpointer key_compare_data, GDestroyNotify key_destroy_func,
 79	-- GDestroyNotify value_destroy_func);
 80	
 81	-- Creates a new GTree like g_tree_new() and allows to specify
 82	-- functions to free the memory allocated for the key and value
 83	-- that get called when removing the entry from the GTree.
 84
 85	-- key_compare_func : 	qsort()-style comparison function.
 86	-- key_compare_data : 	data to pass to comparison function.
 87	-- key_destroy_func : 	a function to free the memory allocated for the key used when removing the entry from the GTree or NULL if you don't want to supply such a function.
 88	-- value_destroy_func : 	a function to free the memory allocated for the value used when removing the entry from the GTree or NULL if you don't want to supply such a function.
 89	-- Returns : 	a new GTree.
 90
 91feature {ANY} -- Basic access:
 92
 93	has (a_key: KEY): BOOLEAN is
 94			-- Is there a value currently associated with `a_key'?
 95
 96			-- See also `fast_has', `at'.
 97		do
 98			if (g_tree_lookup(handle,a_key.handle)).is_not_null
 99			then Result:=True
100			end
101		end
102
103	at (a_key: KEY): VALUE is
104			-- The value associated to `a_key'.
105
106			-- See also `fast_at', `reference_at', `has'.
107		local p: POINTER
108		do
109			p:=g_tree_lookup(handle, a_key.handle)
110			check require_has_key_implies_result_pointer_not_null:
111				p.is_not_null 
112			end
113			Result:=value_factory.wrapper(p)
114		end
115
116	reference_at (a_key: KEY): VALUE is
117			-- the value corresponding to `a_key'. Since a GTree is
118			-- automatically balanced as key/value pairs are added, key
119			-- lookup is very fast.
120		
121			-- Void if `a_key' was not found.
122		local p: POINTER; r: WRAPPER_RETRIEVER[VALUE]
123		do
124			p:=g_tree_lookup(handle, a_key.handle)
125			if p.is_not_null then
126				Result:=value_wrapper.wrapper(p)
127			end
128		end
129
130	fast_has (a_key: KEY): BOOLEAN is
131			-- Is there a value currently associated with `a_key'?
132			-- Using basic `=' for comparison.
133			--
134			-- See also `has', `at', `fast_at'.
135		do
136			debug print_no_fast_notice; print (fast_fallback_notice) end
137			Result:=has(a_key)
138		end
139
140	fast_at (a_key: KEY): VALUE is
141			-- Return the value associated to key `k' using basic `=' for comparison.
142			--
143			-- See also `at', `reference_at', `fast_reference_at'.
144		do
145			debug print_no_fast_notice; print (fast_fallback_notice) end
146			Result:=at(a_key)
147		end
148
149	fast_reference_at (a_key: KEY): VALUE is
150			-- Same work as `reference_at', but basic `=' is used for comparison.
151			--
152			-- See also `reference_at', `at', `has'.
153		do
154			debug print_no_fast_notice; print (fast_fallback_notice) end
155			Result:=reference_at(a_key)
156		end
157
158feature {ANY}
159	put (a_value: VALUE; a_key: KEY) is
160			-- Change some existing entry or `add' the new one. If an entry with `a_key' is not yet in the dictionary,
161			-- enter it with `a_value'. Otherwise overwrite the item associated with `a_key'.
162			-- 
163			-- The tree is automatically 'balanced' as new key/value
164			-- pairs are added, so that the distance from the root to
165			-- every leaf is as small as possible.
166		require else value_not_void: a_value/=Void
167		do
168			-- TODO: Eiffelize this: If you supplied a value_destroy_func
169			-- when creating the GTree, the old value is freed using that
170			-- function. If you supplied a key_destroy_func when creating
171			-- the GTree, the passed key is freed using that function.
172			g_tree_insert(handle, a_key.handle, a_value.handle)
173		end
174
175	fast_put (a_value: VALUE; a_key: KEY) is
176			-- Same job as `put', but uses basic `=' for comparison.
177			--
178			-- See also `put', `add'.
179		do
180			debug print_no_fast_notice; print (fast_fallback_notice) end
181			put(a_value,a_key)
182		end
183
184	add (a_value: VALUE; a_key: KEY) is
185			-- To add a new entry `k' with its associated value `v'.
186			-- Actually, this is equivalent to call `put', but it may run a little bit faster.
187			--
188			-- See also `put', `fast_put'.
189		do
190			debug print_add_fallback end
191			put(a_value,a_key)
192		end
193
194feature {ANY} -- Removing:
195	remove (a_key: KEY) is
196			-- Remove entry `a_key' (which may exist or not before this call).
197			-- As the `remove' procedure actually uses `is_equal', you may consider to use `fast_remove' for expanded
198			-- objects as well while trying to get the very best performances.
199			--
200			-- See also `fast_remove', `clear_count'.
201		local a_result: INTEGER
202		do
203			a_result:=g_tree_steal(handle,a_key.handle)
204			-- Note: g_tree_steal removes a key and its associated value
205			-- from a GTree without calling the key and value destroy
206			-- functions.
207
208			-- a_result is True(1) if the key was found (prior to 2.8,
209			-- this function returned nothing)
210
211			-- TODO: see if the following informations have some
212			-- relevance for Eiffel. We could use g_tree_remove in case
213			-- of particular cases of memory handling. Infact using
214			-- g_tree_remove the following applies: If the GTree was
215			-- created using g_tree_new_full(), the key and value are
216			-- freed using the supplied destroy functions, otherwise you
217			-- have to make sure that any dynamically allocated values
218			-- are freed yourself. If the key does not exist in the
219			-- GTree, the function does nothing.
220		end
221
222	fast_remove (a_key: KEY) is
223			-- Same job as `remove', but uses basic `=' for comparison.
224			--
225			-- See also `remove', `clear_count'.
226		do
227			debug print_no_fast_notice; print (fast_fallback_notice) end
228			remove (a_key)
229		end
230
231	clear_count is
232			-- Discard all items (`is_empty' is True after that call). The internal `capacity' is not changed
233			-- by this call.
234			--
235			-- See also `clear_count_and_capacity', `remove'.
236		do
237			not_yet_implemented
238		end
239
240	clear_count_and_capacity is
241			-- Discard all items (`is_empty' is True after that call). The internal `capacity' may also be
242			-- reduced after this call.
243			--
244			-- See also `clear_count', `remove'.
245		do
246			dispose -- and reallocate
247			from_external_pointer(g_tree_new_with_data
248										 (comparator.callback_address, comparator.to_pointer))
249		end
250
251	capacity: INTEGER is
252			-- Approximation of the actual internal storage `capacity'. The `capacity' will grow automatically
253			-- when needed (i.e. `capacity' is not a limit for the number of values stored). Also note that
254			-- the `capacity' value may not be always accurate depending of the implementation (anyway, this
255			-- `capacity' value is at least equals to `count').
256		do
257			-- Note: implemented to be equal to count
258			Result:=count
259		end
260
261
262feature -- counting
263	count: INTEGER_32 is
264		do
265			Result:=g_tree_nnodes(handle)
266		end
267
268feature {ANY} -- To provide iterating facilities:
269	item (index: INTEGER): VALUE is
270		do
271			not_yet_implemented
272		end
273
274	key (index: INTEGER): KEY is
275		do
276			not_yet_implemented
277		end
278
279	get_new_iterator_on_items: ITERATOR[VALUE] is
280		do
281			not_yet_implemented
282		end
283
284	get_new_iterator_on_keys: ITERATOR[KEY] is
285		do
286			not_yet_implemented
287		end
288
289feature {ANY} -- Agents based features:
290	do_all (action: ROUTINE[TUPLE[VALUE, KEY]]) is
291			-- Apply `action' to every [VALUE, KEY] associations of `Current'.
292			--
293			-- See also `for_all', `exist'.
294		do
295			not_yet_implemented
296		end
297
298	for_all (test: PREDICATE[TUPLE[VALUE, KEY]]): BOOLEAN is
299			-- Do all [VALUE, KEY] associations satisfy `test'?
300			--
301			-- See also `do_all', `exist'.
302		-- local callback: G_TRAVERSE_CALLBACK
303		do
304			not_yet_implemented
305			-- create callback.make a_test)
306			-- g_tree_foreach (handle, callback.low_level_callback, $callback)
307		end
308
309	exists (test: PREDICATE[TUPLE[VALUE, KEY]]): BOOLEAN is
310		do
311			not_yet_implemented
312		end
313
314feature {ANY} -- Other features:
315	internal_key (a_key: KEY): KEY is
316			-- Retrieve the internal key object which correspond to the existing
317			-- entry `a_key' (the one memorized into the `Current' dictionary).
318			--
319			-- See also `has', `fast_has'.
320		do
321			not_yet_implemented
322		end
323
324feature {} -- Implement manifest generic creation:
325	manifest_make (needed_capacity: INTEGER) is
326			-- Manifest creation of a dictionary.
327		do
328			not_yet_implemented
329		end
330
331feature
332	height: INTEGER is
333			-- The height of a G_TREE.
334		
335			-- If the G_TREE contains no nodes, the height is 0. If the
336			-- G_TREE contains only one root node the height is 1. If the
337			-- root node has children the height is 2, etc.
338		do
339			Result:=g_tree_height(handle)
340		end
341
342	-- g_tree_search ()
343
344	-- gpointer    g_tree_search                   (GTree *tree,
345	--                                              GCompareFunc search_func,
346	--                                              gconstpointer user_data);
347	
348	-- Searches a GTree using search_func.
349
350	-- The search_func is called with a pointer to the key of a key/value pair in the tree, and the passed in user_data. If search_func returns 0 for a key/value pair, then g_tree_search_func() will return the value of that pair. If search_func returns -1, searching will proceed among the key/value pairs that have a smaller key; if search_func returns 1, searching will proceed among the key/value pairs that have a larger key.
351
352	-- tree : 	a GTree.
353	-- search_func : 	a function used to search the GTree.
354	-- user_data : 	the data passed as the second argument to the search_func function.
355	-- Returns : 	the value corresponding to the found key, or NULL if the key was not found.
356
357	dispose is
358			-- Destroys the GTree.
359
360			-- TODO: The following should held only for C; check
361			-- it... "If keys and/or values are dynamically allocated,
362			-- you should either free them first or create the GTree
363			-- using g_tree_new_full(). In the latter case the destroy
364			-- functions you supplied will be called on all keys and
365			-- values before destroying the GTree"
366		do
367			g_tree_destroy(handle)
368			handle:=default_pointer
369		end
370
371	compare (a_value, another_value: VALUE): INTEGER is
372			-- The comparison function of two values. The function should
373			-- return a negative integer if the first value comes before
374			-- the second, 0 if they are equal, or a positive integer if
375			-- the first value comes after the second.
376		obsolete "Work in progress on callbacks"
377		do
378			
379		end
380	
381feature {} -- Low level implementation
382	comparator: G_COMPARE_DATA_CALLBACK [KEY]
383			-- The object containing the callback that will be called by C
384
385	key_factory: WRAPPER_FACTORY[KEY]
386
387	value_factory: WRAPPER_FACTORY[VALUE]
388
389	print_no_fast_notice is
390		once
391			print(no_fast_notice)
392		end
393
394	no_fast_notice: STRING is
395		"Original C GTree 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 GTree data-structure, skipping the Glib abstraction. Paolo 2007-07-15%N"
396
397	fast_fallback_notice: STRING is
398		"Fast_[has|at|reference_at|put] feature not available. Falling back to non-fast features.%N"
399
400	print_add_fallback is
401		once
402			print (print_add_fallback_notice)
403		end
404	
405	print_add_fallback_notice: STRING is
406		"Original C GTree implementation does not offer a function equivalent to `add'. Falling back to `put' feature. Paolo 2007-07-15%N"
407
408feature {} -- Unwrapped code
409	-- TODO: it is necessary to wrap g_tree_lookup_extended ?
410	
411	-- gboolean g_tree_lookup_extended (GTree *tree, gconstpointer
412	-- lookup_key, gpointer *orig_key, gpointer *value);
413
414	-- Looks up a key in the GTree, returning the original key and the
415	-- associated value and a gboolean which is TRUE if the key was
416	-- found. This is useful if you need to free the memory allocated
417	-- for the original key, for example before calling
418	-- g_tree_remove().
419	
420	-- tree : 	a GTree.
421	-- lookup_key : 	the key to look up.
422	-- orig_key : 	returns the original key.
423	-- value : 	returns the value associated with the key.
424	-- Returns : 	TRUE if the key was found in the GTree.
425
426	-- AFAIK wrapping replace is just not necessary in Eiffel
427	
428	-- 		replace (a_key: KEY; a_value: VALUE) is
429	-- 			-- Inserts `a_key' and `a_value' into a GTree similar to
430	-- 			-- `insert_value'. The difference is that if `a_key' already
431	-- 			-- exists in the GTree, it gets replaced by the new key. If
432	-- 			-- you supplied a value_destroy_func when creating the GTree,
433	-- 			-- the old value is freed using that function. If you
434	-- 			-- supplied a key_destroy_func when creating the GTree, the
435	-- 			-- old key is freed using that function.
436
437	-- 			-- The tree is automatically 'balanced' as new key/value
438	-- 			-- pairs are added, so that the distance from the root to
439	-- 			-- every leaf is as small as possible.
440	-- 		require
441	-- 			key_not_void: a_key/=Void
442	-- 			value_not_void: a_value/=Void
443	-- 		do
444	-- 			g_tree_replace(handle,a_key.handle,a_value.handle)
445	-- 		end
446
447end
448