00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "htatom.h"
00022 #include "htdata.h"
00023 #include "htdebug.h"
00024 #include "stream.h"
00025 #include "tools.h"
00026
00027 #include <string.h>
00028 #include <stdlib.h>
00029
00030 #define NEW_TREE_ENUM
00031
00032 int (*qsort_compare_compare_keys)(Object *key_a, Object *key_b);
00033
00034 int qsort_compare(const void *e1, const void *e2)
00035 {
00036 Object *d1=*(Object **)e1;
00037 Object *d2=*(Object **)e2;
00038 return qsort_compare_compare_keys(d1, d2);
00039 }
00040
00041 int qsort_compare_keys_tree_node(const void *e1, const void *e2)
00042 {
00043 ht_tree_node *d1=*(ht_tree_node **)e1;
00044 ht_tree_node *d2=*(ht_tree_node **)e2;
00045 return qsort_compare_compare_keys(d1->key, d2->key);
00046 }
00047
00048
00049
00050
00051
00052 ht_data_uint::ht_data_uint(uint v)
00053 {
00054 value=v;
00055 }
00056
00057 int ht_data_uint::load(ht_object_stream *s)
00058 {
00059 value=s->getIntHex(4, NULL);
00060 return s->get_error();
00061 }
00062
00063 void ht_data_uint::store(ht_object_stream *s)
00064 {
00065 s->putIntHex(value, 4, NULL);
00066 }
00067
00068 OBJECT_ID ht_data_uint::object_id() const
00069 {
00070 return ATOM_HT_DATA_UINT;
00071 }
00072
00073
00074
00075
00076
00077 ht_data_uint32::ht_data_uint32(uint32 v)
00078 {
00079 value = v;
00080 }
00081
00082 int ht_data_uint32::load(ht_object_stream *s)
00083 {
00084 value = s->getIntHex(4, NULL);
00085 return s->get_error();
00086 }
00087
00088 void ht_data_uint32::store(ht_object_stream *s)
00089 {
00090 s->putIntHex(value, 4, NULL);
00091 }
00092
00093 OBJECT_ID ht_data_uint32::object_id() const
00094 {
00095 return ATOM_HT_DATA_UINT32;
00096 }
00097
00098
00099
00100
00101
00102 ht_data_ptr::ht_data_ptr(const void *v)
00103 {
00104 value=v;
00105 }
00106
00107
00108
00109
00110
00111 ht_data_mem::ht_data_mem(const void *v, uint _size)
00112 {
00113 size=_size;
00114 if (size) {
00115 value=malloc(size);
00116 memmove(value, v, size);
00117 } else {
00118 value=NULL;
00119 }
00120 }
00121
00122 ht_data_mem::~ht_data_mem()
00123 {
00124 if (value) free(value);
00125 }
00126
00127 int ht_data_mem::load(ht_object_stream *s)
00128 {
00129 value=s->getBinary(size, NULL);
00130 return s->get_error();
00131 }
00132
00133 void ht_data_mem::store(ht_object_stream *s)
00134 {
00135 s->putBinary(value, size, NULL);
00136 }
00137
00138 OBJECT_ID ht_data_mem::object_id() const
00139 {
00140 return ATOM_HT_DATA_MEM;
00141 }
00142
00143
00144
00145
00146
00147 void ht_tree::init(compare_keys_func_ptr _compare_keys)
00148 {
00149 Object::init();
00150 assert(_compare_keys);
00151 compare_keys=_compare_keys;
00152 }
00153
00154 void ht_tree::done()
00155 {
00156 Object::done();
00157 }
00158
00159 void ht_tree::destroy()
00160 {
00161 done();
00162 }
00163
00164 void ht_tree::balance()
00165 {
00166 }
00167
00168 uint ht_tree::count()
00169 {
00170 return 0;
00171 }
00172
00173 bool ht_tree::del(Object *key)
00174 {
00175 return false;
00176 }
00177
00178 Object *ht_tree::enum_next(Object **value, Object *prevkey)
00179 {
00180 return NULL;
00181 }
00182
00183 Object *ht_tree::enum_prev(Object **value, Object *nextkey)
00184 {
00185 return NULL;
00186 }
00187
00188 Object *ht_tree::get(Object *key)
00189 {
00190 return NULL;
00191 }
00192
00193 Object *ht_tree::get_insert(Object *key)
00194 {
00195 return NULL;
00196 }
00197
00198 bool ht_tree::insert(Object *key, Object *data)
00199 {
00200 return false;
00201 }
00202
00203 void ht_tree::set_compare_keys(compare_keys_func_ptr new_compare_keys)
00204 {
00205 }
00206
00207
00208
00209
00210
00211 void ht_stree::init(compare_keys_func_ptr compare_keys)
00212 {
00213 ht_tree::init(compare_keys);
00214 root=NULL;
00215 node_count=0;
00216 }
00217
00218 void ht_stree::done()
00219 {
00220 ht_tree::done();
00221 }
00222
00223 void ht_stree::destroy()
00224 {
00225 empty();
00226 done();
00227 }
00228
00229 void ht_stree::set_compare_keys(compare_keys_func_ptr new_compare_keys)
00230 {
00231 if (node_count > 1) {
00232 ht_tree_node **ltable=(ht_tree_node**)malloc(sizeof (ht_tree_node*) * node_count);
00233 ht_tree_node **l=ltable;
00234
00235 populate_ltable(&l, root);
00236 if (compare_keys != new_compare_keys) {
00237
00238 compare_keys = new_compare_keys;
00239
00240 qsort_compare_compare_keys = compare_keys;
00241 qsort(ltable, node_count, sizeof *ltable, qsort_compare_keys_tree_node);
00242 }
00243
00244 insert_ltable(&root, ltable, ltable+node_count-1);
00245
00246 free(ltable);
00247 }
00248 }
00249
00250 void ht_stree::balance()
00251 {
00252 set_compare_keys(compare_keys);
00253 }
00254
00255 uint ht_stree::count()
00256 {
00257 return node_count;
00258 }
00259
00260 bool ht_stree::del(Object *key)
00261 {
00262 ht_tree_node *node, *parent;
00263 int direction;
00264 if (!get_node_and_parent(key, &node, &parent, &direction)) return false;
00265
00266 node->key->done();
00267 delete node->key;
00268
00269 node->value->done();
00270 delete node->value;
00271
00272 if (node->left) {
00273 ht_tree_node *c=node->left, *a=node->right;
00274 *node=*c;
00275 delete c;
00276 get_rightmost_node(node)->right=a;
00277 } else if (node->right) {
00278 ht_tree_node *c=node->right, *a=node->left;
00279 *node=*c;
00280 delete c;
00281 get_leftmost_node(node)->left=a;
00282 } else {
00283 ht_tree_node **pp;
00284 if (parent) {
00285 if (direction>0) pp=&parent->right; else pp=&parent->left;
00286 } else {
00287 pp=&root;
00288 }
00289 *pp=NULL;
00290 delete node;
00291 }
00292 node_count--;
00293 return true;
00294 }
00295
00296 void ht_stree::empty()
00297 {
00298 if (root) {
00299 free_all(root);
00300 root=NULL;
00301 }
00302 }
00303
00304 void ht_stree::enum_next_i(ht_tree_node *node, Object *prevkey, ht_tree_node **retv)
00305 {
00306 if ((prevkey == NULL) || (compare_keys(prevkey, node->key) < 0)) {
00307 *retv = node;
00308 if (node->left) enum_next_i(node->left, prevkey, retv);
00309 } else {
00310 if (node->right) enum_next_i(node->right, prevkey, retv);
00311 }
00312 }
00313
00314 void ht_stree::enum_prev_i(ht_tree_node *node, Object *nextkey, ht_tree_node **retv)
00315 {
00316 if ((nextkey == NULL) || (compare_keys(node->key, nextkey) < 0)) {
00317 *retv = node;
00318 if (node->right) enum_prev_i(node->right, nextkey, retv);
00319 } else {
00320 if (node->left) enum_prev_i(node->left, nextkey, retv);
00321 }
00322 }
00323
00324 Object *ht_stree::enum_next(Object **value, Object *prevkey)
00325 {
00326 #ifdef NEW_TREE_ENUM
00327 ht_tree_node *n = NULL, *next = NULL;
00328 if (root) {
00329 if (prevkey) {
00330 n = root;
00331 while (n) {
00332 int c = compare_keys(prevkey, n->key);
00333 if (c>0) {
00334 n = n->right;
00335 } else if (c<0) {
00336 next = n;
00337 n = n->left;
00338 } else {
00339 if (n->right) next = get_leftmost_node(n->right);
00340 break;
00341 }
00342 }
00343 } else next = get_leftmost_node(root);
00344 }
00345 if (next) {
00346 *value = next->value;
00347 return next->key;
00348 }
00349 return NULL;
00350 #else
00351 ht_tree_node *n = NULL;
00352 if (root) enum_next_i(root, prevkey, &n);
00353 if (n) {
00354 *value = n->value;
00355 return n->key;
00356 }
00357 return NULL;
00358 #endif
00359 }
00360
00361 Object *ht_stree::enum_prev(Object **value, Object *nextkey)
00362 {
00363 #ifdef NEW_TREE_ENUM
00364 ht_tree_node *n = NULL, *prev = NULL;
00365 if (root) {
00366 if (nextkey) {
00367 n = root;
00368 while (n) {
00369 int c = compare_keys(nextkey, n->key);
00370 if (c>0) {
00371 prev = n;
00372 n = n->right;
00373 } else if (c<0) {
00374 n = n->left;
00375 } else {
00376 if (n->left) prev = get_rightmost_node(n->left);
00377 break;
00378 }
00379 }
00380 } else prev = get_rightmost_node(root);
00381 }
00382 if (prev) {
00383 *value = prev->value;
00384 return prev->key;
00385 }
00386 return NULL;
00387 #else
00388 ht_tree_node *n = NULL;
00389 if (root) enum_prev_i(root, nextkey, &n);
00390 if (n) {
00391 *value = n->value;
00392 return n->key;
00393 }
00394 return NULL;
00395 #endif
00396 }
00397
00398 void ht_stree::free_all(ht_tree_node *node)
00399 {
00400 if (node->left) free_all(node->left);
00401 if (node->right) free_all(node->right);
00402 node->key->done();
00403 delete node->key;
00404
00405 if (node->value) {
00406 node->value->done();
00407 delete node->value;
00408 }
00409
00410 delete node;
00411 node_count--;
00412 }
00413
00414 void ht_stree::free_skeleton(ht_tree_node *node)
00415 {
00416 if (node->left) free_skeleton(node->left);
00417 if (node->right) free_skeleton(node->right);
00418 delete node;
00419 node_count--;
00420 }
00421
00422 Object *ht_stree::get(Object *key)
00423 {
00424 ht_tree_node *n=get_node_i(key);
00425 if (n) return n->value;
00426 return NULL;
00427 }
00428
00429 ht_tree_node *ht_stree::get_node_i(Object *key)
00430 {
00431 ht_tree_node *n=root;
00432 while (n) {
00433 int c=compare_keys(key, n->key);
00434 if (c>0) n=n->right; else
00435 if (c<0) n=n->left; else
00436 return n;
00437 }
00438 return NULL;
00439 }
00440
00441 bool ht_stree::get_node_and_parent(Object *key, ht_tree_node **node, ht_tree_node **parent_node, int *direction)
00442 {
00443 ht_tree_node *p=NULL, *n=root;
00444 int pc=0;
00445 while (n) {
00446 int c=compare_keys(key, n->key);
00447 if (c>0) {
00448 p=n;
00449 pc=c;
00450 n=n->right;
00451 } else if (c<0) {
00452 p=n;
00453 pc=c;
00454 n=n->left;
00455 } else {
00456 *node=n;
00457 *parent_node=p;
00458 *direction=pc;
00459 return true;
00460 }
00461 }
00462 return false;
00463 }
00464
00465 ht_tree_node *ht_stree::get_leftmost_node(ht_tree_node *node)
00466 {
00467 if (node) while (node->left) node=node->left;
00468 return node;
00469 }
00470
00471 ht_tree_node *ht_stree::get_rightmost_node(ht_tree_node *node)
00472 {
00473 if (node) while (node->right) node=node->right;
00474 return node;
00475 }
00476
00477 bool ht_stree::insert(Object *key, Object *value)
00478 {
00479
00480 if (!key) return false;
00481 ht_tree_node **n=&root;
00482 while (*n) {
00483 int c=compare_keys(key, (*n)->key);
00484 if (c>0) n=&(*n)->right; else
00485 if (c<0) n=&(*n)->left; else
00486 return false;
00487 }
00488 *n=new ht_tree_node();
00489 (*n)->key=key;
00490 (*n)->value=value;
00491 (*n)->left=NULL;
00492 (*n)->right=NULL;
00493 node_count++;
00494 return true;
00495 }
00496
00497 void ht_stree::insert_ltable(ht_tree_node **node, ht_tree_node **start, ht_tree_node **end)
00498 {
00499 if (start <= end) {
00500 ht_tree_node **m = start+(end-start)/2;
00501 *node = *m;
00502 insert_ltable(&(*node)->left, start, m-1);
00503 insert_ltable(&(*node)->right, m+1, end);
00504 } else {
00505 *node = NULL;
00506 }
00507 }
00508
00509 void stree_load(ht_object_stream *s, ht_tree_node **n, uint *node_count, int l, int r)
00510 {
00511 if (l>r) {
00512 *n = NULL;
00513 return;
00514 }
00515 *n = new ht_tree_node();
00516 int m = (l+r)/2;
00517 stree_load(s, &(*n)->left, node_count, l, m-1);
00518
00519 (*n)->key = s->getObject(NULL);
00520 (*n)->value = s->getObject(NULL);
00521 (*node_count)++;
00522
00523 stree_load(s, &(*n)->right, node_count, m+1, r);
00524 }
00525
00526 int ht_stree::load(ht_object_stream *s)
00527 {
00528 void *d=find_atom(s->getIntHex(4, NULL));
00529 if (!d) return 1;
00530 compare_keys=(compare_keys_func_ptr)d;
00531
00532 uint c=s->getIntDec(4, NULL);
00533 #if 0
00534 root=NULL;
00535 node_count=0;
00536
00537 for (uint i=0; i<c; i++) {
00538 Object *key=s->get_object(NULL);
00539 Object *value=s->get_object(NULL);
00540 if (!key) return 1;
00541 if (!value) return 1;
00542 insert(key, value);
00543 }
00544 balance();
00545 #else
00546 root=NULL;
00547 node_count=0;
00548
00549 stree_load(s, &root, &node_count, 0, c-1);
00550 assert(node_count == c);
00551
00552 #endif
00553 return s->get_error();
00554 }
00555
00556 void ht_stree::store(ht_object_stream *s)
00557 {
00558 s->putIntHex(find_atom_rev((void*)compare_keys), 4, NULL);
00559
00560 s->putIntDec(count(), 4, NULL);
00561
00562 Object *key=NULL;
00563 Object *value;
00564 while ((key=enum_next(&value, key))) {
00565 if (value) {
00566 s->putObject(key, NULL);
00567 s->putObject(value, NULL);
00568 }
00569 }
00570 }
00571
00572 OBJECT_ID ht_stree::object_id() const
00573 {
00574 return ATOM_HT_STREE;
00575 }
00576
00577 void ht_stree::populate_ltable(ht_tree_node ***ltable, ht_tree_node *node)
00578 {
00579 if (node->left) populate_ltable(ltable, node->left);
00580 **ltable=node;
00581 (*ltable)++;
00582 if (node->right) populate_ltable(ltable, node->right);
00583 }
00584
00585
00586
00587
00588
00589 void ht_dtree::init(compare_keys_func_ptr compare_keys, uint _max_ub_delete, uint _max_ub_insert)
00590 {
00591 ht_stree::init(compare_keys);
00592 dead_node_count=0;
00593 ub_delete=0;
00594 ub_insert=0;
00595 max_ub_delete=_max_ub_delete;
00596 max_ub_insert=_max_ub_insert;
00597 }
00598
00599 void ht_dtree::done()
00600 {
00601 ht_stree::done();
00602 }
00603
00604 void ht_dtree::populate_ltable(ht_tree_node ***ltable, ht_tree_node *node)
00605 {
00606 if (node->left) populate_ltable(ltable, node->left);
00607 if (node->value) {
00608 **ltable=node;
00609 (*ltable)++;
00610 }
00611 if (node->right) populate_ltable(ltable, node->right);
00612 }
00613
00614 void ht_dtree::populate_ltable_free_dead_nodes(ht_tree_node ***ltable, ht_tree_node *node)
00615 {
00616 if (node->left) populate_ltable(ltable, node->left);
00617 if (node->value) {
00618 **ltable=node;
00619 (*ltable)++;
00620 } else {
00621 delete node;
00622 }
00623 if (node->right) populate_ltable(ltable, node->right);
00624 }
00625
00626 void ht_dtree::set_compare_keys(compare_keys_func_ptr new_compare_keys)
00627 {
00628 ub_delete=0;
00629 ub_insert=0;
00630 if (node_count-dead_node_count) {
00631
00632 uint new_node_count = node_count-dead_node_count;
00633 ht_tree_node **ltable = (ht_tree_node**)malloc(sizeof (ht_tree_node*) * new_node_count);
00634 assert(ltable);
00635 ht_tree_node **l = ltable;
00636 populate_ltable_free_dead_nodes(&l, root);
00637
00638
00639 uint old_node_count = node_count;
00640 node_count = 0;
00641 root = NULL;
00642 if (compare_keys != new_compare_keys) {
00643
00644 compare_keys = new_compare_keys;
00645
00646 qsort_compare_compare_keys = compare_keys;
00647 qsort(ltable, new_node_count, sizeof *ltable, qsort_compare_keys_tree_node);
00648 }
00649
00650 insert_ltable(&root, ltable, ltable+new_node_count-1);
00651
00652 node_count = old_node_count;
00653
00654 free(ltable);
00655
00656 node_count = new_node_count;
00657 dead_node_count = 0;
00658 }
00659 }
00660
00661 uint ht_dtree::count()
00662 {
00663 return node_count-dead_node_count;
00664 }
00665
00666 bool ht_dtree::del(Object *key)
00667 {
00668 ht_tree_node *n=get_node_i(key);
00669 if ((n) && (n->value)) {
00670 n->value->done();
00671 delete n->value;
00672 n->value=NULL;
00673 dead_node_count++;
00674 if (max_ub_delete) {
00675 if (++ub_delete>max_ub_delete) balance();
00676 }
00677 return true;
00678 }
00679 return false;
00680 }
00681
00682 Object *ht_dtree::enum_next(Object **value, Object *prevkey)
00683 {
00684 #ifdef NEW_TREE_ENUM
00685 ht_tree_node *n, *next;
00686 do {
00687 n = NULL;
00688 next = NULL;
00689 if (root) {
00690 if (prevkey) {
00691 n = root;
00692 while (n) {
00693 int c = compare_keys(prevkey, n->key);
00694 if (c>0) {
00695 n = n->right;
00696 } else if (c<0) {
00697 next = n;
00698 n = n->left;
00699 } else {
00700 if (n->right) next = get_leftmost_node(n->right);
00701 break;
00702 }
00703 }
00704 } else next = get_leftmost_node(root);
00705 }
00706 if (next) prevkey = next->key;
00707 } while (next && !next->value);
00708 if (next) {
00709 *value = next->value;
00710 return next->key;
00711 }
00712 return NULL;
00713 #else
00714 ht_tree_node *n;
00715 Object *k = prevkey;
00716 while (1) {
00717 n = NULL;
00718 if (root) enum_next_i(root, k, &n);
00719 if (!n) break;
00720 if (n->value) {
00721 *value = n->value;
00722 return n->key;
00723 }
00724 k = n->key;
00725 }
00726 return NULL;
00727 #endif
00728 }
00729
00730 Object *ht_dtree::enum_prev(Object **value, Object *nextkey)
00731 {
00732 #ifdef NEW_TREE_ENUM
00733 ht_tree_node *n, *prev;
00734 while (1) {
00735 n = NULL;
00736 prev = NULL;
00737 if (root) {
00738 if (nextkey) {
00739 n = root;
00740 while (n) {
00741 int c = compare_keys(nextkey, n->key);
00742 if (c>0) {
00743 prev = n;
00744 n = n->right;
00745 } else if (c<0) {
00746 n = n->left;
00747 } else {
00748 if (n->left) prev = get_rightmost_node(n->left);
00749 break;
00750 }
00751 }
00752 } else prev = get_rightmost_node(root);
00753 }
00754 if (prev) nextkey = prev->key;
00755 } while (prev && !prev->value);
00756 if (prev) {
00757 *value = prev->value;
00758 return prev->key;
00759 }
00760 return NULL;
00761 #else
00762 ht_tree_node *n;
00763 Object *k = nextkey;
00764 while (1) {
00765 n = NULL;
00766 if (root) enum_prev_i(root, k, &n);
00767 if (!n) break;
00768 if (n->value) {
00769 *value = n->value;
00770 return n->key;
00771 }
00772 k = n->key;
00773 }
00774 return NULL;
00775 #endif
00776 }
00777
00778 bool ht_dtree::insert(Object *key, Object *value)
00779 {
00780 if ((!key) || (!value)) return false;
00781 ht_tree_node **n=&root;
00782 while (*n) {
00783 int c=compare_keys(key, (*n)->key);
00784 if (c>0) n=&(*n)->right; else
00785 if (c<0) n=&(*n)->left; else
00786 break;
00787 }
00788 if (*n) {
00789 if ((*n)->value) return false;
00790 (*n)->key->done();
00791 delete (*n)->key;
00792 (*n)->key=key;
00793 (*n)->value=value;
00794 dead_node_count--;
00795 } else {
00796 *n=new ht_tree_node();
00797 (*n)->key=key;
00798 (*n)->value=value;
00799 (*n)->left=NULL;
00800 (*n)->right=NULL;
00801 node_count++;
00802 }
00803 if (max_ub_insert) {
00804 if (++ub_insert>max_ub_insert) balance();
00805 }
00806 return true;
00807 }
00808
00809
00810
00811
00812
00813 void ht_list::init(compare_keys_func_ptr _compare_keys)
00814 {
00815 Object::init();
00816 compare_keys=_compare_keys;
00817 }
00818
00819 void ht_list::done()
00820 {
00821 Object::done();
00822 }
00823
00824 void ht_list::destroy()
00825 {
00826 done();
00827 }
00828
00829 void ht_list::append(Object *data)
00830 {
00831 }
00832
00833 uint ht_list::count()
00834 {
00835 return 0;
00836 }
00837
00838 void ht_list::copy_to(uint i, uint count, ht_list *destlist)
00839 {
00840 uint j=0;
00841 while (count--) {
00842 Object *w=get(i+j);
00843 if (j) {
00844 destlist->insert_after(w, j-1);
00845 } else {
00846 destlist->insert(w);
00847 }
00848 j++;
00849 }
00850 }
00851
00852 ht_list *ht_list::cut(uint i, uint count)
00853 {
00854 return NULL;
00855 }
00856
00857 bool ht_list::del(uint i)
00858 {
00859 return false;
00860 }
00861
00862 bool ht_list::del_multiple(uint i, uint count)
00863 {
00864 bool b=true;
00865 while (count--) {
00866 b&=del(i);
00867 }
00868 return b;
00869 }
00870
00871 void ht_list::empty()
00872 {
00873 }
00874
00875 uint ht_list::find(Object *data)
00876 {
00877 return LIST_UNDEFINED;
00878 }
00879
00880 Object *ht_list::get(uint i)
00881 {
00882 return NULL;
00883 }
00884
00885 void ht_list::insert(Object *data)
00886 {
00887 }
00888
00889 void ht_list::insert_after(Object *data, uint i)
00890 {
00891 }
00892
00893 void ht_list::insert_before(Object *data, uint i)
00894 {
00895 }
00896
00897 void ht_list::move(uint source, uint dest)
00898 {
00899 }
00900
00901 void ht_list::move_multiple(uint source, uint dest, uint count)
00902 {
00903 }
00904
00905 void ht_list::prepend(Object *data)
00906 {
00907 }
00908
00909 Object *ht_list::remove(uint i)
00910 {
00911 return NULL;
00912 }
00913
00914 bool ht_list::remove_multiple(uint i, uint count)
00915 {
00916 bool b=true;
00917 while (count--) {
00918 b&=(remove(i)!=NULL);
00919 }
00920 return b;
00921 }
00922
00923 bool ht_list::set(uint i, Object *data)
00924 {
00925 return false;
00926 }
00927
00928 bool ht_list::sort()
00929 {
00930 return false;
00931 }
00932
00933
00934
00935
00936
00937 #define HT_CLIST_ENTRY_COUNT_START 32
00938
00939
00940 #define HT_CLIST_ENTRY_COUNT_EXT_NUM 3
00941 #define HT_CLIST_ENTRY_COUNT_EXT_DEN 2
00942
00943 void ht_clist::init(compare_keys_func_ptr compare_keys)
00944 {
00945 ht_list::init(compare_keys);
00946 c_size=HT_CLIST_ENTRY_COUNT_START;
00947 items=(Object**)malloc(c_size * sizeof (Object*));
00948 c_entry_count=0;
00949 }
00950
00951 void ht_clist::done()
00952 {
00953 free(items);
00954 ht_list::done();
00955 }
00956
00957 void ht_clist::destroy()
00958 {
00959 empty();
00960 done();
00961 }
00962
00963 void ht_clist::append(Object *data)
00964 {
00965 insert_before(data, c_entry_count);
00966 }
00967
00968 uint ht_clist::count()
00969 {
00970 return c_entry_count;
00971 }
00972
00973 ht_list *ht_clist::cut(uint start, uint count)
00974 {
00975 ht_clist *c=new ht_clist();
00976 c->init(compare_keys);
00977 for (uint i=0; i<count; i++) {
00978 c->insert(items[start+i]);
00979 }
00980 remove_multiple(start, count);
00981 return c;
00982 }
00983
00984 bool ht_clist::del(uint i)
00985 {
00986 if (i<c_entry_count) {
00987 do_free(i);
00988 do_remove(i);
00989 return true;
00990 }
00991 return false;
00992 }
00993
00994 void ht_clist::do_free(uint i)
00995 {
00996 if (items[i]) {
00997 items[i]->done();
00998 delete items[i];
00999 }
01000 }
01001
01002 void ht_clist::do_remove(uint i)
01003 {
01004 memmove(&items[i], &items[i+1], sizeof items[i] * (c_entry_count-i-1));
01005 c_entry_count--;
01006 }
01007
01008 Object *ht_clist::duplicate()
01009 {
01010 ht_clist *d=new ht_clist();
01011 d->init(compare_keys);
01012 for (uint i=0; i<c_entry_count; i++) {
01013 d->insert(items[i]->duplicate());
01014 }
01015 return d;
01016 }
01017
01018 void ht_clist::empty()
01019 {
01020 for (uint i=0; i<c_entry_count; i++) {
01021 do_free(i);
01022 }
01023 c_entry_count=0;
01024 }
01025
01026 void ht_clist::extend_list()
01027 {
01028 c_size *= HT_CLIST_ENTRY_COUNT_EXT_NUM;
01029 c_size /= HT_CLIST_ENTRY_COUNT_EXT_DEN;
01030 Object **new_items=(Object**)malloc(c_size * sizeof (Object*));
01031 memmove(new_items, items, c_entry_count * sizeof (Object*));
01032 free(items);
01033 items=new_items;
01034 }
01035
01036 uint ht_clist::find(Object *data)
01037 {
01038 if (compare_keys) {
01039 for (uint i=0; i<c_entry_count; i++) {
01040 if (compare_keys(data, items[i])==0) return i;
01041 }
01042 }
01043 return LIST_UNDEFINED;
01044 }
01045
01046 Object *ht_clist::get(uint i)
01047 {
01048 if (i<c_entry_count) return items[i];
01049 return NULL;
01050 }
01051
01052 void ht_clist::insert(Object *data)
01053 {
01054 append(data);
01055 }
01056
01057 void ht_clist::insert_after(Object *data, uint i)
01058 {
01059 insert_before(data, i+1);
01060 }
01061
01062 void ht_clist::insert_before(Object *data, uint i)
01063 {
01064 uint hi= i>c_entry_count ? i+1 : c_entry_count+1;
01065 while (hi>=c_size) extend_list();
01066 if (i>c_entry_count) {
01067 c_entry_count=i+1;
01068 } else {
01069 memmove(items+i+1, items+i, sizeof items[0] * (c_entry_count-i));
01070 c_entry_count++;
01071 }
01072 items[i]=data;
01073 }
01074
01075 int ht_clist::load(ht_object_stream *s)
01076 {
01077 c_size=HT_CLIST_ENTRY_COUNT_START;
01078 items=(Object**)malloc(c_size * sizeof (Object*));
01079 c_entry_count=0;
01080
01081 void *d=find_atom(s->getIntHex(4, NULL));
01082
01083 compare_keys=(compare_keys_func_ptr)d;
01084
01085 int c=s->getIntDec(4, "item_count");
01086 for (int i=0; i<c; i++) {
01087 Object *d=s->getObject("item");
01088 if (s->get_error()) break;
01089 prepend(d);
01090 }
01091 return s->get_error();
01092 }
01093
01094 void ht_clist::move(uint source, uint dest)
01095 {
01096 if (dest<=c_entry_count) {
01097 Object *src=get(source);
01098 memmove(items+source, items+source+1, sizeof items[0] * (c_entry_count-source-1));
01099 memmove(items+dest+1, items+dest, sizeof items[0] * (c_entry_count-dest-1));
01100 items[dest]=src;
01101 }
01102 }
01103
01104 void ht_clist::move_multiple(uint source, uint dest, uint count)
01105 {
01106 if (dest<=c_entry_count) {
01107 for (uint i=0; i<count; i++) {
01108 move(source, dest+count-1);
01109 }
01110 }
01111 }
01112
01113 OBJECT_ID ht_clist::object_id() const
01114 {
01115 return ATOM_HT_CLIST;
01116 }
01117
01118 void ht_clist::prepend(Object *data)
01119 {
01120 insert_before(data, 0);
01121 }
01122
01123 Object *ht_clist::remove(uint i)
01124 {
01125 if (i<c_entry_count) {
01126 Object *d=items[i];
01127 do_remove(i);
01128 return d;
01129 }
01130 return NULL;
01131 }
01132
01133 bool ht_clist::set(uint i, Object *data)
01134 {
01135 while (i>=c_entry_count) append(NULL);
01136 do_free(i);
01137 items[i] = data;
01138 return true;
01139 }
01140
01141 bool ht_clist::sort()
01142 {
01143 if (compare_keys && (c_entry_count>1)) {
01144 qsort_compare_compare_keys = compare_keys;
01145 qsort(items, c_entry_count, sizeof *items, qsort_compare);
01146 }
01147 return false;
01148 }
01149
01150 void ht_clist::store(ht_object_stream *s)
01151 {
01152 s->putIntHex(find_atom_rev((void*)compare_keys), 4, NULL);
01153 s->putIntDec(c_entry_count, 4, "item_count");
01154 for (int i=c_entry_count-1; i>=0; i--) {
01155 s->putObject(items[i], "item");
01156 }
01157 }
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 void ht_sorted_list::init(compare_keys_func_ptr compare_keys)
01199 {
01200 ht_clist::init(compare_keys);
01201 }
01202
01203 void ht_sorted_list::done()
01204 {
01205 ht_clist::done();
01206 }
01207
01208 void ht_sorted_list::append(Object *data)
01209 {
01210 insert(data);
01211 }
01212
01213 uint ht_sorted_list::find(Object *data)
01214 {
01215 if (compare_keys) {
01216 HT_ERROR("function untested !");
01217 uint w=(c_entry_count-1)/2, ow=0;
01218 while (w!=ow) {
01219 ow=w;
01220 int ck=compare_keys(data, items[w]);
01221 if (ck==0) return w;
01222 if (ck>0) w+=c_entry_count-1;
01223 w>>=1;
01224 }
01225 }
01226 return LIST_UNDEFINED;
01227 }
01228
01229 void ht_sorted_list::insert(Object *data)
01230 {
01231 if (c_entry_count) {
01232 int l=0, r=c_entry_count-1;
01233 int m=(l+r+1)/2;
01234 do {
01235 int cmp=compare_keys(data, items[m]);
01236 if (cmp>0) l=m+1; else
01237 if (cmp<0) r=m-1; else break;
01238 m=(l+r+1)/2;
01239 } while (l<=r);
01240 ht_clist::insert_before(data, m);
01241 } else {
01242 ht_clist::insert_before(data, 0);
01243 }
01244 }
01245
01246 void ht_sorted_list::insert_after(Object *data, uint i)
01247 {
01248 insert(data);
01249 }
01250
01251 void ht_sorted_list::insert_before(Object *data, uint i)
01252 {
01253 insert(data);
01254 }
01255
01256 void ht_sorted_list::move(uint source, uint dest)
01257 {
01258
01259 }
01260
01261 void ht_sorted_list::move_multiple(uint source, uint dest, uint count)
01262 {
01263
01264 }
01265
01266 void ht_sorted_list::prepend(Object *data)
01267 {
01268 insert(data);
01269 }
01270
01271 bool ht_sorted_list::set(uint i, Object *data)
01272 {
01273 insert(data);
01274 return true;
01275 }
01276
01277
01278
01279
01280
01281 Object *ht_stack::pop()
01282 {
01283 if (c_entry_count) {
01284 Object *d=get(c_entry_count-1);
01285 do_remove(c_entry_count-1);
01286 return d;
01287 }
01288 return NULL;
01289 }
01290
01291 void ht_stack::push(Object *data)
01292 {
01293 append(data);
01294 }
01295
01296
01297
01298
01299
01300 void ht_queue::enqueue(Object *data)
01301 {
01302 append(data);
01303 }
01304
01305 Object *ht_queue::dequeue()
01306 {
01307 if (c_entry_count) {
01308 Object *d=get(0);
01309 do_remove(0);
01310 return d;
01311 }
01312 return NULL;
01313 }
01314
01315 Object *ht_queue::pop()
01316 {
01317 return dequeue();
01318 }
01319
01320 void ht_queue::push(Object *data)
01321 {
01322 enqueue(data);
01323 }
01324
01325
01326
01327
01328
01329 char *matchhash(int value, int_hash *hash_table)
01330 {
01331 if (hash_table) {
01332 while (hash_table->desc) {
01333 if (hash_table->value==value) return hash_table->desc;
01334 hash_table++;
01335 }
01336 }
01337 return NULL;
01338 }
01339
01340
01341
01342
01343
01344 int compare_keys_ht_data(Object *key_a, Object *key_b)
01345 {
01346 return key_a->compareTo(key_b);
01347 }
01348
01349 int compare_keys_int(Object *key_a, Object *key_b)
01350 {
01351 int a=((ht_data_uint*)key_a)->value;
01352 int b=((ht_data_uint*)key_b)->value;
01353 if (a>b) return 1; else if (a<b) return -1;
01354 return 0;
01355 }
01356
01357 int compare_keys_uint(Object *key_a, Object *key_b)
01358 {
01359 uint a=((ht_data_uint*)key_a)->value;
01360 uint b=((ht_data_uint*)key_b)->value;
01361 if (a>b) return 1; else if (a<b) return -1;
01362 return 0;
01363 }
01364
01365
01366
01367
01368
01369 BUILDER(ATOM_HT_DATA_UINT, ht_data_uint);
01370 BUILDER(ATOM_HT_DATA_UINT32, ht_data_uint32);
01371 BUILDER(ATOM_HT_DATA_MEM, ht_data_mem);
01372 BUILDER(ATOM_HT_STREE, ht_stree);
01373 BUILDER(ATOM_HT_CLIST, ht_clist);
01374
01375 bool init_data()
01376 {
01377 REGISTER(ATOM_HT_DATA_UINT, ht_data_uint);
01378 REGISTER(ATOM_HT_DATA_UINT32, ht_data_uint32);
01379 REGISTER(ATOM_HT_DATA_MEM, ht_data_mem);
01380 REGISTER(ATOM_HT_STREE, ht_stree);
01381 REGISTER(ATOM_HT_CLIST, ht_clist);
01382
01383 register_atom(ATOM_COMPARE_KEYS_HT_DATA, (void*)compare_keys_ht_data);
01384 register_atom(ATOM_COMPARE_KEYS_INT, (void*)compare_keys_int);
01385 register_atom(ATOM_COMPARE_KEYS_UINT, (void*)compare_keys_uint);
01386
01387 return true;
01388 }
01389
01390
01391
01392
01393
01394 void done_data()
01395 {
01396 unregister_atom(ATOM_COMPARE_KEYS_HT_DATA);
01397 unregister_atom(ATOM_COMPARE_KEYS_INT);
01398 unregister_atom(ATOM_COMPARE_KEYS_UINT);
01399
01400 UNREGISTER(ATOM_HT_DATA_UINT, ht_data_uint);
01401 UNREGISTER(ATOM_HT_DATA_UINT32, ht_data_uint32);
01402 UNREGISTER(ATOM_HT_DATA_MEM, ht_data_mem);
01403 UNREGISTER(ATOM_HT_STREE, ht_stree);
01404 UNREGISTER(ATOM_HT_CLIST, ht_clist);
01405 }
01406