source: trunk/gsdl/src/hashfile/hashfile.cpp@ 915

Last change on this file since 915 was 915, checked in by sjboddie, 24 years ago

davidb change

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 5.0 KB
Line 
1/**********************************************************************
2 *
3 * hashfile.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include <stdio.h>
27
28#define MAXNUMLEN 100 // bytes
29
30
31// The number class is used to store very long unsigned integers.
32// The least significant of each number is stored first. Numbers can
33// be no longer than MAXNUMLEN bytes long. A number with length=0
34// is considered to be equal to 0. There should be no extra zeros
35// at the front of the number.
36
37struct number {
38 unsigned int len;
39 unsigned char num[MAXNUMLEN];
40
41 number () {len = 0;}
42};
43
44
45// evaluates a = a + b
46// a and b can be the same number
47void my_inc (number &a, number &b) {
48 unsigned int carry = 0;
49 unsigned int num = 0;
50 unsigned int i = 0;
51
52 while ((carry || (i < a.len) || (i < b.len)) && (i < MAXNUMLEN)) {
53 num = carry;
54 if (i < a.len) num += a.num[i];
55 if (i < b.len) num += b.num[i];
56
57 if (num >= 256) {
58 num -= 256; // assumes that each number in the list < 256
59 carry = 1;
60 } else {
61 carry = 0;
62 }
63 a.num[i] = (unsigned char)num;
64
65 i++;
66 }
67
68 a.len = i;
69}
70
71
72// evaluates a = a - b if a >= b
73// returns true if the subtraction was possible
74int my_ifpos_dec (number &a, number &b) {
75 int carry = 0;
76 int num = 0;
77 int i = 0;
78 unsigned int len = 0; // the last non-zero digit
79
80 // make sure a >= b
81 if (b.len > a.len) return 0;
82 if (b.len == a.len) {
83 i = a.len - 1;
84 while (i >= 0) {
85 if (a.num[i] > b.num[i]) break;
86 if (a.num[i] < b.num[i]) return 0;
87 i--;
88 }
89 }
90
91 unsigned int j = 0;
92 len = 0;
93 while ((j < a.len) || (j < b.len)) {
94 num = -carry;
95 if (j < a.len) num += a.num[j];
96 if (j < b.len) num -= b.num[j];
97
98 if (num < 0) {
99 num += 256; // assumes each number in the list < 256
100 carry = 1;
101 } else {
102 carry = 0;
103 }
104
105 a.num[j] = (unsigned char) num;
106
107 j++;
108 if (num != 0) len = j;
109 }
110
111 a.len = len;
112
113 if (carry) {
114 // panic, this should NOT happen
115 fprintf (stderr, "panic: error in my_ifpos_dec\n");
116 }
117
118 return 1;
119}
120
121
122char *my_convert_num (number &a) {
123 char *result = new char[(a.len*2)+1];
124 int i,len;
125 char convert[16] = {'0','1','2','3','4','5','6','7',
126 '8','9','a','b','c','d','e','f'};
127
128 // zero might be a special case
129 if (a.len == 0) {
130 result[0] = '0';
131 result[1] = '\0';
132 return result;
133 }
134
135 for (i=a.len-1, len=0; i >= 0; i--) {
136 result[len++] = convert[a.num[i]/16];
137 result[len++] = convert[a.num[i]%16];
138 }
139 result[len] = '\0';
140
141 return result;
142}
143
144
145char *hashfile (char *filename) {
146 FILE *infile = (FILE *)NULL;
147 int i;
148
149 // calculate the 8 multiples of the prime number to use
150 // in the long division
151 number primepow[8];
152 number pow;
153 number remainder;
154 unsigned char c;
155
156 // our prime number (618970019642690137449562111)
157 pow.num[0] = 255; pow.num[1] = 255;
158 pow.num[2] = 255; pow.num[3] = 255;
159 pow.num[4] = 255; pow.num[5] = 255;
160 pow.num[6] = 255; pow.num[7] = 255;
161 pow.num[8] = 255; pow.num[9] = 255;
162 pow.num[10] = 255; pow.num[11] = 1;
163 pow.len = 12;
164
165 for (i=0; i<8; i++) {
166 primepow[i] = pow;
167 my_inc (pow, pow);
168 }
169
170 infile = fopen (filename, "rb");
171 if (infile == NULL) {
172 return (char *)NULL;
173 }
174
175 remainder.len = 0;
176 c = (unsigned char)fgetc(infile);
177 while (!feof (infile)) {
178 // remainder = remainder * 256 + c
179 if (remainder.len == MAXNUMLEN-1) {
180 fprintf (stderr, "ERROR - number overflow\n");
181 return (char *)NULL;
182 }
183 for (i=remainder.len; i>0; i--) {
184 remainder.num[i] = remainder.num[i-1];
185 }
186 remainder.num[0] = c;
187 if (remainder.len > 0 || c != 0) remainder.len = remainder.len+1;
188
189 for (i=7; i>=0; i--) {
190 my_ifpos_dec (remainder, primepow[i]);
191 }
192
193 c = (unsigned char)fgetc(infile);
194 }
195
196 fclose (infile);
197
198 return my_convert_num (remainder);
199}
200
201
202int main (int argc, char *argv[]) {
203 int i;
204 char *result;
205
206 for (i = 1; i < argc; i++) {
207 result = hashfile (argv[i]);
208 if (result == NULL) {
209 printf ("ERROR - could not process %s\n", argv[i]);
210 } else {
211 printf ("%s: %s\n", argv[i], result);
212 delete [] result;
213 }
214 }
215
216 return 0;
217}
Note: See TracBrowser for help on using the repository browser.