diff --git a/noun/retrieve.c b/noun/retrieve.c index b919ef47e..6fdb8e651 100644 --- a/noun/retrieve.c +++ b/noun/retrieve.c @@ -1485,7 +1485,12 @@ u3r_mug_bytes(const c3_y *buf_y, c3_w u3r_mug_chub(c3_d num_d) { - return u3r_mug_bytes((c3_y*)&num_d, 8); + c3_w buf_w[2]; + + buf_w[0] = (c3_w)(num_d & 0xffffffffULL); + buf_w[1] = (c3_w)(num_d >> 32ULL); + + return u3r_mug_words(buf_w, 2); } /* u3r_mug_string(): Compute the mug of `a`, LSB first. @@ -1501,7 +1506,17 @@ u3r_mug_string(const c3_c *a_c) c3_w u3r_mug_words(const c3_w* key_w, c3_w len_w) { - return u3r_mug_bytes((c3_y*)key_w, 4 * len_w); + c3_w siz_w = 0; + c3_w byt_w = 0; + c3_w wor_w; + + while ( siz_w < len_w ) { + wor_w = key_w[siz_w]; + byt_w += _(u3a_is_cat(wor_w)) ? u3r_met(3, wor_w) : 4; + siz_w++; + } + + return u3r_mug_bytes((c3_y*)key_w, byt_w); } /* u3r_mug_both(): Join two mugs. diff --git a/tests/hash_tests.c b/tests/hash_tests.c index f3e190c06..0acd279fd 100644 --- a/tests/hash_tests.c +++ b/tests/hash_tests.c @@ -53,6 +53,46 @@ _test_mug(void) fprintf(stderr, "fail (h)\r\n"); exit(1); } + + { + // stick some zero bytes in a string + u3_noun str = u3kc_lsh(3, 1, + u3kc_mix(u3qc_bex(212), + u3i_string("abcdefjhijklmnopqrstuvwxyz"))); + + c3_w byt_w = u3r_met(3, str); + c3_w wor_w = u3r_met(5, str); + c3_y* str_y = c3_malloc(byt_w); + c3_w* str_w = c3_malloc(wor_w); + c3_d str_d = 0; + + u3r_bytes(0, byt_w, str_y, str); + u3r_words(0, wor_w, str_w, str); + + str_d |= str_w[0]; + str_d |= ((c3_d)str_w[1] << 32ULL); + + if ( 0x34d08717 != u3r_mug(str) ) { + fprintf(stderr, "fail (i) (1) \r\n"); + exit(1); + } + if ( 0x34d08717 != u3r_mug_bytes(str_y, byt_w) ) { + fprintf(stderr, "fail (i) (2)\r\n"); + exit(1); + } + if ( 0x34d08717 != u3r_mug_words(str_w, wor_w) ) { + fprintf(stderr, "fail (i) (3)\r\n"); + exit(1); + } + if ( u3r_mug_words(str_w, 2) != u3r_mug_chub(str_d) ) { + fprintf(stderr, "fail (i) (4)\r\n"); + exit(1); + } + + free(str_w); + free(str_y); + u3z(str); + } } /* main(): run all test cases.