Copyright (C) 1994, Digital Equipment Corp. GENERIC MODULEWhereTableList (Key, Value, KeyValueTable);
Key.T and Value.T are types that are not open array types
and Key contains
PROCEDURE Equal(k1, k2: Key.T): BOOLEAN;
and KeyValueTableList is the instantiation of the generic interface
TableList with the interfaces Key and Value.
Equal must be an equivalence relation.
Equal may be declared with a parameter mode of either VALUE or
READONLY, but not VAR.
IMPORT RefList;
REVEAL
T = KeyValueTable.T OBJECT
METHODS
init(): T;
keyEqual(READONLY k1, k2: Key.T): BOOLEAN
END BRANDED OBJECT
list: RefList.T; (* An association list. *)
sz: CARDINAL;
OVERRIDES
get := Get;
put := Put;
delete := Delete;
size := Size;
iterate := Iterate;
init := Init;
keyEqual := KeyEqual;
END (* OBJECT *);
TYPE
ListIter = KeyValueTable.Iterator OBJECT
list: RefList.T;
OVERRIDES
next := Next;
END (* OBJECT *);
PROCEDURE Init (tbl: T): T =
BEGIN tbl.list := NIL; tbl.sz := 0; RETURN tbl END Init;
PROCEDURE Get (tbl: T; READONLY key: Key.T; VAR val: Value.T): BOOLEAN =
VAR l := tbl.list; BEGIN
WHILE l # NIL DO
VAR pair: RefList.T := l.head; BEGIN
IF Key.Equal(pair.head, key) THEN
val := pair.tail.head;
RETURN TRUE
END (* IF *)
END (* BEGIN *);
l := l.tail
END (* WHILE *);
RETURN FALSE
END Get;
PROCEDURE Put (tbl: T; READONLY key: Key.T; READONLY val: Value.T): BOOLEAN =
VAR l := tbl.list; BEGIN
WHILE l # NIL DO
VAR pair: RefList.T := l.head; BEGIN
IF Key.Equal(pair.head, key) THEN
pair.tail.head := val;
RETURN TRUE
END (* IF *)
END;
l := l.tail
END (* WHILE *);
tbl.list := RefList.Cons(RefList.List2(key, val), tbl.list);
INC(tbl.sz);
RETURN FALSE
END Put;
PROCEDURE Delete (tbl: T; READONLY key: Key.T; VAR val: Value.T): BOOLEAN =
VAR l := tbl.list; prev: RefList.T := NIL; BEGIN
WHILE l # NIL DO
VAR pair: RefList.T := l.head; BEGIN
IF Key.Equal(pair.head, key) THEN
val := pair.tail.head;
IF prev = NIL THEN
tbl.list := l.tail
ELSE
prev.tail := l.tail
END (* IF *);
DEC(tbl.sz);
RETURN TRUE
END (* IF *)
END (* BEGIN *);
prev := l;
l := l.tail
END (* WHILE *);
RETURN FALSE
END Delete;
PROCEDURE Size (tbl: T): CARDINAL =
BEGIN RETURN tbl.sz END Size;
PROCEDURE Iterate (tbl: T): KeyValueTable.Iterator =
BEGIN RETURN NEW(ListIter, list := tbl.list)
END Iterate;
PROCEDURE KeyEqual (<*UNUSED*> tbl: T; READONLY k1, k2: Key.T): BOOLEAN =
BEGIN RETURN Key.Equal(k1, k2) END KeyEqual;
******************
Iterator methods
******************
PROCEDURENext (i: ListIter; VAR key: Key.T; VAR val: Value.T): BOOLEAN = BEGIN IF i.list = NIL THEN RETURN FALSE ELSE VAR pair: RefList.T := i.list.head; BEGIN key := pair.head; val := pair.tail.head END (* BEGIN *); i.list := i.list.tail; RETURN TRUE END (* IF *) END Next; BEGIN END TableList.