]>
Raphaël G. Git Repositories - carabistouilles/blob - analyse.c
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 * Written by Raphaël Gertz <rapsys@rapsys.eu>
18 /* exit EXIT_FAILURE EXIT_SUCCESS */
36 /* Zero ascii offset */
37 #define ZERO_OFFSET 48
53 /* Lookup leaf function prototype */
54 struct leaf
*lookupLeaf(void **, const char *, unsigned);
56 /* Freeing node function prototype */
57 void freeTree(void *, unsigned);
60 int main(int argc
, char **argv
) {
72 char line
[11] = { 0 };
78 struct branch
*tree
= NULL
;
83 /* Duplicated counter */
84 unsigned duplicate
= 0;
87 /* Check argument count */
88 if (argc
< 2 || argc
> 2) {
89 fprintf(stderr
, "Usage: %s sirens_fxt.txt\n", argv
[0]);
94 if (stat(argv
[1], &ss
) == -1) {
95 perror("Stat failed");
99 /* Check it is a file */
100 if (!S_ISREG(ss
.st_mode
)) {
101 fprintf(stderr
, "%s must be a valid file\n", argv
[1]);
105 /* Check if readable */
106 if (access(argv
[1], R_OK
)) {
107 fprintf(stderr
, "%s must be readable\n", argv
[1]);
112 if ((fd
= open(argv
[1], O_RDONLY
)) == -1) {
113 perror("Open failed");
119 /* Try reading line and check line format */
120 if ((ret
= read(fd
, &line
, 10)) == 10 && strspn(line
, "0123456789") == 9 && line
[9] == '\n') {
123 /* Lookup matching leaf */
124 current
= lookupLeaf((void **)&tree
, line
, 0);
126 if (current
->count
== 0) {
128 } else if (current
->count
== 1) {
133 /* Handle read error */
134 } else if (ret
== -1) {
135 perror("Read failed");
137 /* Handle partial read or invalid line format */
138 } else if (ret
> 0) {
140 fprintf(stderr
, "%s must be filled with lines matching [0-9]{9}LF format; got \"%s\" instead\n", argv
[1], line
);
143 /* Read until end of file */
150 if (close(fd
) == -1) {
151 perror("Close failed");
156 printf("Unique%s: %d, duplicate%s: %d\n", (unique
> 1 ? "s" : ""), unique
, (duplicate
> 1 ? "s" : ""), duplicate
);
162 /* Recursive freeing of node function */
163 void freeTree(void *base
, unsigned index
) {
164 void *current
= base
, *next
;
168 /* Free horizontaly */
171 if (((struct branch
*)current
)->child
!= NULL
) {
172 freeTree(((struct branch
*)current
)->child
, index
+ 1);
174 /* Free current and switch to next */
175 next
= ((struct branch
*)current
)->next
;
178 } while (current
!= NULL
);
181 /* Free horizontaly */
183 /* Free current and switch to next */
184 next
= ((struct leaf
*)current
)->next
;
187 } while (current
!= NULL
);
192 /* Recursive lookup and populate tree function */
193 struct leaf
*lookupLeaf(void **base
, const char *key
, unsigned index
) {
197 /* Insert node on empty level */
201 if ((*base
= malloc(sizeof(struct branch
))) == NULL
) {
202 perror("Malloc failed");
205 ((struct branch
*)*base
)->key
= key
[index
] - ZERO_OFFSET
;
206 ((struct branch
*)*base
)->next
= NULL
;
207 ((struct branch
*)*base
)->child
= NULL
;
208 ret
= lookupLeaf(&(((struct branch
*)*base
)->child
), key
, index
+ 1);
211 if ((*base
= malloc(sizeof(struct leaf
))) == NULL
) {
212 perror("Malloc failed");
215 ((struct leaf
*)*base
)->key
= key
[index
] - ZERO_OFFSET
;
216 ((struct leaf
*)*base
)->next
= NULL
;
217 ((struct leaf
*)*base
)->count
= 0;
218 ret
= (struct leaf
*)*base
;
220 /* Search horizontaly next node */
222 /* Current node for horizontal search */
223 void *current
= *base
, *prev
;
226 /* Lookup node matching key or allocate it */
227 while(((struct branch
*)current
)->key
!= key
[index
] - ZERO_OFFSET
) {
228 /* End of horizontal search */
229 if (((struct branch
*)current
)->next
== NULL
) {
230 /* Backup current in prev */
232 /* Create new branch with key */
233 if ((current
= malloc(sizeof(struct branch
))) == NULL
) {
234 perror("Malloc failed");
237 ((struct branch
*)current
)->key
= key
[index
] - ZERO_OFFSET
;
238 ((struct branch
*)current
)->next
= NULL
;
239 ((struct branch
*)current
)->child
= NULL
;
240 ((struct branch
*)prev
)->next
= (struct branch
*)current
;
242 /* Pass to next one */
243 current
= ((struct branch
*)current
)->next
;
247 /* Lookup leaf or branch in next level */
248 ret
= lookupLeaf(&(((struct branch
*)current
)->child
), key
, index
+ 1);
251 /* Lookup node matching key or allocate it */
252 while(((struct leaf
*)current
)->key
!= key
[index
] - ZERO_OFFSET
) {
253 /* End of horizontal search */
254 if (((struct leaf
*)current
)->next
== NULL
) {
255 /* Backup current in prev */
257 /* Create new leaf with key */
258 if ((current
= malloc(sizeof(struct leaf
))) == NULL
) {
259 perror("Malloc failed");
262 ((struct leaf
*)current
)->key
= key
[index
] - ZERO_OFFSET
;
263 ((struct leaf
*)current
)->next
= NULL
;
264 ((struct leaf
*)current
)->count
= 0;
265 ((struct leaf
*)prev
)->next
= (struct leaf
*)current
;
267 /* Pass to next one */
268 current
= ((struct leaf
*)current
)->next
;
272 /* Found leaf, return it */
273 ret
= (struct leaf
*)current
;