File: JHash.xs

package info (click to toggle)
libdigest-jhash-perl 0.10-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, stretch
  • size: 176 kB
  • ctags: 22
  • sloc: perl: 297; makefile: 3
file content (99 lines) | stat: -rw-r--r-- 2,714 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

/* Jenkins Hash http://burtleburtle.net/bob/hash/doobs.html */

const int DEBUG = 0;

/* Need to constrain U32 to only 32 bits on 64 bit systems
 * For efficiency we only use the & 0xffffffff if required
 */
#if BYTEORDER > 0x4321 || defined(TRUNCATE_U32)
#define MIX(a,b,c) \
{ \
  a &= 0xffffffff; b &= 0xffffffff; c &= 0xffffffff; \
  a -= b; a -= c; a ^= (c>>13); a &= 0xffffffff; \
  b -= c; b -= a; b ^= (a<<8);  b &= 0xffffffff; \
  c -= a; c -= b; c ^= (b>>13); c &= 0xffffffff; \
  a -= b; a -= c; a ^= (c>>12); a &= 0xffffffff; \
  b -= c; b -= a; b ^= (a<<16); b &= 0xffffffff; \
  c -= a; c -= b; c ^= (b>>5);  c &= 0xffffffff; \
  a -= b; a -= c; a ^= (c>>3);  a &= 0xffffffff; \
  b -= c; b -= a; b ^= (a<<10); b &= 0xffffffff; \
  c -= a; c -= b; c ^= (b>>15); c &= 0xffffffff; \
}
#else
#define MIX(a,b,c) \
{ \
  a -= b; a -= c; a ^= (c>>13); \
  b -= c; b -= a; b ^= (a<<8);  \
  c -= a; c -= b; c ^= (b>>13); \
  a -= b; a -= c; a ^= (c>>12); \
  b -= c; b -= a; b ^= (a<<16); \
  c -= a; c -= b; c ^= (b>>5);  \
  a -= b; a -= c; a ^= (c>>3);  \
  b -= c; b -= a; b ^= (a<<10); \
  c -= a; c -= b; c ^= (b>>15); \
}
#endif

U32 jhash( SV* str )
{
    STRLEN rawlen;
    char* p;
    U32 a, b, c, len, length;

    /* extract the string data and string length from the perl scalar */
    p = (char*)SvPV(str, rawlen);
    length = len = (U32)rawlen;

    /* Test for undef or null string case and return 0 */
    if ( length == 0 ) {
        DEBUG && printf( "Recieved a null or undef string!\n" );
      return 0;
    }

    DEBUG && printf( "Received string '%.*s'.\n", (int)len, p );

    a = b = 0x9e3779b9;        /* golden ratio suggested by Jenkins */
    c = 0;
    while (len >= 12)
    {
        a += (p[0] + (((U32)p[1])<<8) + (((U32)p[2])<<16) +
              (((U32)p[3])<<24));
        b += (p[4] + (((U32)p[5])<<8) + (((U32)p[6])<<16) +
              (((U32)p[7])<<24));
        c += (p[8] + (((U32)p[9])<<8) + (((U32)p[10])<<16) +
              (((U32)p[11])<<24));
        MIX(a, b, c);
        p += 12;
        len -= 12;
    }
    c += length;
    switch(len) {
    case 11: c+=((U32)p[10]<<24);
    case 10: c+=((U32)p[9]<<16);
    case 9:  c+=((U32)p[8]<<8);
    case 8:  b+=((U32)p[7]<<24);
    case 7:  b+=((U32)p[6]<<16);
    case 6:  b+=((U32)p[5]<<8);
    case 5:  b+=((U32)p[4]);
    case 4:  a+=((U32)p[3]<<24);
    case 3:  a+=((U32)p[2]<<16);
    case 2:  a+=((U32)p[1]<<8);
    case 1:  a+=((U32)p[0]);
    }
    MIX(a, b, c);
    DEBUG && printf( "Hash value is %d.\n", (int)(c) );

    return(c);
}

MODULE = Digest::JHash        PACKAGE = Digest::JHash

PROTOTYPES: ENABLE

U32
jhash(str)
    SV*    str