//
//  wchiter.h    Definitions for the WATCOM Container Hash Iterator Classes
//
//  Copyright by WATCOM International Corp. 1988-1996.  All rights reserved.
//

#ifndef _WCHITER_H_INCLUDED

#ifndef __cplusplus
#error wchiter.h is for use with C++
#endif

#include <wcdefs.h>
#include <wcexcept.h>
#include <wchash.h>



//
// The WCHashIterBase is the base class for all hash iterator classes
//
// WCIterExcept is used as a base class to provide exception handling
//
//

class WCHashIterBase : public WCIterExcept {
private:
    typedef WCSLink BaseHashLink;

protected:
    const WCHashBase *          curr_hash;
    WCIsvSListIter<BaseHashLink> bucket_iter;
    unsigned                    curr_bucket;
    int                         at_end;

    WCbool base_advance();

    inline WCbool base_hash_valid() const {
        return( ( curr_hash != 0 )&&( curr_hash->num_buckets > 0 ) );
    };

public:
    inline WCHashIterBase() : curr_hash( 0 ), bucket_iter()
                                , curr_bucket( 0 ), at_end( 0 ) {};

    inline WCHashIterBase( const WCHashBase& hash )
                : curr_hash( &hash ), bucket_iter() {
        reset();
    };

    inline virtual ~WCHashIterBase() = 0;

    void reset();
};


WCHashIterBase::~WCHashIterBase() {};



//
// The WCValHashTableIter is the iterator for the WCValHashTable class
//
// WCIterExcept is used as a base class to provide exception handling
//

template<class Type>
class WCValHashTableIter : public WCHashIterBase {
protected:
    typedef WCHashLink<Type> HashLink;
    
    // get the current hashlink object, or 0 if current undefined
    WCHashLink<Type> *base_curr_hashlink() const;

public:
    inline WCValHashTableIter() {};

    inline WCValHashTableIter( const WCValHashTable<Type>& hash )
                : WCHashIterBase( hash ) {};

    inline virtual ~WCValHashTableIter() {};

    inline const WCValHashTable<Type> *container() const {
        if( curr_hash == 0 ) {
            base_throw_undef_iter();
        }
        return( (const WCValHashTable<Type> *)curr_hash );
    };

    Type current() const;

    inline void reset() {
        WCHashIterBase::reset();
    };

    inline void reset( const WCValHashTable<Type> &hash ) {
        curr_hash = &hash;
        reset();
    };

    inline WCbool operator++() {
        return( base_advance() );
    }

    inline WCbool operator()() {
        return( base_advance() );
    }
};


template <class Type>
WCHashLink<Type> *WCValHashTableIter<Type>::base_curr_hashlink() const {
    HashLink *link = 0;
    if( base_hash_valid() ) {
        link = (HashLink *)bucket_iter.current();
    } 
    return( link );
};


template <class Type>
Type WCValHashTableIter<Type>::current() const {
    HashLink *link = base_curr_hashlink();
    if( link == 0 ) {
        // bucket_iter is off end or no hash to iterate over
        base_throw_undef_item();
        Type temp;
        return( temp );
    }
    return( link->data );
};




//
// The WCPtrHashTableIter is the iterator for the WCPtrHashTable class.
//

template<class Type>
class WCPtrHashTableIter : public WCValHashTableIter<void *> {
public:
    inline WCPtrHashTableIter() {};

    inline WCPtrHashTableIter( const WCPtrHashTable<Type>& hash )
                : WCValHashTableIter( hash ) {};

    inline virtual ~WCPtrHashTableIter() {};

    inline const WCPtrHashTable<Type> *container() const {
        return( (const WCPtrHashTable<Type> *)WCValHashTableIter::container() );
    };

    inline Type *current() const {
        return( (Type *)WCValHashTableIter::current() );
    };

    inline void reset() {
        WCValHashTableIter::reset();
    };

    inline void reset( const WCPtrHashTable<Type> &hash ) {
        WCValHashTableIter::reset( hash );
    };
};




//
// The WCValHashSetIter is the iterator for the WCValHashSet class.
//

template<class Type>
class WCValHashSetIter : public WCValHashTableIter<Type> {
public:
    inline WCValHashSetIter() {};

    inline WCValHashSetIter( const WCValHashSet<Type>& hash )
                : WCValHashTableIter( hash ) {};

