scripts: move mega-sena in
[lcapit-junk-code.git] / CEP / C / cep-browser.c
blob798189aa36680abe3561b0b0ba79b5b8b94db634
1 /*
2 * cep-browser: Address search based on CEP.
3 *
4 * A CEP is a sequence of numbers which correspond to a specific
5 * address. It's the system of postal codes used by the Correios
6 * (Brazil's Postal Service).
7 *
8 * This program supports more than one data structure to store
9 * and search the addresses, it can be used to experiment
10 * different data structures and algorithms.
12 * This program is lincesed under the GPLv2, see COPYING for
13 * more information.
15 * Luiz Fernando N. Capitulino
16 * <lcapitulino@gmail.com>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <errno.h>
24 #include "db.h"
25 #include "misc.h"
26 #include "module.h"
27 #include "mod_list.h"
28 #include "mod_avl.h"
29 #include "mod_bst.h"
30 #include "mod_aa.h"
32 /* module being used */
33 static struct module *cep_module;
35 /* usage(): print usage info */
36 static void usage(void)
38 printf(
39 "usage: cep-browser [options] < file >\n\n"
40 " options:\n"
41 " -h this text\n"
42 " -l use list module\n"
43 " -a use AVL tree module\n"
44 " -b use BST tree module\n"
45 " -A use AA tree module\n"
46 " -D dump the database using choosen module\n"
47 " -r raw database dump\n"
48 " -t run test for selected data structure\n"
49 "\n"
53 /* cep_compare(): return -1 if key1 < key2, 1 if key1 > key2 and
54 * 0 if key1 == key2. Where key is the struct db_entry and what
55 * gets compared is its cep member */
56 static int cep_compare(const void *key1, const void *key2)
58 const struct db_entry *entry1, *entry2;
60 entry1 = (const struct db_entry *) key1;
61 entry2 = (const struct db_entry *) key2;
63 if (entry1->cep < entry2->cep)
64 return -1;
65 else if (entry1->cep > entry2->cep)
66 return 1;
67 return 0;
70 /* cep_destroy(): wrapper to db_free_entry() which can be used by
71 * the module's destroy function */
72 static void cep_destroy(void *data)
74 struct db_entry *entry;
76 entry = (struct db_entry *) data;
77 db_free_entry(&entry);
80 /* cep_dump(): wrapper for db_dump_entry() which can be used by
81 the module's dump function */
82 static void cep_dump(const void *data)
84 db_dump_entry((const struct db_entry *) data);
87 /* Begin HACK
89 * cep_is_duplicated(): return a positive integer if 'cep' is
90 * in the duplicated list, otherwise return 0.
92 * This function should only be used in do_test().
94 * The problem here is that the Brazil's full CEP list file has
95 * some entries which have the same CEP number for different
96 * addresses, but the module's insert() function will only insert
97 * the first occurence of the duplicated entry, silently ignoring
98 * the others.
100 * This can make the do_test() function fail because there won't
101 * be a match for the sencond entry.
103 * So we just ignore duplicated CEPs in do_test().
105 * End HACK
107 static inline int cep_is_duplicated(int cep)
109 switch (cep) {
110 case 72821470:
111 case 72855007:
112 case 72855034:
113 case 72855140:
114 case 72856560:
115 case 72859134:
116 case 29965990:
117 return 1;
120 return 0;
123 /* do_test(): run a simple test to assure that basic functionality
124 * is working. The test resets the database file and does a lookup()
125 * for each CEP in the file. */
126 static void do_test(FILE *db)
128 void *ret;
129 int failed;
130 struct db_entry *entry;
132 rewind(db);
134 printf("%s LOOKUP TEST: ", cep_module->mod_name);
136 failed = 0;
137 for (;;) {
138 entry = db_next_entry(db);
139 if (!entry)
140 break;
142 if (cep_is_duplicated(entry->cep))
143 continue;
145 ret = cep_module->mod_lookup((void *) &entry->cep);
146 if (!ret)
147 failed = 1;
148 if (ret && !db_entries_match(entry, (struct db_entry *) ret))
149 failed = 1;
151 db_free_entry(&entry);
154 if (failed)
155 printf("FAILED\n");
156 else
157 printf("PASSED\n");
160 /* user_command(): executes a command entered by the user in the
161 * interactive shell. Return 1 if the command was executed or
162 * 0 if the command doesn't exist. */
163 static int user_command(const char *cmd)
165 if (!strcmp(cmd, "size")) {
166 printf("%d\n", cep_module->mod_size());
167 return 1;
170 return 0;
173 static int eof_input(FILE *stream, char c)
175 (void) stream;
177 return (c == '\n' ? 1 : 0);
180 static char *user_shell(const char *prompt)
182 printf("%s", prompt);
183 return read_chars(stdin, eof_input);
186 int main(int argc, char *argv[])
188 FILE *db;
189 struct db_entry *entry;
190 int opt, verbose, raw_dump, dump, run_test;
192 cep_module = NULL;
193 raw_dump = dump = run_test = verbose = 0;
195 while ((opt = getopt(argc, argv, "hlAabrDtv")) != -1 ) {
196 switch (opt) {
197 case 'h':
198 usage();
199 exit(0);
200 case 'l':
201 cep_module = &list_module;
202 break;
203 case 'a':
204 cep_module = &avl_module;
205 break;
206 case 'A':
207 cep_module = &aa_module;
208 break;
209 case 'b':
210 cep_module = &bst_module;
211 break;
212 case 'r':
213 raw_dump = 1;
214 break;
215 case 'D':
216 dump = 1;
217 break;
218 case 't':
219 run_test = 1;
220 break;
221 case 'v':
222 verbose = 1;
223 break;
224 default:
225 usage();
226 exit(1);
230 if (optind >= argc)
231 fatal("you have to specify a filename");
233 if ((dump && !cep_module) || (!cep_module && !raw_dump))
234 fatal("you have to select a module");
236 if (cep_module && raw_dump)
237 fatal("you can't use a module to do raw database dump");
239 db = fopen(argv[optind], "r");
240 if (!db) {
241 fatal("can't open file '%s': %s", argv[optind],
242 strerror(errno));
245 if (raw_dump) {
246 db_dump_csv(db);
247 fclose(db);
248 exit(0);
252 * Setup done, here we go
255 cep_module->mod_init(cep_compare, cep_destroy, cep_dump);
257 if (verbose)
258 putchar('\n');
260 /* read all entries */
261 for (;;) {
262 entry = db_next_entry(db);
263 if (!entry)
264 break;
266 cep_module->mod_insert((void *) entry);
268 if (verbose) {
269 printf("-> reading entries: %d\r",
270 cep_module->mod_size());
274 if (dump) {
275 if (cep_module->mod_dump == NULL) {
276 fatal("module '%s' doesn't support database dump",
277 cep_module->mod_name);
280 if (run_test) {
281 fatal("you can't run the test if you want to dump "
282 "the database");
285 cep_module->mod_dump();
286 fclose(db);
287 goto out;
290 if (run_test) {
291 do_test(db);
292 fclose(db);
293 goto out;
296 fclose(db);
298 setlinebuf(stdout);
300 printf("\n-> using %s module [ with %d entries ]\n\n",
301 cep_module->mod_name, cep_module->mod_size());
303 for (;;) {
304 void *data;
305 char *line;
306 unsigned int cep;
308 line = user_shell(">>> ");
309 if (!line) {
310 putchar('\n');
311 break;
314 if (line[0] == '\0') {
315 free(line);
316 continue;
319 if (user_command(line)) {
320 free(line);
321 continue;
324 cep = strtol(line, NULL, 10);
326 data = cep_module->mod_lookup((void *) &cep);
327 if (data)
328 db_print_entry((struct db_entry *) data);
329 else
330 printf("%s: not found\n", line);
332 free(line);
335 out:
336 if (cep_module->mod_destroy)
337 cep_module->mod_destroy();
338 return 0;