1 
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5 
6 
7 #define BUFFER_SIZE (8192)
8 #define BUFFER_2SIZE (BUFFER_SIZE*2)
9 
10 
11 typedef unsigned long t_myInt;
12 
13 typedef struct ts_Data
14 {
15   t_myInt mask,
16 prime,
17 maskbits,
18 charcount,
19 modulo;
20 
21   t_myInt values[256];
22 } t_Data;
23 
24 
25 
26 MODULE = Digest::ManberHash         PACKAGE = Digest::ManberHash
27 
28 
29 SV*
30 Init(maskbits,prime, charcount)
31 	unsigned long maskbits
32 	unsigned long prime
33 	unsigned long charcount;
34 CODE:
35   {
36     t_Data *data;
37     int i;
38     t_myInt p;
39 
40     RETVAL=newSVpvf("%*s",sizeof(*data),"a");
41     //	SvGROW(RETVAL,sizeof(*data));
42 
43     data=(t_Data*)SvPV_nolen(RETVAL);
44 
45     data->maskbits=maskbits;
46     data->prime=prime;
47     data->charcount=charcount;
48     data->modulo=-1;
49     data->mask= ~(-1 << maskbits);
50 
51 
52     for(p=1,i=0; i<data->charcount; i++)
53       p=(p * data->prime) & data->modulo;
54 
55     for(i=0; i<256; i++)
56       data->values[i]=(i*p) & data->modulo;
57 
58   }
59 OUTPUT:
60 	RETVAL
61 
62 
63 int
64 ManberHash(set, filename, output)
65         char *set
66 	char *filename
67         SV *output
68 CODE:
69   {
70     int fh;
71     t_myInt curr,last,prev;
72     char buffer[BUFFER_2SIZE];
73     int i,b2d,b2use,i_last,count,j;
74     HV * hv;
75     HE * he;
76     SV *sv,**svp;
77 	t_Data *settings;
78   char hex[11];
79 
80 	RETVAL=0;
81   if (SvTYPE(SvRV(output)) != SVt_PVHV)
82   return;
83  /*  if (SvTYPE(SvRV(set)) != SVt_PV)
84    return;
85  settings=(t_Data*)SVPV_nolen(SvRV(set));
86   */
87  settings=(t_Data*)set;
88   memset(hex,0,sizeof(hex));
89 
90 
91     /*
92        if (strcmp(fn,"-")==0)
93        {
94        fp=stdin;
95        }
96        else
97        {
98        fp=fopen(fn,"rb");
99        if (fp == NULL)
100        {
101        fprintf(stderr,"Can't open '%s': %s (%d)\n",
102        fn,strerror(errno),errno);
103        exit(1);
104        }
105        }
106      */
107 
108     fh=open(filename,O_RDONLY);
109     if (fh<0)
110       return;
111 
112   //  printf("file opend\n");
113 
114     b2d=read(fh,buffer,BUFFER_2SIZE);
115     b2use=0;
116 
117     if (b2d < settings->charcount)
118       return;
119 
120     for(i=curr=0; i<settings->charcount; i++)
121     {
122       curr=curr*settings->prime + buffer[i];
123     }
124     last=prev=curr;
125     i_last=0;
126     b2d-=settings->charcount;
127 
128     hv=(HV*)SvRV(output);
129 
130     while (b2d>=0)
131     {
132       if (b2d == BUFFER_SIZE)
133       {
134 	b2d += read(fh,buffer + (b2use ? BUFFER_SIZE : 0),BUFFER_SIZE);
135 	b2use = !b2use;
136       }
137 
138       curr= ( curr * settings->prime +
139 	  buffer[i] -
140 	  settings->values[buffer[i_last]] )
141 	& settings->modulo;
142 
143 
144       if (curr != last)
145   {
146       if ((curr & settings->mask) == 0)
147       {
148   sprintf(hex,"0x%08X",prev);
149     //printf("found hash  %08X\n",curr);
150 	//      hash=curr >> settings->maskbits;
151 	svp=hv_fetch(hv, hex, sizeof(hex)-1, 1);
152 	if (!svp) return;
153 	 sv=*svp;
154   if (SvIOK(sv))
155 	  count=SvIV(sv)+1;
156   else
157     count=1;
158 
159 	sv_setiv(sv,count);
160 
161 	  last=curr;
162       }
163     prev=curr;
164   }
165 
166 
167       i=(i+1) % BUFFER_2SIZE;
168       i_last=(i_last+1) % BUFFER_2SIZE;
169       b2d--;
170     }
171 
172     close(fh);
173 
174   //   printf("finished hashing\n");
175 
176   //  XPUSHs( sv_2mortal(newRV_noinc((SV*)hv)));
177 	RETVAL=1;
178   }
179 OUTPUT:
180 	RETVAL
181 
182 
183