/* $XConsortium: table2.h,v 1.3 94/06/03 21:41:06 matt Exp $ */ /* * Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University * Copyright (c) 1991 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Stanford and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Stanford and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * Object association table with 2 keys. */ #ifndef table2_h #define table2_h #include "types.h" #if !defined(UNIXCPP) #define __Table2Entry(Table2) Table2##_Entry #define Table2Entry(Table2) __Table2Entry(Table2) #define __Table2Iterator(Table2) Table2##_Iterator #define Table2Iterator(Table2) __Table2Iterator(Table2) #else #define __Table2Entry(Table2) Table2/**/_Entry #define Table2Entry(Table2) __Table2Entry(Table2) #define __Table2Iterator(Table2) Table2/**/_Iterator #define Table2Iterator(Table2) __Table2Iterator(Table2) #endif #define declareTable2(Table2,Key1,Key2,Value) \ class Table2Entry(Table2); \ \ class Table2 { \ public: \ Table2(int); \ ~Table2(); \ \ void insert(Key1, Key2, Value); \ Boolean find(Value&, Key1, Key2); \ void remove(Key1, Key2); \ private: \ friend class Table2Iterator(Table2); \ \ int size_; \ Table2Entry(Table2)** first_; \ Table2Entry(Table2)** last_; \ \ Table2Entry(Table2)*& probe(Key1, Key2); \ }; \ \ class Table2Entry(Table2) { \ private: \ friend class Table2; \ friend class Table2Iterator(Table2); \ \ Key1 key1_; \ Key2 key2_; \ Value value_; \ Table2Entry(Table2)* chain_; \ }; \ \ class Table2Iterator(Table2) { \ public: \ Table2Iterator(Table2)(Table2&); \ \ Key1& cur_key1(); \ Key2& cur_key2(); \ Value& cur_value(); \ Boolean more(); \ Boolean next(); \ private: \ Table2Entry(Table2)* cur_; \ Table2Entry(Table2)** entry_; \ Table2Entry(Table2)** last_; \ }; \ \ inline Key1& Table2Iterator(Table2)::cur_key1() { return cur_->key1_; } \ inline Key2& Table2Iterator(Table2)::cur_key2() { return cur_->key2_; } \ inline Value& Table2Iterator(Table2)::cur_value() { return cur_->value_; } \ inline Boolean Table2Iterator(Table2)::more() { return entry_ <= last_; } /* * Predefined hash functions */ #ifndef table_h inline unsigned long key_to_hash(long k) { return (unsigned long)k; } inline unsigned long key_to_hash(const void* k) { return (unsigned long)k; } #endif /* * Table2 implementation */ #define implementTable2(Table2,Key1,Key2,Value) \ Table2::Table2(int n) { \ for (size_ = 32; size_ < n; size_ <<= 1); \ first_ = new Table2Entry(Table2)*[size_]; \ --size_; \ last_ = &first_[size_]; \ for (register Table2Entry(Table2)** e = first_; e <= last_; e++) { \ *e = nil; \ } \ } \ \ Table2::~Table2() { \ delete first_; \ } \ \ inline Table2Entry(Table2)*& Table2::probe(Key1 k1, Key2 k2) { \ return first_[(key_to_hash(k1) ^ key_to_hash(k2)) & size_]; \ } \ \ void Table2::insert(Key1 k1, Key2 k2, Value v) { \ register Table2Entry(Table2)* e = new Table2Entry(Table2); \ e->key1_ = k1; \ e->key2_ = k2; \ e->value_ = v; \ register Table2Entry(Table2)** a = &probe(k1, k2); \ e->chain_ = *a; \ *a = e; \ } \ \ Boolean Table2::find(Value& v, Key1 k1, Key2 k2) { \ for ( \ register Table2Entry(Table2)* e = probe(k1, k2); \ e != nil; \ e = e->chain_ \ ) { \ if (e->key1_ == k1 && e->key2_ == k2) { \ v = e->value_; \ return true; \ } \ } \ return false; \ } \ \ void Table2::remove(Key1 k1, Key2 k2) { \ Table2Entry(Table2)** a = &probe(k1, k2); \ register Table2Entry(Table2)* e = *a; \ if (e != nil) { \ if (e->key1_ == k1 && e->key2_ == k2) { \ *a = e->chain_; \ delete e; \ } else { \ register Table2Entry(Table2)* prev; \ do { \ prev = e; \ e = e->chain_; \ } while (e != nil && (e->key1_ != k1 || e->key2_ != k2)); \ if (e != nil) { \ prev->chain_ = e->chain_; \ delete e; \ } \ } \ } \ } \ \ Table2Iterator(Table2)::Table2Iterator(Table2)(Table2& t) { \ last_ = t.last_; \ for (entry_ = t.first_; entry_ <= last_; entry_++) { \ cur_ = *entry_; \ if (cur_ != nil) { \ break; \ } \ } \ } \ \ Boolean Table2Iterator(Table2)::next() { \ cur_ = cur_->chain_; \ if (cur_ != nil) { \ return true; \ } \ for (++entry_; entry_ <= last_; entry_++) { \ cur_ = *entry_; \ if (cur_ != nil) { \ return true; \ } \ } \ return false; \ } #endif