Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htdata.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      htdata.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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  *      CLASS ht_data_uint
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  *      ht_data_uint32
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  *      CLASS ht_data_ptr
00100  */
00101 
00102 ht_data_ptr::ht_data_ptr(const void *v)
00103 {
00104         value=v;
00105 }
00106 
00107 /*
00108  *      CLASS ht_data_mem
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  *      CLASS ht_tree
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  *      CLASS ht_stree  (simple tree)
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                 /* create ltable from tree */
00235                 populate_ltable(&l, root);
00236                 if (compare_keys != new_compare_keys) {
00237                         /* set new keying method */
00238                         compare_keys = new_compare_keys;
00239                         /* re-sort ltable */
00240                         qsort_compare_compare_keys = compare_keys;
00241                         qsort(ltable, node_count, sizeof *ltable, qsort_compare_keys_tree_node);
00242                 }
00243                 /* rebuild tree from ltable and old_tree */
00244                 insert_ltable(&root, ltable, ltable+node_count-1);
00245                 /* destroy ltable */
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 //      if ((!key) || (!value)) return false;
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  *      CLASS ht_dtree (rebalancing and dead node tree)
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                 /* create ltable from tree */
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                 /* save old tree, empty tree */
00639                 uint old_node_count = node_count;
00640                 node_count = 0;
00641                 root = NULL;
00642                 if (compare_keys != new_compare_keys) {
00643                         /* set new keying method */
00644                         compare_keys = new_compare_keys;
00645                         /* re-sort ltable */
00646                         qsort_compare_compare_keys = compare_keys;
00647                         qsort(ltable, new_node_count, sizeof *ltable, qsort_compare_keys_tree_node);
00648                 }
00649                 /* rebuild tree from ltable and old_tree */
00650                 insert_ltable(&root, ltable, ltable+new_node_count-1);
00651                 /* destroy old_tree */
00652                 node_count = old_node_count;
00653                 /* destroy ltable */
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  *      CLASS ht_list
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  *      CLASS ht_clist
00935  */
00936 
00937 #define HT_CLIST_ENTRY_COUNT_START              32
00938 
00939 // exponential growth factor: num/den
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 //      if (!d) return 1;
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 !!! THERE'S A BUG IN HERE !!!
01162 
01163 bool ht_clist::qsort_i(uint _l, uint _r)
01164 {
01165         int xchg_count=0;
01166         int l=(int)_l;
01167         int r=(int)_r;
01168         int m=(l+r) / 2;
01169         int origl=l;
01170         int origr=r;
01171         Object *c;
01172         c=items[m];
01173         do {
01174                 while ((l<m) && compare_keys(items[l], c) < 0) l++;
01175                 while ((r>m) && compare_keys(items[r], c) > 0) r--;
01176                 if (l < r) {
01177                         Object *t;
01178                         t=items[l];
01179                         items[l]=items[r];
01180                         items[r]=t;
01181                         l++;
01182                         r--;
01183                         xchg_count++;
01184                 } else if (l==r) {
01185                         l++;
01186                         r--;
01187                 }
01188         } while (l < r);
01189         if (origl < r) qsort_i(origl, r);
01190         if (l < origr) qsort_i(l, origr);
01191         return (xchg_count!=0);
01192 }*/
01193 
01194 /*
01195  *      CLASS ht_sorted_list
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         // do nothing
01259 }
01260 
01261 void ht_sorted_list::move_multiple(uint source, uint dest, uint count)
01262 {
01263         // do nothing
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  *      CLASS ht_stack
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  *      CLASS ht_queue
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  *   matchhash
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  *      compare procedures
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  *      INIT
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  *      DONE
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 

Generated on Fri May 7 21:15:32 2004 by doxygen 1.3.5