Introduce TinyHttp server
[lcapit-junk-code.git] / CEP / C / db.c
blob62b50dd7f94fe44b6042cc691cae8a634d886f0a
1 /*
2 * db: functions to retrieve data from the database file.
3 *
4 * The database is a CSV list, each line has the following format
5 * (pt_BR for now):
6 *
7 * CEP;UF;Cidade;Bairro;Rua
9 * A line is called an entry, each value in the line is called
10 * an info.
12 * This file is licensed under the GPLv2 license.
14 * Luiz Fernando N. Capitulino
15 * <lcapitulino@gmail.com>
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
21 #include "db.h"
22 #include "misc.h"
24 /* eof_info(): return 1 if 'c' is an end of info character,
25 * otherwise return 0. */
26 static int eof_info(FILE *db, char c)
28 if (c == ';' || c == '\n')
29 return 1;
31 if (c == '\r') {
32 /* remove trailing '\n' */
33 c = fgetc(db);
34 if (c != '\n')
35 fatal("DOS file seems corrupted");
36 return 1;
39 return 0;
42 /* read_info(): Return the next info from the 'db' file,
43 * aborts program execution on error. */
44 static char *read_info(FILE *db)
46 char *info;
48 info = read_chars(db, eof_info);
49 if (!info)
50 fatal("didn't read expected EOF from db file");
52 return info;
56 /* read_buf(): read 'len' characters from 'db' file into 'buf',
57 * the characters have to be part of an info (ie, they're
58 * terminated by ';' or '\n') otherwise program execution is
59 * aborted. */
60 static void read_buf(FILE *db, char *buf, size_t len)
62 int c;
63 size_t i;
65 for (i = 0; i < (len - 1); i++)
66 buf[i] = fgetc(db);
68 buf[i] = '\0';
70 c = fgetc(db);
71 if (c != ';')
72 fatal("db file is corrupted");
75 /* read_cep(): read CEP info from the 'db' file. */
76 static unsigned int read_cep(FILE *db)
78 char cep_str[DB_CEP_LEN + 1];
80 read_buf(db, cep_str, sizeof(cep_str));
82 /* XXX: error check */
83 return strtol(cep_str, NULL, 10);
86 /* read_uf(): read UF info from the 'db' file. */
87 static void read_uf(FILE *db, char *uf)
89 read_buf(db, uf, DB_UF_LEN);
92 /* file_eof(): return 1 if next character from 'db' is EOF,
93 * otherwise return 0. */
94 static int file_eof(FILE *db)
96 int c;
98 c = fgetc(db);
99 if (c == EOF)
100 return 1;
102 ungetc(c, db);
103 return 0;
106 /* db_next_entry(): return the next entry from 'db' file, if
107 * EOF is found return NULL. */
108 struct db_entry *db_next_entry(FILE *db)
110 struct db_entry *entry;
112 if (file_eof(db))
113 return NULL;
115 entry = malloc(sizeof(*entry));
116 if (!entry)
117 fatal("cannot allocate memory");
119 entry->cep = read_cep(db);
120 read_uf(db, entry->uf);
121 entry->cidade = read_info(db);
122 entry->bairro = read_info(db);
123 entry->desc = read_info(db);
125 return entry;
128 /* db_free_entry(): free all the memory allocated by 'entry */
129 void db_free_entry(struct db_entry **entry)
131 free((*entry)->cidade);
132 free((*entry)->bairro);
133 free((*entry)->desc);
134 free(*entry);
137 /* db_dump_entry(): dump 'entry' info in CSV format to stdout */
138 void db_dump_entry(const struct db_entry *entry)
140 printf("%u;%s;%s;%s;%s\n", entry->cep, entry->uf,
141 entry->cidade, entry->bairro, entry->desc);
144 /* db_print_entry(): print 'entry' info in human readable format
145 * to stdout */
146 void db_print_entry(const struct db_entry *entry)
148 putchar('\n');
150 printf(
151 "CEP: %d\n"
152 "UF: %s\n"
153 "Cidade: %s\n"
154 "Bairro: %s\n"
155 "Desc: %s\n",
156 entry->cep, entry->uf, entry->cidade,
157 entry->bairro, entry->desc);
159 putchar('\n');
162 /* db_dump_csv(): dump all entries in 'db' file in CSV format
163 * to stdout */
164 void db_dump_csv(FILE *db)
166 struct db_entry *entry;
168 for (;;) {
169 entry = db_next_entry(db);
170 if (!entry)
171 break;
173 db_dump_entry(entry);
174 db_free_entry(&entry);
178 /* db_entries_match(): return 1 if ent1 == ent2, return
179 * 0 otherwise */
180 int db_entries_match(const struct db_entry *ent1,
181 const struct db_entry *ent2)
183 if (ent1->cep != ent2->cep)
184 return 0;
186 if (strcmp(ent1->uf, ent2->uf))
187 return 0;
189 if (strcmp(ent1->cidade, ent2->cidade))
190 return 0;
192 if (strcmp(ent1->bairro, ent2->bairro))
193 return 0;
195 if (strcmp(ent1->desc, ent2->desc))
196 return 0;
198 return 1;