示例#1
0
文件: lookup3.c 项目: GerHobbelt/POPT
/* -------------------------------------------------------------------- */
uint32_t jlu32w(uint32_t h, const uint32_t *k, size_t size)
{
    uint32_t a = _JLU3_INIT(h, (size * sizeof(*k)));
    uint32_t b = a;
    uint32_t c = a;

    if (k == NULL)
	goto exit;

    /*----------------------------------------------- handle most of the key */
    while (size > 3) {
	a += k[0];
	b += k[1];
	c += k[2];
	_JLU3_MIX(a,b,c);
	size -= 3;
	k += 3;
    }

    /*----------------------------------------- handle the last 3 uint32_t's */
    switch (size) {
    case 3 : c+=k[2];
    case 2 : b+=k[1];
    case 1 : a+=k[0];
	_JLU3_FINAL(a,b,c);
	/*@fallthrough@*/
    case 0:
	break;
    }
    /*---------------------------------------------------- report the result */
exit:
    return c;
}
示例#2
0
/* -------------------------------------------------------------------- */
uint32_t jlu32l(uint32_t h, const void *key, size_t size)
{
    union {
        const void *ptr;
        size_t i;
    } u;
    uint32_t a = _JLU3_INIT(h, size);
    uint32_t b = a;
    uint32_t c = a;

    if (key == NULL)
        goto exit;

    u.ptr = key;
    if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
        const uint32_t *k = (const uint32_t *)key;	/* read 32-bit chunks */
#ifdef	VALGRIND
        const uint8_t  *k8;
#endif

        /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
        while (size > 12) {
            a += k[0];
            b += k[1];
            c += k[2];
            _JLU3_MIX(a,b,c);
            size -= 12;
            k += 3;
        }

        /*------------------------- handle the last (probably partial) block */
        /*
         * "k[2]&0xffffff" actually reads beyond the end of the string, but
         * then masks off the part it's not allowed to read.  Because the
         * string is aligned, the masked-off tail is in the same word as the
         * rest of the string.  Every machine with memory protection I've seen
         * does it on word boundaries, so is OK with this.  But VALGRIND will
         * still catch it and complain.  The masking trick does make the hash
         * noticably faster for short strings (like English words).
         */
#ifndef VALGRIND

        switch (size) {
        case 12:
            c += k[2];
            b+=k[1];
            a+=k[0];
            break;
        case 11:
            c += k[2]&0xffffff;
            b+=k[1];
            a+=k[0];
            break;
        case 10:
            c += k[2]&0xffff;
            b+=k[1];
            a+=k[0];
            break;
        case  9:
            c += k[2]&0xff;
            b+=k[1];
            a+=k[0];
            break;
        case  8:
            b += k[1];
            a+=k[0];
            break;
        case  7:
            b += k[1]&0xffffff;
            a+=k[0];
            break;
        case  6:
            b += k[1]&0xffff;
            a+=k[0];
            break;
        case  5:
            b += k[1]&0xff;
            a+=k[0];
            break;
        case  4:
            a += k[0];
            break;
        case  3:
            a += k[0]&0xffffff;
            break;
        case  2:
            a += k[0]&0xffff;
            break;
        case  1:
            a += k[0]&0xff;
            break;
        case  0:
            goto exit;
        }

#else /* make valgrind happy */

        k8 = (const uint8_t *)k;
        switch (size) {
        case 12:
            c += k[2];
            b+=k[1];
            a+=k[0]	break;
        case 11:
            c += ((uint32_t)k8[10])<<16;	/*@fallthrough@*/
        case 10:
            c += ((uint32_t)k8[9])<<8;	/*@fallthrough@*/
        case  9:
            c += k8[8];			/*@fallthrough@*/
        case  8:
            b += k[1];
            a+=k[0];
            break;
        case  7:
            b += ((uint32_t)k8[6])<<16;	/*@fallthrough@*/
        case  6:
            b += ((uint32_t)k8[5])<<8;	/*@fallthrough@*/
        case  5:
            b += k8[4];			/*@fallthrough@*/
        case  4:
            a += k[0];
            break;
        case  3:
            a += ((uint32_t)k8[2])<<16;	/*@fallthrough@*/
        case  2:
            a += ((uint32_t)k8[1])<<8;	/*@fallthrough@*/
        case  1:
            a += k8[0];
            break;
        case  0:
            goto exit;
        }

#endif /* !valgrind */

    } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {