File: hash.c

package info (click to toggle)
diablo 1.16.test2-1
  • links: PTS
  • area: non-free
  • in suites: slink
  • size: 1,504 kB
  • ctags: 1,603
  • sloc: ansic: 17,654; perl: 2,054; sh: 260; csh: 118; makefile: 73
file content (135 lines) | stat: -rw-r--r-- 2,862 bytes parent folder | download
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

/*
 * LIB/HASH.C
 *
 * (c)Copyright 1997, Matthew Dillon, All Rights Reserved.  Refer to
 *    the COPYRIGHT file in the base directory of this distribution 
 *    for specific rights granted.
 *
 * CRC hash generator
 */

#include "defs.h"

Prototype hash_t hhash(const char *msgid);
Prototype void bhash(hash_t *h, const char *p, int len);
Prototype const char *GFName(const char *group, const char *prefix, int artBase);

#define P1	7834891
#define P2	6017489

#define HINIT1  0xFAC432B1
#define HINIT2  0x0CD5E44A

#define POLY1   0x00600340UL
#define POLY2   0x00F0D50BUL
#define OPOLY2  0x00F0D50AUL

hash_t CrcXor[3][256];
int    DidCrcInit;

void
crcinit(int method)
{
    int i;

    for (i = 0; i < 256; ++i) {
        int j;
        int v = i;
        hash_t hv = { 0, 0 };

        for (j = 0; j < 8; ++j, (v <<= 1)) {
            if (v & 0x80) {
                hv.h1 ^= POLY1;
                hv.h2 ^= (method == HASH_CRC) ? POLY2 : OPOLY2;
            }
            hv.h2 = (hv.h2 << 1);
            if (hv.h1 & 0x80000000)
                hv.h2 |= 1;
            hv.h1 <<= 1;
        }
        CrcXor[method][i] = hv;
    }
    DidCrcInit = 1;
}

hash_t
hhash(const char *msgid)
{
    hash_t t;

    if (DiabloHashMethod == HASH_CRC || DiabloHashMethod == HASH_OCRC) {
	/*
	 * HASH_CRC  - CRC64
	 */
	if (DidCrcInit == 0) {
	    crcinit(HASH_CRC);
	    crcinit(HASH_OCRC);
	}
	t.h1 = HINIT1;
	t.h2 = HINIT2;
	
	while (*msgid) {
	    int i = (t.h1 >> 24) & 255;
	    t.h1 = (t.h1 << 8) ^ (int)((uint32)t.h2 >> 24) ^ CrcXor[DiabloHashMethod][i].h1;
	    t.h2 = (t.h2 << 8) ^ (uint8)*msgid ^ CrcXor[DiabloHashMethod][i].h2;
	    ++msgid;
	}
	if (t.h1 & 0x80000000)
	    t.h1 = (t.h1 & 0x7FFFFFFF) | 1;
	if (t.h2 & 0x80000000)
	    t.h2 = (t.h2 & 0x7FFFFFFF) | 1;
	t.h1 |= 0x80000000;	/* indicate CRC64 hash */
    } else {
	/*
	 * HASH_PRIME
	 */
	int h1 = 0x0034629D;
	int h2 = 0x007395DD;
	int hv = 0x1A3F5C4F;

	while (*msgid) {
	    h1 = h1 * *(const unsigned char *)msgid % P1;
	    h2 = h2 * *(const unsigned char *)msgid % P2;
	    hv = (hv << 5) ^ *(const unsigned char *)msgid ^ (hv >> 23);
	    ++msgid;
	}
	t.h1 = (h1 ^ (hv << 14)) & 0x7FFFFFFF;	/* bit 31 reserved */
	t.h2 = (h2 ^ (hv << 20)) & 0x7FFFFFFF;	/* bit 31 reserved */
    }
    return(t);
}

/*
 * Slightly different and faster hash algorithm to handle message bodies.
 * This is simpler.
 */

void 
bhash(hash_t *h, const char *p, int len)
{
    while (len) {
	h->h1 += *(unsigned char *)p;	/* simple checksum */
	h->h2 = (h->h2 << 5) ^ h->h1 ^ (h->h2 >> 27);
	++p;
	--len;
    }
}

const char *
GFName(const char *group, const char *prefix, int artBase)
{
    hash_t hv = hhash(group);
    static char GFBuf[64];

    snprintf(GFBuf, sizeof(GFBuf), "%02lx/%s.%d.%08lx.%08lx",
	(long)(uint8)hv.h1,
	prefix,
	artBase,
	(long)hv.h1,
	(long)hv.h2
    );
    return(GFBuf);
}