/* Copyright 1989-93 GROUPE BULL -- See license conditions in file COPYRIGHT */
/************************\
* 			 *
*  KlO  Hash	  	 *
*  DEFINITIONS		 *
* 			 *
\************************/

#ifndef INCLUDE_Kl_HASH_H
#define INCLUDE_Kl_HASH_H

/* type */

typedef struct _KlHashCell {		/* a cell of the linked lists */
    struct _KlHashCell *next;
    KlO key;
    KlO object;
}          *KlHashCell;

typedef struct _KlHashCell2 {		/* a cell of the linked lists */
    KlHashCell cell;
    KlHashCell next;
}          *KlHashCell2;

typedef struct _KlHash {
    KlKLONE_HEADER;
    int size;				/* number of stored objs */
    KlHashCell *table;			/* array of linked lists */
    int limit;				/* room for N entries */
    unsigned int ref_counted;		/* what is refcounted? */
    KlHashCell2 curcell;			/* for dohash */
}      *KlHash;

/* ref_counted flags */
#define KlHashRefK 1			/* keys are refcounted */
#define KlHashRefV 2			/* values are refcounted */
#define KlHashFrozen 4			/* table frozen (during KlDoHash) */

/* exported functions */

extern KlHash KlHashAlloc();
extern KlHash KlHashMake();
extern KlO KlHashGet();
extern KlO KlHashPut();
extern KlO KlHashDelete();
extern KlO KlHashGetEqual();
extern KlO KlHashPutEqual();
extern KlO KlHashDeleteEqual();
extern KlO KlHashPrint();
extern KlO KlHashFree();
extern KlO KlHashCoerceListToHash();
extern KlO KlHashRestore();

/* to iterate on the ht elements */
#define KlHashFORBEGIN(ht, cell) { \
    KlHashCell *slot = ht->table, *last_cell = slot + ht->limit, cell; \
    for (;slot < last_cell; slot++) { \
	if (*slot) { \
	    for (cell = *slot; cell; cell = cell->next)
#define KlHashFOREND 	    }}}

/* to iterate on the ht elements when the table can change in the loop */
#define KlHashProtectedFORBEGIN(ht, cell) { \
    KlHashCell *slot = ht->table, *last_cell = slot + ht->limit, cell; \
    struct _KlHashCell2 htc; \
    ht->curcell = &htc;\
    KlUnwindProtectStatementBefore(KlHashRestore, ht, 0); \
    for (;slot < last_cell; slot++) { \
	if (*slot) { \
	    for (cell = *slot; cell; cell = ht->curcell->next) { \
                ht->curcell->cell = cell; ht->curcell->next = cell->next; 
								     
#define KlHashProtectedFOREND(ht, cell) 	    }}} \
 KlUnwindProtectStatementAfter(KlHashRestore, ht, 0);}

/* exported variables */

EXT int KlHashInitialSize INIT(7);
EXT int KlHashInitialized INIT(0);

/* methods */

EXT KlType KlHashType;
EXT KlType KlStructuredType;

#define KlIsAHash(obj) ((obj)->type == KlHashType)
#define KlMustBeHash(obj, n) KlArgumentMustBe(obj, n, KlHashType)

#endif					/* INCLUDE_Kl_HASH_H */


syntax highlighted by Code2HTML, v. 0.9.1