156 lines
5.7 KiB
Plaintext
156 lines
5.7 KiB
Plaintext
# associative array handling using hashing #
|
|
|
|
# the modes allowed as associative array element values - change to suit #
|
|
MODE AAVALUE = STRING;
|
|
# the modes allowed as associative array element keys - change to suit #
|
|
MODE AAKEY = STRING;
|
|
# nil element value #
|
|
REF AAVALUE nil value = NIL;
|
|
|
|
# an element of an associative array #
|
|
MODE AAELEMENT = STRUCT( AAKEY key, REF AAVALUE value );
|
|
# a list of associative array elements - the element values with a #
|
|
# particular hash value are stored in an AAELEMENTLIST #
|
|
MODE AAELEMENTLIST = STRUCT( AAELEMENT element, REF AAELEMENTLIST next );
|
|
# nil element list reference #
|
|
REF AAELEMENTLIST nil element list = NIL;
|
|
# nil element reference #
|
|
REF AAELEMENT nil element = NIL;
|
|
|
|
# the hash modulus for the associative arrays #
|
|
INT hash modulus = 256;
|
|
|
|
# generates a hash value from an AAKEY - change to suit #
|
|
OP HASH = ( STRING key )INT:
|
|
BEGIN
|
|
INT result := ABS ( UPB key - LWB key ) MOD hash modulus;
|
|
FOR char pos FROM LWB key TO UPB key DO
|
|
result PLUSAB ( ABS key[ char pos ] - ABS " " );
|
|
result MODAB hash modulus
|
|
OD;
|
|
result
|
|
END; # HASH #
|
|
|
|
# a mode representing an associative array #
|
|
MODE AARRAY = STRUCT( [ 0 : hash modulus - 1 ]REF AAELEMENTLIST elements
|
|
, INT curr hash
|
|
, REF AAELEMENTLIST curr position
|
|
);
|
|
|
|
# initialises an associative array so all the hash chains are empty #
|
|
OP INIT = ( REF AARRAY array )REF AARRAY:
|
|
BEGIN
|
|
FOR hash value FROM 0 TO hash modulus - 1 DO ( elements OF array )[ hash value ] := nil element list OD;
|
|
array
|
|
END; # INIT #
|
|
|
|
# gets a reference to the value corresponding to a particular key in an #
|
|
# associative array - the element is created if it doesn't exist #
|
|
PRIO // = 1;
|
|
OP // = ( REF AARRAY array, AAKEY key )REF AAVALUE:
|
|
BEGIN
|
|
REF AAVALUE result;
|
|
INT hash value = HASH key;
|
|
# get the hash chain for the key #
|
|
REF AAELEMENTLIST element := ( elements OF array )[ hash value ];
|
|
# find the element in the list, if it is there #
|
|
BOOL found element := FALSE;
|
|
WHILE ( element ISNT nil element list )
|
|
AND NOT found element
|
|
DO
|
|
found element := ( key OF element OF element = key );
|
|
IF found element
|
|
THEN
|
|
result := value OF element OF element
|
|
ELSE
|
|
element := next OF element
|
|
FI
|
|
OD;
|
|
IF NOT found element
|
|
THEN
|
|
# the element is not in the list #
|
|
# - add it to the front of the hash chain #
|
|
( elements OF array )[ hash value ]
|
|
:= HEAP AAELEMENTLIST
|
|
:= ( HEAP AAELEMENT := ( key
|
|
, HEAP AAVALUE := ""
|
|
)
|
|
, ( elements OF array )[ hash value ]
|
|
);
|
|
result := value OF element OF ( elements OF array )[ hash value ]
|
|
FI;
|
|
result
|
|
END; # // #
|
|
|
|
# returns TRUE if array contains key, FALSE otherwise #
|
|
PRIO CONTAINSKEY = 1;
|
|
OP CONTAINSKEY = ( REF AARRAY array, AAKEY key )BOOL:
|
|
BEGIN
|
|
# get the hash chain for the key #
|
|
REF AAELEMENTLIST element := ( elements OF array )[ HASH key ];
|
|
# find the element in the list, if it is there #
|
|
BOOL found element := FALSE;
|
|
WHILE ( element ISNT nil element list )
|
|
AND NOT found element
|
|
DO
|
|
found element := ( key OF element OF element = key );
|
|
IF NOT found element
|
|
THEN
|
|
element := next OF element
|
|
FI
|
|
OD;
|
|
found element
|
|
END; # CONTAINSKEY #
|
|
|
|
# gets the first element (key, value) from the array #
|
|
OP FIRST = ( REF AARRAY array )REF AAELEMENT:
|
|
BEGIN
|
|
curr hash OF array := LWB ( elements OF array ) - 1;
|
|
curr position OF array := nil element list;
|
|
NEXT array
|
|
END; # FIRST #
|
|
|
|
# gets the next element (key, value) from the array #
|
|
OP NEXT = ( REF AARRAY array )REF AAELEMENT:
|
|
BEGIN
|
|
WHILE ( curr position OF array IS nil element list )
|
|
AND curr hash OF array < UPB ( elements OF array )
|
|
DO
|
|
# reached the end of the current element list - try the next #
|
|
curr hash OF array +:= 1;
|
|
curr position OF array := ( elements OF array )[ curr hash OF array ]
|
|
OD;
|
|
IF curr hash OF array > UPB ( elements OF array )
|
|
THEN
|
|
# no more elements #
|
|
nil element
|
|
ELIF curr position OF array IS nil element list
|
|
THEN
|
|
# reached the end of the table #
|
|
nil element
|
|
ELSE
|
|
# have another element #
|
|
REF AAELEMENTLIST found element = curr position OF array;
|
|
curr position OF array := next OF curr position OF array;
|
|
element OF found element
|
|
FI
|
|
END; # NEXT #
|
|
|
|
# test the associative array #
|
|
BEGIN
|
|
# create an array and add some values #
|
|
REF AARRAY a1 := INIT LOC AARRAY;
|
|
a1 // "k1" := "k1 value";
|
|
a1 // "z2" := "z2 value";
|
|
a1 // "k1" := "new k1 value";
|
|
a1 // "k2" := "k2 value";
|
|
a1 // "2j" := "2j value";
|
|
# iterate over the values #
|
|
REF AAELEMENT e := FIRST a1;
|
|
WHILE e ISNT nil element
|
|
DO
|
|
print( ( " (" + key OF e + ")[" + value OF e + "]", newline ) );
|
|
e := NEXT a1
|
|
OD
|
|
END
|