    inline virtual ~WCValHashSetIter() {};

    inline const WCValHashSet<Type> *container() const {
        return( (const WCValHashSet<Type> *)WCValHashTableIter::container() );
    };

    inline void reset() {
        WCValHashTableIter::reset();
    };

    inline void reset( const WCValHashSet<Type> &hash ) {
        WCValHashTableIter::reset( hash );
    };
};




//
// The WCPtrHashSetIter is the iterator for the WCPtrHashSet class.
//

template<class Type>
class WCPtrHashSetIter : public WCPtrHashTableIter<Type> {
public:
    inline WCPtrHashSetIter() {};

    inline WCPtrHashSetIter( const WCPtrHashSet<Type>& hash )
                : WCPtrHashTableIter( hash ) {};

    inline virtual ~WCPtrHashSetIter() {};

    inline const WCPtrHashSet<Type> *container() const {
        return( (const WCPtrHashSet<Type> *)WCPtrHashTableIter::container() );
    };

    inline void reset() {
        WCPtrHashTableIter::reset();
    };

    inline void reset( const WCPtrHashSet<Type> &hash ) {
        WCPtrHashTableIter::reset( hash );
    };
};




//
// The WCValHashDictIter is the iterator for the WCValHashDict class.
//
// This class inherits privately to hide the current member function.
//

template<class Key, class Value>
class WCValHashDictIter
        : private WCValHashTableIter<WCHashDictKeyVal<Key, Value > > {
public:
    inline WCValHashDictIter() {};

    inline WCValHashDictIter( const WCValHashDict<Key, Value>& hash )
                : WCValHashTableIter( hash ) {};

    inline virtual ~WCValHashDictIter() {};

    inline const WCValHashDict<Key, Value> *container() const {
        return( (const WCValHashDict<Key, Value> *)WCValHashTableIter
                                                        ::container() );
    };

    inline wciter_state exceptions() const {
        return( WCValHashTableIter::exceptions() );
    };

    inline wciter_state exceptions( wciter_state const set_flags ) {
        return( WCValHashTableIter::exceptions( set_flags ) );
    };

    Key key() const;

    inline void reset() {
        WCValHashTableIter::reset();
    };

    inline void reset( const WCValHashDict<Key, Value> &hash ) {
        WCValHashTableIter::reset( hash );
    };

    Value value() const;

    inline WCbool operator++() {
        return( WCValHashTableIter::operator++() );
    };

    inline WCbool operator()() {
        return( WCValHashTableIter::operator()() );
    };
};


template <class Key, class Value>
Key WCValHashDictIter<Key, Value>::key() const {
    HashLink *link = base_curr_hashlink();
    if( link == 0 ) {
        // bucket_iter is off end or no hash to iterate over
        base_throw_undef_item();
        Key temp;
        return( temp );
    }
    return( link->data.key );
};


template <class Key, class Value>
Value WCValHashDictIter<Key, Value>::value() const {
    HashLink *link = base_curr_hashlink();
    if( link == 0 ) {
        // bucket_iter is off end or no hash to iterate over
        base_throw_undef_item();
        Value temp;
        return( temp );
    }
    return( link->data.value );
};




//
// The WCPtrHashDictIter is the iterator for the WCPtrHashDict class.
//

template<class Key, class Value>
class WCPtrHashDictIter
        : public WCValHashDictIter<void *, void *> {
public:
    inline WCPtrHashDictIter() {};

    inline WCPtrHashDictIter( const WCPtrHashDict<Key, Value>& hash )
                : WCValHashDictIter( hash ) {};

    inline virtual ~WCPtrHashDictIter() {};

    inline const WCPtrHashDict<Key, Value> *container() const {
        return( (const WCPtrHashDict<Key, Value> *)WCValHashDictIter
                                                        ::container() );
    };

    inline Key * key() const {
        return( (Key *)WCValHashDictIter::key() );
    };

    inline void reset() {
        WCValHashDictIter::reset();
    };

    inline void reset( const WCPtrHashDict<Key, Value> &hash ) {
        WCValHashDictIter::reset( hash );
    };

    Value *value() const {
        return( (Value *)WCValHashDictIter::value() );
    };
};


#define _WCHITER_H_INCLUDED
#endif
