2 * Copyright © 2008 by Eric Bishop <eric@gargoyle-router.com>
4 * This work 'as-is' we provide.
5 * No warranty, express or implied.
8 * Liability for damages denied.
10 * Permission is granted hereby,
11 * to copy, share, and modify.
14 * On this notice these rights rely.
18 * Note that unlike other portions of Gargoyle this code
19 * does not fall under the GPL, but the rather whimsical
20 * 'Poetic License' above.
22 * Basically, this library contains a bunch of utilities
23 * that I find useful. I'm sure other libraries exist
24 * that are just as good or better, but I like these tools
25 * because I personally wrote them, so I know their quirks.
26 * (i.e. I know where the bodies are buried). I want to
27 * make sure that I can re-use these utilities for whatever
28 * code I may want to write in the future be it
29 * proprietary or open-source, so I've put them under
30 * a very, very permissive license.
32 * If you find this code useful, use it. If not, don't.
33 * I really don't care.
39 #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
40 #define free(foo) kfree(foo)
41 #define printf(format,args...) printk(format,##args)
44 static inline char *kernel_strdup(const char *str
);
45 static inline char *kernel_strdup(const char *str
)
50 tmp
= kmalloc(s
, GFP_ATOMIC
);
57 #define strdup kernel_strdup
63 /* tree_map structs / prototypes */
64 typedef struct long_tree_map_node
70 struct long_tree_map_node
* left
;
71 struct long_tree_map_node
* right
;
77 unsigned long num_elements
;
84 unsigned char store_keys
;
85 unsigned long num_elements
;
91 /* long map functions */
92 long_map
* initialize_long_map(void);
93 void* get_long_map_element(long_map
* map
, unsigned long key
);
94 void* get_smallest_long_map_element(long_map
* map
, unsigned long* smallest_key
);
95 void* get_largest_long_map_element(long_map
* map
, unsigned long* largest_key
);
96 void* remove_smallest_long_map_element(long_map
* map
, unsigned long* smallest_key
);
97 void* remove_largest_long_map_element(long_map
* map
, unsigned long* largest_key
);
98 void* set_long_map_element(long_map
* map
, unsigned long key
, void* value
);
99 void* remove_long_map_element(long_map
* map
, unsigned long key
);
100 unsigned long* get_sorted_long_map_keys(long_map
* map
, unsigned long* num_keys_returned
);
101 void** get_sorted_long_map_values(long_map
* map
, unsigned long* num_values_returned
);
102 void** destroy_long_map(long_map
* map
, int destruction_type
, unsigned long* num_destroyed
);
103 void apply_to_every_long_map_value(long_map
* map
, void (*apply_func
)(unsigned long key
, void* value
));
105 /* string map functions */
106 string_map
* initialize_string_map(unsigned char store_keys
);
107 void* get_string_map_element(string_map
* map
, const char* key
);
108 void* set_string_map_element(string_map
* map
, const char* key
, void* value
);
109 void* remove_string_map_element(string_map
* map
, const char* key
);
110 char** get_string_map_keys(string_map
* map
, unsigned long* num_keys_returned
);
111 void** get_string_map_values(string_map
* map
, unsigned long* num_values_returned
);
112 void** destroy_string_map(string_map
* map
, int destruction_type
, unsigned long* num_destroyed
);
113 void apply_to_every_string_map_value(string_map
* map
, void (*apply_func
)(char* key
, void* value
));
117 * three different ways to deal with values when data structure is destroyed
119 #define DESTROY_MODE_RETURN_VALUES 20
120 #define DESTROY_MODE_FREE_VALUES 21
121 #define DESTROY_MODE_IGNORE_VALUES 22
125 * for convenience & backwards compatibility alias _string_map_ functions to
126 * _map_ functions since string map is used more often than long map
128 #define initialize_map initialize_string_map
129 #define set_map_element set_string_map_element
130 #define get_map_element get_string_map_element
131 #define remove_map_element remove_string_map_element
132 #define get_map_keys get_string_map_keys
133 #define get_map_values get_string_map_values
134 #define destroy_map destroy_string_map
137 /* internal utility structures/ functions */
138 typedef struct stack_node_struct
140 long_map_node
** node_ptr
;
141 signed char direction
;
142 struct stack_node_struct
* previous
;
145 static void free_stack(stack_node
* stack
);
146 static void** destroy_long_map_values(long_map
* map
, int destruction_type
, unsigned long* num_destroyed
);
147 static void apply_to_every_long_map_node(long_map_node
* node
, void (*apply_func
)(unsigned long key
, void* value
));
148 static void apply_to_every_string_map_node(long_map_node
* node
, unsigned char has_key
, void (*apply_func
)(char* key
, void* value
));
149 static void get_sorted_node_keys(long_map_node
* node
, unsigned long* key_list
, unsigned long* next_key_index
, int depth
);
150 static void get_sorted_node_values(long_map_node
* node
, void** value_list
, unsigned long* next_value_index
, int depth
);
151 static signed char rebalance (long_map_node
** n
, signed char direction
, signed char update_op
);
152 static void rotate_right (long_map_node
** parent
);
153 static void rotate_left (long_map_node
** parent
);
155 /* internal for string map */
160 } string_map_key_value
;
161 static unsigned long sdbm_string_hash(const char *key
);
166 /***************************************************
168 ***************************************************/
170 void print_list(stack_node *l);
172 void print_list(stack_node *l)
176 printf(" list key = %ld, dir=%d, \n", (*(l->node_ptr))->key, l->direction);
177 print_list(l->previous);
181 /******************************************************
183 *******************************************************/
188 /***************************************************
189 * string_map function definitions
190 ***************************************************/
192 string_map
* initialize_string_map(unsigned char store_keys
)
194 string_map
* map
= (string_map
*)malloc(sizeof(string_map
));
197 map
->store_keys
= store_keys
;
199 map
->lm
.num_elements
= 0;
200 map
->num_elements
= map
->lm
.num_elements
;
205 void* get_string_map_element(string_map
* map
, const char* key
)
207 unsigned long hashed_key
= sdbm_string_hash(key
);
208 void* return_value
= get_long_map_element( &(map
->lm
), hashed_key
);
209 if(return_value
!= NULL
&& map
->store_keys
)
211 string_map_key_value
* r
= (string_map_key_value
*)return_value
;
212 return_value
= r
->value
;
214 map
->num_elements
= map
->lm
.num_elements
;
218 void* set_string_map_element(string_map
* map
, const char* key
, void* value
)
220 unsigned long hashed_key
= sdbm_string_hash(key
);
221 void* return_value
= NULL
;
224 string_map_key_value
* kv
= (string_map_key_value
*)malloc(sizeof(string_map_key_value
));
225 if(kv
== NULL
) /* deal with malloc failure */
229 kv
->key
= strdup(key
);
230 if(kv
->key
== NULL
) /* deal with malloc failure */
236 return_value
= set_long_map_element( &(map
->lm
), hashed_key
, kv
);
237 if(return_value
!= NULL
)
239 string_map_key_value
* r
= (string_map_key_value
*)return_value
;
240 return_value
= r
->value
;
247 return_value
= set_long_map_element( &(map
->lm
), hashed_key
, value
);
249 map
->num_elements
= map
->lm
.num_elements
;
253 void* remove_string_map_element(string_map
* map
, const char* key
)
255 unsigned long hashed_key
= sdbm_string_hash(key
);
256 void* return_value
= remove_long_map_element( &(map
->lm
), hashed_key
);
258 if(return_value
!= NULL
&& map
->store_keys
)
260 string_map_key_value
* r
= (string_map_key_value
*)return_value
;
261 return_value
= r
->value
;
265 map
->num_elements
= map
->lm
.num_elements
;
269 char** get_string_map_keys(string_map
* map
, unsigned long* num_keys_returned
)
272 str_keys
= (char**)malloc((map
->num_elements
+1)*sizeof(char*));
273 if(str_keys
== NULL
) /* deal with malloc failure */
278 *num_keys_returned
= 0;
279 if(map
->store_keys
&& map
->num_elements
> 0)
281 unsigned long list_length
;
282 void** long_values
= get_sorted_long_map_values( &(map
->lm
), &list_length
);
283 unsigned long key_index
;
284 /*list_length will be 0 on malloc failure in get_sorted_long_map_values, so this code shouldn't seg fault if that happens */
285 for(key_index
= 0; key_index
< list_length
; key_index
++)
287 str_keys
[key_index
] = strdup( ((string_map_key_value
*)(long_values
[key_index
]))->key
);
288 if(str_keys
[key_index
] == NULL
) /* deal with malloc failure */
290 //just return the incomplete list (hey, it's null terminated...)
294 *num_keys_returned
= *num_keys_returned
+ 1;
296 str_keys
[list_length
] = NULL
;
303 void** get_string_map_values(string_map
* map
, unsigned long* num_values_returned
)
305 void** values
= NULL
;
308 values
= get_sorted_long_map_values ( &(map
->lm
), num_values_returned
);
314 void** destroy_string_map(string_map
* map
, int destruction_type
, unsigned long* num_destroyed
)
316 void** return_values
= NULL
;
321 void** kvs
= destroy_long_map_values( &(map
->lm
), DESTROY_MODE_RETURN_VALUES
, num_destroyed
);
322 unsigned long kv_index
= 0;
323 for(kv_index
=0; kv_index
< *num_destroyed
; kv_index
++)
325 string_map_key_value
* kv
= (string_map_key_value
*)kvs
[kv_index
];
326 void* value
= kv
->value
;
330 if(destruction_type
== DESTROY_MODE_FREE_VALUES
)
334 if(destruction_type
== DESTROY_MODE_RETURN_VALUES
)
336 kvs
[kv_index
] = value
;
339 if(destruction_type
== DESTROY_MODE_RETURN_VALUES
)
350 return_values
= destroy_long_map_values( &(map
->lm
), destruction_type
, num_destroyed
);
354 return return_values
;
360 /***************************************************
361 * long_map function definitions
362 ***************************************************/
364 long_map
* initialize_long_map(void)
366 long_map
* map
= (long_map
*)malloc(sizeof(long_map
));
367 if(map
!= NULL
) /* test for malloc failure */
370 map
->num_elements
= 0;
375 void* get_long_map_element(long_map
* map
, unsigned long key
)
379 if(map
->root
!= NULL
)
381 long_map_node
* parent_node
= map
->root
;
382 long_map_node
* next_node
;
383 while( key
!= parent_node
->key
&& (next_node
= (long_map_node
*)(key
< parent_node
->key
? parent_node
->left
: parent_node
->right
)) != NULL
)
385 parent_node
= next_node
;
387 if(parent_node
->key
== key
)
389 value
= parent_node
->value
;
395 void* get_smallest_long_map_element(long_map
* map
, unsigned long* smallest_key
)
398 if(map
->root
!= NULL
)
400 long_map_node
* next_node
= map
->root
;
401 while( next_node
->left
!= NULL
)
403 next_node
= next_node
->left
;
405 value
= next_node
->value
;
406 *smallest_key
= next_node
->key
;
411 void* get_largest_long_map_element(long_map
* map
, unsigned long* largest_key
)
414 if(map
->root
!= NULL
)
416 long_map_node
* next_node
= map
->root
;
417 while( next_node
->right
!= NULL
)
419 next_node
= next_node
->right
;
421 value
= next_node
->value
;
422 *largest_key
= next_node
->key
;
427 void* remove_smallest_long_map_element(long_map
* map
, unsigned long* smallest_key
)
429 get_smallest_long_map_element(map
, smallest_key
);
430 return remove_long_map_element(map
, *smallest_key
);
433 void* remove_largest_long_map_element(long_map
* map
, unsigned long* largest_key
)
435 get_largest_long_map_element(map
, largest_key
);
436 return remove_long_map_element(map
, *largest_key
);
440 /* if replacement performed, returns replaced value, otherwise null */
441 void* set_long_map_element(long_map
* map
, unsigned long key
, void* value
)
443 stack_node
* parent_list
= NULL
;
444 void* old_value
= NULL
;
445 int old_value_found
= 0;
447 long_map_node
* parent_node
;
448 long_map_node
* next_node
;
449 stack_node
* next_parent
;
450 stack_node
* previous_parent
;
451 signed char new_balance
;
454 long_map_node
* new_node
= (long_map_node
*)malloc(sizeof(long_map_node
));
459 new_node
->value
= value
;
461 new_node
->left
= NULL
;
462 new_node
->right
= NULL
;
463 new_node
->balance
= 0;
467 if(map
->root
== NULL
)
469 map
->root
= new_node
;
473 parent_node
= map
->root
;
475 next_parent
= (stack_node
*)malloc(sizeof(stack_node
));
476 if(next_parent
== NULL
) /* deal with malloc failure */
479 return NULL
; /* won't insert but won't seg fault */
481 next_parent
->node_ptr
= &(map
->root
);
482 next_parent
->previous
= parent_list
;
483 parent_list
= next_parent
;
485 while( key
!= parent_node
->key
&& (next_node
= (key
< parent_node
->key
? parent_node
->left
: parent_node
->right
) ) != NULL
)
487 next_parent
= (stack_node
*)malloc(sizeof(stack_node
));
488 if(next_parent
== NULL
) /* deal with malloc failure */
490 /* free previous stack nodes to prevent memory leak */
491 free_stack(parent_list
);
495 next_parent
->node_ptr
= key
< parent_node
->key
? &(parent_node
->left
) : &(parent_node
->right
);
496 next_parent
->previous
= parent_list
;
497 next_parent
->previous
->direction
= key
< parent_node
->key
? -1 : 1;
498 parent_list
= next_parent
;
500 parent_node
= next_node
;
504 if(key
== parent_node
->key
)
506 old_value
= parent_node
->value
;
508 parent_node
->value
= value
;
510 /* we merely replaced a node, no need to rebalance */
514 if(key
< parent_node
->key
)
516 parent_node
->left
= (void*)new_node
;
517 parent_list
->direction
= -1;
521 parent_node
->right
= (void*)new_node
;
522 parent_list
->direction
= 1;
526 /* we inserted a node, rebalance */
527 previous_parent
= parent_list
;
528 new_balance
= 1; /* initial value is not used, but must not be 0 for initial loop condition */
531 while(previous_parent
!= NULL
&& new_balance
!= 0)
533 new_balance
= rebalance(previous_parent
->node_ptr
, previous_parent
->direction
, 1);
534 previous_parent
= previous_parent
->previous
;
539 free_stack(parent_list
);
541 if(old_value_found
== 0)
543 map
->num_elements
= map
->num_elements
+ 1;
550 void* remove_long_map_element(long_map
* map
, unsigned long key
)
555 long_map_node
* root_node
= map
->root
;
556 stack_node
* parent_list
= NULL
;
559 long_map_node
* remove_parent
;
560 long_map_node
* remove_node
;
561 long_map_node
* next_node
;
563 long_map_node
* replacement
;
564 long_map_node
* replacement_parent
;
565 long_map_node
* replacement_next
;
567 stack_node
* next_parent
;
568 stack_node
* previous_parent
;
569 stack_node
* replacement_stack_node
;
572 signed char new_balance
;
576 if(root_node
!= NULL
)
578 remove_parent
= root_node
;
579 remove_node
= key
< remove_parent
->key
? remove_parent
->left
: remove_parent
->right
;
581 if(remove_node
!= NULL
&& key
!= remove_parent
->key
)
583 next_parent
= (stack_node
*)malloc(sizeof(stack_node
));
584 if(next_parent
== NULL
) /* deal with malloc failure */
588 next_parent
->node_ptr
= &(map
->root
);
589 next_parent
->previous
= parent_list
;
590 parent_list
= next_parent
;
591 while( key
!= remove_node
->key
&& (next_node
= (key
< remove_node
->key
? remove_node
->left
: remove_node
->right
)) != NULL
)
593 next_parent
= (stack_node
*)malloc(sizeof(stack_node
));
594 if(next_parent
== NULL
) /* deal with malloc failure */
596 /* free previous stack nodes to prevent memory leak */
597 free_stack(parent_list
);
600 next_parent
->node_ptr
= key
< remove_parent
->key
? &(remove_parent
->left
) : &(remove_parent
->right
);
601 next_parent
->previous
= parent_list
;
602 next_parent
->previous
->direction
= key
< remove_parent
->key
? -1 : 1;
603 parent_list
= next_parent
;
606 remove_parent
= remove_node
;
607 remove_node
= next_node
;
609 parent_list
->direction
= key
< remove_parent
-> key
? -1 : 1;
613 remove_node
= remove_parent
;
617 if(key
== remove_node
->key
)
620 /* find replacement for node we are deleting */
621 if( remove_node
->right
== NULL
)
623 replacement
= remove_node
->left
;
625 else if( remove_node
->right
->left
== NULL
)
628 replacement
= remove_node
->right
;
629 replacement
->left
= remove_node
->left
;
630 replacement
->balance
= remove_node
->balance
;
632 /* put pointer to replacement node into list for balance update */
633 replacement_stack_node
= (stack_node
*)malloc(sizeof(stack_node
));
634 if(replacement_stack_node
== NULL
) /* deal with malloc failure */
636 /* free previous stack nodes to prevent memory leak */
637 free_stack(parent_list
);
640 replacement_stack_node
->previous
= parent_list
;
641 replacement_stack_node
->direction
= 1; /* replacement is from right */
642 if(remove_node
== remove_parent
) /* special case for root node */
644 replacement_stack_node
->node_ptr
= &(map
->root
);
648 replacement_stack_node
->node_ptr
= key
< remove_parent
-> key
? &(remove_parent
->left
) : &(remove_parent
->right
);
650 parent_list
= replacement_stack_node
;
655 /* put pointer to replacement node into list for balance update */
656 replacement_stack_node
= (stack_node
*)malloc(sizeof(stack_node
));
657 if(replacement_stack_node
== NULL
) /* deal with malloc failure */
659 /* free previous stack nodes to prevent memory leak */
660 free_stack(parent_list
);
664 replacement_stack_node
->previous
= parent_list
;
665 replacement_stack_node
->direction
= 1; /* we always look for replacement on right */
666 if(remove_node
== remove_parent
) /* special case for root node */
668 replacement_stack_node
->node_ptr
= &(map
->root
);
672 replacement_stack_node
->node_ptr
= key
< remove_parent
-> key
? &(remove_parent
->left
) : &(remove_parent
->right
);
675 parent_list
= replacement_stack_node
;
679 * put pointer to replacement node->right into list for balance update
680 * this node will have to be updated with the proper pointer
681 * after we have identified the replacement
683 replacement_stack_node
= (stack_node
*)malloc(sizeof(stack_node
));
684 if(replacement_stack_node
== NULL
) /* deal with malloc failure */
686 /* free previous stack nodes to prevent memory leak */
687 free_stack(parent_list
);
691 replacement_stack_node
->previous
= parent_list
;
692 replacement_stack_node
->direction
= -1; /* we always look for replacement to left of this node */
693 parent_list
= replacement_stack_node
;
695 /* find smallest node on right (large) side of tree */
696 replacement_parent
= remove_node
->right
;
697 replacement
= replacement_parent
->left
;
699 while((replacement_next
= replacement
->left
) != NULL
)
701 next_parent
= (stack_node
*)malloc(sizeof(stack_node
));
702 if(next_parent
== NULL
) /* deal with malloc failure */
704 /* free previous stack nodes to prevent memory leak */
705 free_stack(parent_list
);
709 next_parent
->node_ptr
= &(replacement_parent
->left
);
710 next_parent
->previous
= parent_list
;
711 next_parent
->direction
= -1; /* we always go left */
712 parent_list
= next_parent
;
714 replacement_parent
= replacement
;
715 replacement
= replacement_next
;
719 replacement_parent
->left
= replacement
->right
;
721 replacement
->left
= remove_node
->left
;
722 replacement
->right
= remove_node
->right
;
723 replacement
->balance
= remove_node
->balance
;
724 replacement_stack_node
->node_ptr
= &(replacement
->right
);
727 /* insert replacement at proper location in tree */
728 if(remove_node
== remove_parent
)
730 map
->root
= replacement
;
734 remove_parent
->left
= remove_node
== remove_parent
->left
? replacement
: remove_parent
->left
;
735 remove_parent
->right
= remove_node
== remove_parent
->right
? replacement
: remove_parent
->right
;
740 previous_parent
= parent_list
;
742 while(previous_parent
!= NULL
&& new_balance
== 0)
744 new_balance
= rebalance(previous_parent
->node_ptr
, previous_parent
->direction
, -1);
745 previous_parent
= previous_parent
->previous
;
752 * since we found a value to remove, decrease number of elements in map
753 * set return value to the deleted node's value and free the node
755 map
->num_elements
= map
->num_elements
- 1;
756 value
= remove_node
->value
;
761 free_stack(parent_list
);
767 /* note: returned keys are dynamically allocated, you need to free them! */
768 unsigned long* get_sorted_long_map_keys(long_map
* map
, unsigned long* num_keys_returned
)
770 unsigned long* key_list
= (unsigned long*)malloc((map
->num_elements
)*sizeof(unsigned long));
771 unsigned long next_key_index
;
774 *num_keys_returned
= 0;
778 get_sorted_node_keys(map
->root
, key_list
, &next_key_index
, 0);
780 *num_keys_returned
= map
->num_elements
;
786 void** get_sorted_long_map_values(long_map
* map
, unsigned long* num_values_returned
)
788 void** value_list
= (void**)malloc((map
->num_elements
+1)*sizeof(void*));
789 unsigned long next_value_index
;
791 if(value_list
== NULL
)
793 *num_values_returned
= 0;
796 next_value_index
= 0;
797 get_sorted_node_values(map
->root
, value_list
, &next_value_index
, 0);
798 value_list
[map
->num_elements
] = NULL
; /* since we're dealing with pointers make list null terminated */
800 *num_values_returned
= map
->num_elements
;
807 void** destroy_long_map(long_map
* map
, int destruction_type
, unsigned long* num_destroyed
)
809 void** return_values
= destroy_long_map_values(map
, destruction_type
, num_destroyed
);
811 return return_values
;
816 void apply_to_every_long_map_value(long_map
* map
, void (*apply_func
)(unsigned long key
, void* value
))
818 apply_to_every_long_map_node(map
->root
, apply_func
);
820 void apply_to_every_string_map_value(string_map
* map
, void (*apply_func
)(char* key
, void* value
))
822 apply_to_every_string_map_node( (map
->lm
).root
, map
->store_keys
, apply_func
);
826 /***************************************************
827 * internal utility function definitions
828 ***************************************************/
829 static void free_stack(stack_node
* stack
)
833 stack_node
* prev_node
= stack
;
834 stack
= prev_node
->previous
;
840 static void** destroy_long_map_values(long_map
* map
, int destruction_type
, unsigned long* num_destroyed
)
842 void** return_values
= NULL
;
843 unsigned long return_index
= 0;
847 if(destruction_type
== DESTROY_MODE_RETURN_VALUES
)
849 return_values
= (void**)malloc((map
->num_elements
+1)*sizeof(void*));
850 if(return_values
== NULL
) /* deal with malloc failure */
852 destruction_type
= DESTROY_MODE_IGNORE_VALUES
; /* could cause memory leak, but there's no other way to be sure we won't seg fault */
856 return_values
[map
->num_elements
] = NULL
;
859 while(map
->num_elements
> 0)
861 unsigned long smallest_key
;
862 void* removed_value
= remove_smallest_long_map_element(map
, &smallest_key
);
863 if(destruction_type
== DESTROY_MODE_RETURN_VALUES
)
865 return_values
[return_index
] = removed_value
;
867 if(destruction_type
== DESTROY_MODE_FREE_VALUES
)
872 *num_destroyed
= *num_destroyed
+ 1;
874 return return_values
;
877 static void apply_to_every_long_map_node(long_map_node
* node
, void (*apply_func
)(unsigned long key
, void* value
))
881 apply_to_every_long_map_node(node
->left
, apply_func
);
883 apply_func(node
->key
, node
->value
);
885 apply_to_every_long_map_node(node
->right
, apply_func
);
888 static void apply_to_every_string_map_node(long_map_node
* node
, unsigned char has_key
, void (*apply_func
)(char* key
, void* value
))
892 apply_to_every_string_map_node(node
->left
, has_key
, apply_func
);
896 string_map_key_value
* kv
= (string_map_key_value
*)(node
->value
);
897 apply_func(kv
->key
, kv
->value
);
901 apply_func(NULL
, node
->value
);
903 apply_to_every_string_map_node(node
->right
, has_key
, apply_func
);
909 static void get_sorted_node_keys(long_map_node
* node
, unsigned long* key_list
, unsigned long* next_key_index
, int depth
)
913 get_sorted_node_keys(node
->left
, key_list
, next_key_index
, depth
+1);
915 key_list
[ *next_key_index
] = node
->key
;
918 get_sorted_node_keys(node
->right
, key_list
, next_key_index
, depth
+1);
922 static void get_sorted_node_values(long_map_node
* node
, void** value_list
, unsigned long* next_value_index
, int depth
)
926 get_sorted_node_values(node
->left
, value_list
, next_value_index
, depth
+1);
928 value_list
[ *next_value_index
] = node
->value
;
929 (*next_value_index
)++;
931 get_sorted_node_values(node
->right
, value_list
, next_value_index
, depth
+1);
938 * direction = -1 indicates left subtree updated, direction = 1 for right subtree
939 * update_op = -1 indicates delete node, update_op = 1 for insert node
941 static signed char rebalance (long_map_node
** n
, signed char direction
, signed char update_op
)
944 printf( "original: key = %ld, balance = %d, update_op=%d, direction=%d\n", (*n)->key, (*n)->balance, update_op, direction);
947 (*n
)->balance
= (*n
)->balance
+ (update_op
*direction
);
949 if( (*n
)->balance
< -1)
951 if((*n
)->left
->balance
< 0)
954 (*n
)->right
->balance
= 0;
957 else if((*n
)->left
->balance
== 0)
960 (*n
)->right
->balance
= -1;
963 else if((*n
)->left
->balance
> 0)
965 rotate_left( &((*n
)->left
) );
968 if( (*n)->balance < 0 )
970 (*n)->left->balance = 0;
971 (*n)->right->balance = 1;
973 else if( (*n)->balance == 0 )
975 (*n)->left->balance = 0;
976 (*n)->right->balance = 0;
978 else if( (*n)->balance > 0 )
980 (*n)->left->balance = -1;
981 (*n)->right->balance = 0;
984 (*n
)->left
->balance
= (*n
)->balance
> 0 ? -1 : 0;
985 (*n
)->right
->balance
= (*n
)->balance
< 0 ? 1 : 0;
989 if( (*n
)->balance
> 1)
991 if((*n
)->right
->balance
> 0)
994 (*n
)->left
->balance
= 0;
997 else if ((*n
)->right
->balance
== 0)
1000 (*n
)->left
->balance
= 1;
1003 else if((*n
)->right
->balance
< 0)
1005 rotate_right( &((*n
)->right
) );
1008 if( (*n)->balance < 0 )
1010 (*n)->left->balance = 0;
1011 (*n)->right->balance = 1;
1013 else if( (*n)->balance == 0 )
1015 (*n)->left->balance = 0;
1016 (*n)->right->balance = 0;
1018 else if( (*n)->balance > 0 )
1020 (*n)->left->balance = -1;
1021 (*n)->right->balance = 0;
1024 (*n
)->left
->balance
= (*n
)->balance
> 0 ? -1 : 0;
1025 (*n
)->right
->balance
= (*n
)->balance
< 0 ? 1 : 0;
1031 printf( "key = %ld, balance = %d\n", (*n)->key, (*n)->balance);
1034 return (*n
)->balance
;
1038 static void rotate_right (long_map_node
** parent
)
1040 long_map_node
* old_parent
= *parent
;
1041 long_map_node
* pivot
= old_parent
->left
;
1042 old_parent
->left
= pivot
->right
;
1043 pivot
->right
= old_parent
;
1048 static void rotate_left (long_map_node
** parent
)
1050 long_map_node
* old_parent
= *parent
;
1051 long_map_node
* pivot
= old_parent
->right
;
1052 old_parent
->right
= pivot
->left
;
1053 pivot
->left
= old_parent
;
1060 /***************************************************************************
1061 * This algorithm was created for the sdbm database library (a public-domain
1062 * reimplementation of ndbm) and seems to work relatively well in
1066 * This code was derived from code found at:
1067 * http://www.cse.yorku.ca/~oz/hash.html
1068 ***************************************************************************/
1069 static unsigned long sdbm_string_hash(const char *key
)
1071 unsigned long hashed_key
= 0;
1074 unsigned int nextch
;
1075 while(key
[index
] != '\0')
1077 nextch
= key
[index
];
1078 hashed_key
= nextch
+ (hashed_key
<< 6) + (hashed_key
<< 16) - hashed_key
;