// -*-c++-*- /* $Id: itree.h,v 1.11 2000/03/30 22:56:08 dm Exp $ */ /* * * Copyright (C) 1998 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #ifndef _ITREE_H_ #define _ITREE_H_ 1 #include "callback.h" #include "keyfunc.h" struct __opaquecontainer; #define oc __opaquecontainer_pointer typedef __opaquecontainer *oc; enum itree_color {INVALID, BLACK, RED}; void itree_insert (oc *, oc, const int, int (*) (void *, oc, oc), void *); void itree_delete (oc *, oc, const int); oc itree_successor (oc, const int); oc itree_predecessor (oc, const int); void __itree_check(oc *, const int, int (*) (void *, oc, oc), void *); #ifdef ITREE_DEBUG #define itree_check(r, os, cmpfn) __itree_check(r, os, cmpfn) #else /* !ITREE_DEBUG */ #define itree_check(r, os, cmpfn) #endif /* !ITREE_DEBUG */ struct __itree_entry_private { oc rbe_up; oc rbe_left; oc rbe_right; enum itree_color rbe_color; }; template #ifndef NO_TEMPLATE_FRIENDS class #else /* NO_TEMPLATE_FRIENDS */ struct #endif /* NO_TEMPLATE_FRIENDS */ itree_entry { __itree_entry_private p; #ifndef NO_TEMPLATE_FRIENDS /* Let's get friendly with the implementation... */ template U::*field, class C> friend class itree_core; #endif /* NO_TEMPLATE_FRIENDS */ public: T *up () { return (T *) p.rbe_up; } T *left () { return (T *) p.rbe_left; } T *right () { return (T *) p.rbe_right; } }; template T::*field, class C = compare > class itree_core { oc rb_root; const C cmp; static int scmp (void *t, oc a, oc b) { return (((itree_core *) t)->cmp) (*(T *) a, *(T *) b); } /* No copying */ itree_core (const itree_core &); itree_core &operator = (const itree_core &); #define eos ((int) &(((T *) 0)->*field).p) #define cmpfn scmp, (void *) this public: itree_core () { clear (); } itree_core (const C &c) : cmp (c) { clear (); } void deleteall () { T *n, *nn; for (n = first (); n; n = nn) { nn = next (n); delete n; } clear (); } void clear () {rb_root = NULL;} T *root () const { return (T *) rb_root; } static T *up (T *n) { return (n->*field).up (); } static T *left (T *n) { return (n->*field).left (); } static T *right (T *n) { return (n->*field).right (); } T *first () const { T *n, *nn; for (n = root (); n && (nn = left (n)); n = nn) ; return n; } static T *next (T *n) { return (T *) itree_successor ((oc) n, eos); } static T *prev (T *n) { return (T *) itree_predecessor ((oc) n, eos); } void insert (T *n) { itree_insert (&rb_root, (oc) n, eos, cmpfn); itree_check (&rb_root, eos, cmpfn); } void remove (T *n) { itree_delete (&rb_root, (oc) n, eos); itree_check (&rb_root, eos, cmpfn); } T *search (callback::ref cb) const { T *ret = NULL; T *n = root (); while (n) { int srchres = (*cb) (n); if (srchres < 0) n = left (n); else if (srchres > 0) n = right (n); else { /* In case there are duplicate keys, keep looking for the first one */ ret = n; n = left (n); } } return ret; } // XXX - template search to work around egcs 1.2 bug template T *search (int (*cb) (const A1 *, const A2 *, const T*), const A1 *a1, const A2 *a2) const { T *ret = NULL; T *n = root (); while (n) { int srchres = (*cb) (a1, a2, n); if (srchres < 0) n = left (n); else if (srchres > 0) n = right (n); else { /* In case there are duplicate keys, keep looking for the first one */ ret = n; n = left (n); } } return ret; } void traverse (callback::ref cb) { T *n, *nn; for (n = first (); n; n = nn) { nn = next (n); (*cb) (n); } } void traverse (void (T::*fn) ()) { T *n, *nn; for (n = first (); n; n = nn) { nn = next (n); (n->*fn) (); } } #undef eos #undef cmpfn }; #undef oc template V::*field, class C = compare > class itree : public itree_core > { typedef keyfunc_2 cmp_t; typedef itree_core core_t; const C kcmp; #if 0 template int kvcmp (const T *k, const V *v) { return kcmp (*k, v->*key); } #else int kvcmp (const K *k, const V *v) { return kcmp (*k, v->*key); } #endif static int skvcmp (const C *c, const K *k, const V *v) { return (*c) (*k, v->*key); } public: itree () {} itree (const C &c) : core_t (cmp_t (c)), kcmp (c) {} #if 0 template V *operator[] (const T &k) { int (itree::*fn) (const T *, const V *) = &kvcmp; return search (wrap (this, fn, &k)); } #else V *operator[] (const K &k) { // return search (wrap (this, &kvcmp, &k)); return search (skvcmp, &kcmp, &k); } #endif }; #endif /* !_ITREE_H_ */