summaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-04-16 22:26:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-04-16 22:26:12 -0700
commit307ddfe0bbb4ad7997cccbda5abb750b599b10be (patch)
tree824d8242bdac63f8234a596af1b71e2cb0bed9db /hash.c
parent8b50725da4d58aa77ba61c4270c5407438b2209d (diff)
downloadtxr-307ddfe0bbb4ad7997cccbda5abb750b599b10be.tar.gz
txr-307ddfe0bbb4ad7997cccbda5abb750b599b10be.tar.bz2
txr-307ddfe0bbb4ad7997cccbda5abb750b599b10be.zip
New buffer data type.
Work in progress. * gc.c (finalize): Add cast to switch expression so gcc flags when we are missing one of the enumerations. Handle new BUF enum to free dynamic buffers. (mark_obj): Mark len and size fields of buf, in case they aren't just nil or integers. * hash.c (hash_buf): New static function. (equal_hash): Route BUF type to hash_buf. * lib.c (buf_s): New symbol variable. (code2type): Handle BUF. (equal): Handle BUF using memcmp on the data. (obj_init): Intern buf symbol and initialize buf_s. * lib.h (type_t): New enum member BUF. (struct buf): New type. (union obj): New member b, of struct buf type. (buf_s): Declared.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/hash.c b/hash.c
index d1a60da5..8d27892f 100644
--- a/hash.c
+++ b/hash.c
@@ -107,6 +107,44 @@ static unsigned long hash_c_str(const wchar_t *str)
return h;
}
+static unsigned long hash_buf(const mem_t *ptr, cnum size)
+{
+ int count = hash_str_limit;
+ unsigned long h = 0;
+
+ for (; size >= 4 && count--; size -= 4, ptr += 4) {
+ unsigned long el = (((unsigned long) ptr[0]) << 24 |
+ ((unsigned long) ptr[1]) << 16 |
+ ((unsigned long) ptr[2]) << 8 |
+ ((unsigned long) ptr[3]));
+ unsigned long g;
+ h = (h << 4) + el;
+ g = h & 0x7C000000;
+ h = h ^ (g >> 26) ^ g;
+ ptr += 4;
+ }
+
+ if (count) {
+ unsigned long el = 0;
+ unsigned long g;
+ switch (size) {
+ case 0:
+ break;
+ case 3:
+ el = *ptr++;
+ case 2:
+ el = el << 8 | *ptr++;
+ case 1:
+ el = el << 8 | *ptr++;
+ h = (h << 4) + el;
+ g = h & 0x7C000000;
+ h = h ^ (g >> 26) ^ g;
+ ptr += 4;
+ }
+ }
+ return h;
+}
+
static cnum hash_double(double n)
{
#ifdef HAVE_UINTPTR_T
@@ -191,6 +229,8 @@ cnum equal_hash(val obj, int *count)
case RNG:
return (equal_hash(obj->rn.from, count)
+ 32 * (equal_hash(obj->rn.to, count) & (NUM_MAX / 16))) & NUM_MAX;
+ case BUF:
+ return hash_buf(obj->b.data, c_num(obj->b.len));
}
internal_error("unhandled case in equal function");