/* Public domain */ #ifndef _PERCGI_TABLE_H_ #define _PERCGI_TABLE_H_ #define TABLE_MAX_FIELDS 16 typedef struct tbl_entry { char *key; /* First field */ char *fields[TABLE_MAX_FIELDS]; /* Extra fields */ SLIST_ENTRY(tbl_entry) ents; SLIST_ENTRY(tbl_entry) bents; } TBL_Entry; typedef struct tbl_bucket { SLIST_HEAD(,tbl_entry) ents; unsigned int nEnts; } TBL_Bucket; typedef struct tbl { char *data; /* File data (if file-backed) */ size_t dataSize; Uint nFields; /* Number of fields per entry */ TBL_Bucket *buckets; /* Hash table */ Uint nBuckets; SLIST_HEAD(,tbl_entry) ents; /* Flat list */ const char *sep; /* Field separator character(s) */ } TBL; #define TBL_FOREACH(ent, table) \ SLIST_FOREACH((ent), &(table)->ents, ents) /* Flags for TBL_Load() */ #define TBL_LOAD_NOERRORS 0x01 /* Fail if a line cannot be parsed */ #define TBL_LOAD_NODUPS 0x02 /* Fail if duplicate keys are found */ __BEGIN_DECLS TBL *TBL_New(Uint, Uint); void TBL_Init(TBL *, Uint, Uint); TBL *TBL_Load(const char *, Uint, const char *, int); int TBL_Save(TBL *, const char *); void TBL_SaveJS(TBL *, VAR *); void TBL_Destroy(TBL *); void TBL_Free(TBL *); TBL_Entry *TBL_Lookup(TBL *, const char *, Uint); char *TBL_LookupField(TBL *, const char *, Uint); int TBL_CopyField(TBL *, const char *, Uint, char *, size_t) BOUNDED_ATTRIBUTE(__string__, 4, 5); int TBL_InsertUnique(TBL *, TBL_Entry *); int TBL_Delete(TBL *, const char *); static __inline__ Uint TBL_Hash(TBL *t, const char *key) { Uint h; u_char *p; for (h = 0, p = (u_char *)key; *p != '\0'; p++) { h = 31 * h + *p; } return (h % t->nBuckets); } static __inline__ void TBL_Insert(TBL *ta, TBL_Entry *ent, Uint h) { SLIST_INSERT_HEAD(&ta->buckets[h].ents, ent, bents); SLIST_INSERT_HEAD(&ta->ents, ent, ents); ta->buckets[h].nEnts++; } __END_DECLS #endif /* _PERCGI_TABLE_H_ */