// -*-c++-*- /* $Id: qhash.h,v 1.16 2001/07/18 03:02:17 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 _QHASH_H_ #define _QHASH_H_ 1 #include "ihash.h" template struct qhash_lookup_return { typedef T *type; typedef const T *const_type; static type ret (T *v) { return v; } static const_type const_ret (T *v) { return v; } }; template struct qhash_lookup_return > { typedef ptr type; typedef ptr const_type; static type ret (ref *v) { if (v) return *v; return NULL; } static const_type const_ret (ref *v) { if (v) return *v; return NULL; } }; template struct qhash_lookup_return { typedef T *type; typedef const T *const_type; static type ret (T *v) { return v; } static const_type const_ret (T *v) { return v; } }; template struct qhash_slot { ihash_entry link; const K key; V value; qhash_slot (const K &k, CREF (V) v) : key (k), value (v) {} qhash_slot (const K &k, NCREF (V) v) : key (k), value (v) {} }; template, class E = equals, // XXX - We need to kludge this for both g++ and KCC class R = qhash_lookup_return, ihash_entry > qhash_slot::*kludge = &qhash_slot::link> class qhash : public ihash_core, kludge> { typedef qhash_slot slot; typedef ihash_core core; const E eq; const H hash; slot *getslot (const K &k) const { slot *s; for (s = lookup_val (hash (k)); s && !eq (s->key, k); s = next_val (s)) ; return s; } void delslot (slot *s) { core::remove (s); delete s; } static void mkcb (callback::ref cb, slot *s) { (*cb) (s->key, R::ret (&s->value)); } static void mkcbr (callback::ref cb, slot *s) { (*cb) (s->key, R::ret (&s->value)); } public: qhash () {} void clear () { core::traverse (wrap (this, &qhash::delslot)); core::clear (); } ~qhash () { clear (); } #if 0 void traverse (callback ::ref cb) { core::traverse (wrap (mkcb, cb)); } #endif void traverse (callback ::ref cb) { core::traverse (wrap (mkcbr, cb)); } void insert (const K &k) { if (slot *s = getslot (k)) s->value = V (); else core::insert_val (New slot (k, V ()), hash (k)); } void insert (const K &k, CREF (V) v) { if (slot *s = getslot (k)) s->value = v; else core::insert_val (New slot (k, v), hash (k)); } void insert (const K &k, NCREF (V) v) { if (slot *s = getslot (k)) s->value = v; else core::insert_val (New slot (k, v), hash (k)); } void remove (const K &k) { if (slot *s = getslot (k)) delslot (s); } typename R::type operator[] (const K &k) { if (slot *s = getslot (k)) return R::ret (&s->value); else return R::ret (NULL); } typename R::const_type operator[] (const K &k) const { if (slot *s = getslot (k)) return R::const_ret (&s->value); else return R::const_ret (NULL); } }; template struct qhash_slot { ihash_entry link; const K key; qhash_slot (const K &k) : key (k) {} }; template, class E = equals, // XXX - We need to kludge this for both g++ and KCC ihash_entry > qhash_slot::*kludge = &qhash_slot::link> class bhash // : public ihash_core, kludge> { typedef qhash_slot slot; typedef ihash_core core; const E eq; const H hash; slot *getslot (const K &k) const { slot *s; for (s = lookup_val (hash (k)); s && !eq (s->key, k); s = next_val (s)) ; return s; } void delslot (slot *s) { core::remove (s); delete s; } static void mkcb (callback::ref cb, qhash_slot *s) { (*cb) (s->key); } static void mkcbr (callback::ref cb, qhash_slot *s) { (*cb) (s->key); } public: bhash () {} void clear () { deleteall (); } ~bhash () { clear (); } bool insert (const K &k) { if (!getslot (k)) { core::insert_val (New slot (k), hash (k)); return true; } return false; } void remove (const K &k) { if (slot *s = getslot (k)) delslot (s); } bool operator[] (const K &k) const { return getslot (k); } #if 0 void traverse (callback ::ref cb) { core::traverse (wrap (mkcb, cb)); } #endif void traverse (callback ::ref cb) { core::traverse (wrap (mkcbr, cb)); } }; #endif /* !_QHASH_H_ */