
/* gdbm_dict.q: provide an hdict-like interface to gdbm files 05-06-03 AG */

import gdbm;

/* Open a gdbm file in read/write mode. The file is created if necessary. Note
   that opening the file in read/write mode prevents multiple accesses to the
   same database file. If you only need to inspect the database you might wish
   to open the file read-only instead. */

gdbm_dict NAME:String	= gdbm_open NAME 512 GDBM_WRCREAT 0666;

/* Encode arbitrary expressions as byte strings. In OO languages this is also
   called "serialization". To simplify matters, this implementation uses the
   standard textual encoding. For more elaborate applications you might have
   to implement a suitable binary encoding instead. */

encode DATA		= bytestr (str DATA);

decode DATA		= val (bstr DATA);

/* Size of the dictionary (number of keys). */

#DBF:GdbmFile		= #keys DBF;

/* Retrieve a value from the dictionary. */

DBF:GdbmFile!KEY	= decode (gdbm_fetch DBF KEY) if gdbm_exists DBF KEY
			    where KEY = encode KEY;

/* Check whether the dictionary is empty. */

null DBF:GdbmFile	= not isbytestr (gdbm_firstkey DBF);

/* Check for membership. */

member DBF:GdbmFile KEY	= gdbm_exists DBF (encode KEY);

/* List the contents of the dictionary. */

list DBF:GdbmFile	= zip (map decode KEYS) (map decode VALS)
			    where KEYS = while isbytestr
			      (gdbm_nextkey DBF) (gdbm_firstkey DBF),
			      VALS = map (gdbm_fetch DBF) KEYS;

keys DBF:GdbmFile	= map decode KEYS
			    where KEYS = while isbytestr
			      (gdbm_nextkey DBF) (gdbm_firstkey DBF);

vals DBF:GdbmFile	= map decode VALS
			    where KEYS = while isbytestr
			      (gdbm_nextkey DBF) (gdbm_firstkey DBF),
			      VALS = map (gdbm_fetch DBF) KEYS;

/* Insert and delete items. Note that the semantics of these operations are
   rather different from the standard dictionary operations, since they
   involve side-effects. Unlike HDict's the GdbmFile objects are mutable,
   hence changing the contents of the dictionary affects all its copies. */

insert DBF:GdbmFile (KEY,VAL)
			= gdbm_store DBF (encode KEY) (encode VAL)
			  GDBM_REPLACE || DBF;

update DBF:GdbmFile KEY VAL
			= gdbm_store DBF (encode KEY) (encode VAL)
			  GDBM_REPLACE || DBF;

delete DBF:GdbmFile KEY	= gdbm_delete DBF (encode KEY) || DBF;
