forked from pharpala/HashTableLibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmainline.c
314 lines (268 loc) · 8.3 KB
/
mainline.c
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
#include <stdio.h>
#include <string.h> /* for strlen(), strdup() */
#include <stdlib.h> /* for free() */
#include <unistd.h> /* for getopt() */
#include <ctype.h> /* for isdigit() */
#include <errno.h>
#include "aarray.h"
#include "data-reader.h"
#define LINE_MAX 128
/**
* Load the assocArray of attribute value entries
*/
static int
loadAssociativeArray(AssociativeArray *assocArray, char *filename, int useIntKey)
{
char linebuffer[LINE_MAX];
char *strkey = NULL, *value = NULL;
int nEntries = 0;
int intkey;
FILE *fp = NULL;
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Error: Failed to open input file '%s' : %s",
filename, strerror(errno));
return -1;
}
while (readDataLine(fp, linebuffer, LINE_MAX, &strkey, &value) > 0) {
if (useIntKey && isdigit(strkey[0])) {
if (sscanf(strkey, "%d", &intkey) != 1) {
fprintf(stderr, "Error: Failed extracting integer from '%s'\n", strkey);
return -1;
}
if (aaInsert(assocArray,
(AAKeyType) &intkey, sizeof(int),
strdup(value)) < 0) {
fprintf(stderr, "Failed to add key '%d' to assocArray\n", intkey);
return -1;
}
} else {
if (aaInsert(assocArray,
(AAKeyType) strkey, strlen(strkey),
strdup(value)) < 0) {
fprintf(stderr, "Failed to add key '%s' to assocArray\n", strkey);
return -1;
}
}
nEntries++;
}
fclose(fp);
return nEntries;
}
/**
* Query the array with all the values in the given file
*/
static int
queryAssociativeArray(AssociativeArray *assocArray, char *filename, int useIntKey)
{
char linebuffer[LINE_MAX];
char *strkey = NULL, *value = NULL;
int intkey;
FILE *fp = NULL;
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Error: Failed to open query input file '%s' : %s",
filename, strerror(errno));
return -1;
}
while (readPlainLine(fp, linebuffer, LINE_MAX, &strkey)) {
if (useIntKey && isdigit(strkey[0])) {
if (sscanf(strkey, "%d", &intkey) != 1) {
fprintf(stderr, "Error: Failed extracting integer from '%s'\n", strkey);
return -1;
}
value = aaLookup(assocArray, (AAKeyType) &intkey, sizeof(int));
if (value == NULL) {
printf("LOOKUP: key (%d) produced no value\n", intkey);
} else {
printf("LOOKUP: key (%d) produced value '%s'\n", intkey, value);
}
} else {
value = aaLookup(assocArray, (AAKeyType) strkey, strlen(strkey));
if (value == NULL) {
printf("LOOKUP: key '%s' produced no value\n", strkey);
} else {
printf("LOOKUP: key '%s' produced value '%s'\n", strkey, value);
}
}
}
fclose(fp);
return 1;
}
/**
* Delete the selected values from the array. Note that we free the values
* as otherwise they are memory leaks as we are managing the memory for
* these values outside of the library
*/
static int
deleteFromAssociativeArray(AssociativeArray *assocArray, char *filename, int useIntKey)
{
char linebuffer[LINE_MAX];
char *strkey = NULL, *value = NULL;
int intkey;
FILE *fp = NULL;
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Error: Failed to open query input file '%s' : %s",
filename, strerror(errno));
return -1;
}
while (readPlainLine(fp, linebuffer, LINE_MAX, &strkey)) {
if (useIntKey && isdigit(strkey[0])) {
if (sscanf(strkey, "%d", &intkey) != 1) {
fprintf(stderr, "Error: Failed extracting integer from '%s'\n", strkey);
return -1;
}
value = aaDelete(assocArray, (AAKeyType) &intkey, sizeof(int));
if (value == NULL) {
printf("DELETE: key (%d) produced no value\n", intkey);
} else {
printf("DELETE: key (%d) produced value '%s'\n", intkey, value);
free(value);
}
} else {
value = aaDelete(assocArray, (AAKeyType) strkey, strlen(strkey));
if (value == NULL) {
printf("DELETE: key '%s' produced no value\n", strkey);
} else {
printf("DELETE: key '%s' produced value '%s'\n", strkey, value);
free(value);
}
}
}
fclose(fp);
return 1;
}
static int
deleteValue(AAKeyType key, size_t keylen, void *value, void *userdata)
{
if (value != NULL) free(value);
return 0;
}
#define DEFAULT_ARRAY_SIZE 100
#define OPTIONLEN 10
/** print out the help */
void usage(char *progname)
{
fprintf(stderr, "%s [<OPTIONS>] <datafile> [ <datafile> ... ]\n", progname);
fprintf(stderr, "\n");
fprintf(stderr, "Creates an associative array and loads it with values from\n");
fprintf(stderr, "the data files given.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Options: \n");
fprintf(stderr, "%-*s: Print this help.\n", OPTIONLEN, "-h");
fprintf(stderr, "%-*s: If a key is made of digits, store it as an int.\n", OPTIONLEN, "-i");
fprintf(stderr, "%-*s: Size of table used internally, default %d.\n",
OPTIONLEN, "-n <SIZE>", DEFAULT_ARRAY_SIZE);
fprintf(stderr, "%-*s: Output file to write to, default stdout.\n",
OPTIONLEN, "-o <FILE>");
fprintf(stderr, "%-*s: Print out the table after processing.\n", OPTIONLEN, "-p");
fprintf(stderr, "%-*s: Hash using the given algorithm. Choices are \"sum\", \"length\",\n",
OPTIONLEN, "-H <ALG>");
fprintf(stderr, "%-*s: or your own algorithm.\n", OPTIONLEN, "");
fprintf(stderr, "%-*s: Probe using the given algorithm. Choices are \"linear\", \"quadratic\",\n",
OPTIONLEN, "-P <ALG>");
fprintf(stderr, "%-*s: or \"doublehash\".\n", OPTIONLEN, "");
fprintf(stderr, "%-*s: Perform queries on all of the keys listed in <FILE> (one per line)\n",
OPTIONLEN, "-q <FILE>");
fprintf(stderr, "%-*s: Delete all of the keys listed in <FILE> (one per line)\n",
OPTIONLEN, "-d <FILE>");
fprintf(stderr, "\n");
fprintf(stderr, "The order of the operations controlled by -d, -q and -p are: deletion first,\n");
fprintf(stderr, "followed by any queries, and then finally printing (if indicated)\n");
fprintf(stderr, "\n");
exit (1);
}
/**
* Program mainline -- loads all data from files listed into the hash.
* Uses getopt(3) to parse arguments.
*/
int
main(int argc, char **argv)
{
char *programname = NULL;
FILE *ofp = stdout;
int arraySize = DEFAULT_ARRAY_SIZE;
int useIntKey = 0;
int printContents = 0;
char *queryfile = NULL, *deletefile = NULL;
int i, c;
AssociativeArray *assocArray;
char *hash1 = "sum", *hash2 = "len", *probe = "lin";
/* save program name before calling getopt() */
programname = argv[0];
/** use getopt(3) to parse command line */
while ((c = getopt(argc, argv, "hpin:o:P:H:2:q:d:")) != -1) {
if (c == 'i') {
useIntKey = 1;
} else if (c == 'p') {
printContents = 1;
} else if (c == 'n') {
if (sscanf(optarg, "%d", &arraySize) != 1) {
fprintf(stderr,
"Error: cannot parse assocArray size requested from '%s'\n",
optarg);
usage(programname);
}
} else if (c == 'H') {
hash1 = optarg;
} else if (c == '2') {
hash2 = optarg;
} else if (c == 'P') {
probe = optarg;
} else if (c == 'q') {
queryfile = optarg;
} else if (c == 'd') {
deletefile = optarg;
} else if (c == 'o') {
ofp = fopen(optarg, "w");
if (ofp == NULL) {
fprintf(stderr,
"Error: cannot open requested output file '%s' : %s\n",
optarg, strerror(errno));
usage(programname);
}
} else if (c == 'h') {
usage(programname);
}
}
/** update argc + argv to skip past flags */
argc -= optind;
argv += optind;
if (argc < 1) {
fprintf(stderr, "Error: No data files listed to load!\n");
usage(programname);
}
/** allocate the array and fail out if we cannot */
assocArray = aaCreateAssociativeArray(arraySize, probe, hash1, hash2);
if (assocArray == NULL) {
fprintf(stderr, "Error: cannot allocate associative array - exitting\n");
return -1;
}
/** getopt leaves us only "file" arguments left in argv */
for (i = 0; i < argc; i++) {
if (loadAssociativeArray(assocArray, argv[i], useIntKey) < 0) {
fprintf(stderr, "Error: failed loading from file '%s'\n", argv[i]);
return -1;
}
}
printf("Associative array loaded\n");
/** delete anything that we were asked to */
if (deletefile != NULL) {
deleteFromAssociativeArray(assocArray, deletefile, useIntKey);
}
/** perform any queries we were asked to */
if (queryfile != NULL) {
queryAssociativeArray(assocArray, queryfile, useIntKey);
}
/* print out what we loaded */
aaPrintSummary(ofp, assocArray);
if (printContents) {
aaPrintContents(ofp, assocArray, " ");
}
/* clean up before exit */
aaIterateAction(assocArray, deleteValue, NULL);
aaDeleteAssociativeArray(assocArray);
/* exit with success if we get here */
return 0;
}