summaryrefslogtreecommitdiff
path: root/hashtable.sml
diff options
context:
space:
mode:
authorVladimir Azarov <avm@intermediate-node.net>2025-03-27 23:31:10 +0100
committerVladimir Azarov <avm@intermediate-node.net>2025-03-27 23:31:10 +0100
commitd7d4830443f1e385af862462f976553c8a9033e1 (patch)
tree0fbdef6579a26e962b249c55e6ae407cd5b8dfda /hashtable.sml
parent11e14dd4b93154964c87fc97cfcee62c52edf97a (diff)
Hashtable-based findKeyword function
Diffstat (limited to 'hashtable.sml')
-rw-r--r--hashtable.sml64
1 files changed, 64 insertions, 0 deletions
diff --git a/hashtable.sml b/hashtable.sml
new file mode 100644
index 0000000..24e5bba
--- /dev/null
+++ b/hashtable.sml
@@ -0,0 +1,64 @@
+structure Hashtable :> HASHTABLE = struct
+ (* (Array, (cells occupied, total size)) *)
+ type 'a t = ((string * 'a) option) array * (int * int)
+
+ exception HashtableFull
+ exception Exists
+
+ fun create size = (Array.array (size, NONE), (0, size))
+
+ val fillLimit = 0.75
+
+ val ` = Word32.fromInt
+
+ fun hashFunc key =
+ let
+ open Word32
+ in
+ List.foldl (fn (x, acc) => acc * `31 + `(ord x)) (`0) $ explode key
+ end
+
+ fun insert (buf, (taken, total)) key value =
+ if Real.fromInt (taken + 1) / Real.fromInt total > fillLimit then
+ raise HashtableFull
+ else
+ let
+ open Array
+ val hash = hashFunc key
+
+ (* TODO: use bitwise manipulation instead of mod *)
+ val i = ref $ Word32.toInt $ Word32.mod (hash, `(length buf))
+ val flag = ref true
+ in
+ while !flag do (
+ case sub (buf, !i) of
+ NONE => (update (buf, !i, SOME (key, value)); flag := false)
+ | SOME (key', _) =>
+ if key' = key then
+ raise Exists
+ else
+ i := (!i + 1) mod (length buf)
+ )
+ end
+
+ fun lookup (buf, _) key =
+ let
+ open Array
+ val hash = hashFunc key
+
+ val i = ref $ Word32.toInt $ Word32.mod (hash, `(length buf))
+ val flag = ref true
+ val result = ref NONE
+ in
+ while !flag do (
+ case sub (buf, !i) of
+ SOME (key', value) =>
+ if key' = key then
+ (result := SOME value; flag := false)
+ else
+ i := (!i + 1) mod (length buf)
+ | NONE => flag := false
+ );
+ !result
+ end
+end