diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-04-16 22:26:12 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-04-16 22:26:12 -0700 |
commit | 307ddfe0bbb4ad7997cccbda5abb750b599b10be (patch) | |
tree | 824d8242bdac63f8234a596af1b71e2cb0bed9db /hash.c | |
parent | 8b50725da4d58aa77ba61c4270c5407438b2209d (diff) | |
download | txr-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.c | 40 |
1 files changed, 40 insertions, 0 deletions
@@ -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"); |