]>
Raphaël G. Git Repositories - carabistouilles/blob - analyse.c
1adcdd980569f72940c60c473a46c7373c148571
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 prototype */
54 struct leaf
*lookupLeaf(void **, const char *, unsigned);
57 int main(int argc
, char **argv
) {
69 char line
[11] = { 0 };
75 struct branch
*tree
= NULL
;
80 /* Duplicated counter */
81 unsigned duplicate
= 0;
84 /* Check argument count */
85 if (argc
< 2 || argc
> 2) {
86 fprintf(stderr
, "Usage: %s sirens_fxt.txt\n", argv
[0]);
91 if (stat(argv
[1], &ss
) == -1) {
92 perror("Stat failed");
96 /* Check it is a file */
97 if (!S_ISREG(ss
.st_mode
)) {
98 fprintf(stderr
, "%s must be a valid file\n", argv
[1]);
102 /* Check if readable */
103 if (access(argv
[1], R_OK
)) {
104 fprintf(stderr
, "%s must be readable\n", argv
[1]);
109 if ((fd
= open(argv
[1], O_RDONLY
)) == -1) {
110 perror("Open failed");
116 /* Try reading line and check line format */
117 if ((ret
= read(fd
, &line
, 10)) == 10 && strspn(line
, "0123456789") == 9 && line
[9] == '\n') {
120 /* Lookup matching leaf */
121 current
= lookupLeaf((void **)&tree
, line
, 0);
123 if (current
->count
== 0) {
125 } else if (current
->count
== 1) {
130 /* Handle read error */
131 } else if (ret
== -1) {
132 perror("Read failed");
134 /* Handle partial read or invalid line format */
135 } else if (ret
> 0) {
137 fprintf(stderr
, "%s must be filled with lines matching [0-9]{9}LF format; got \"%s\" instead\n", argv
[1], line
);
140 /* Read until end of file */
144 if (close(fd
) == -1) {
145 perror("Close failed");
150 printf("Unique%s: %d, duplicate%s: %d\n", (unique
> 1 ? "s" : ""), unique
, (duplicate
> 1 ? "s" : ""), duplicate
);
156 /* Recursive lookup and populate tree function */
157 struct leaf
*lookupLeaf(void **base
, const char *key
, unsigned index
) {
161 /* Insert node on empty level */
165 *base
= malloc(sizeof(struct branch
));
166 ((struct branch
*)*base
)->key
= key
[index
] - ZERO_OFFSET
;
167 ((struct branch
*)*base
)->next
= NULL
;
168 ((struct branch
*)*base
)->child
= NULL
;
169 ret
= lookupLeaf(&(((struct branch
*)*base
)->child
), key
, index
+ 1);
172 *base
= malloc(sizeof(struct leaf
));
173 ((struct leaf
*)*base
)->key
= key
[index
] - ZERO_OFFSET
;
174 ((struct leaf
*)*base
)->next
= NULL
;
175 ((struct leaf
*)*base
)->count
= 0;
176 ret
= (struct leaf
*)*base
;
178 /* Search horizontaly next node */
180 /* Current node for horizontal search */
181 void *current
= *base
, *prev
;
184 /* Lookup node matching key or allocate it */
185 while(((struct branch
*)current
)->key
!= key
[index
] - ZERO_OFFSET
) {
186 /* End of horizontal search */
187 if (((struct branch
*)current
)->next
== NULL
) {
188 /* Backup current in prev */
190 /* Create new branch with key */
191 current
= malloc(sizeof(struct branch
));
192 ((struct branch
*)current
)->key
= key
[index
] - ZERO_OFFSET
;
193 ((struct branch
*)current
)->next
= NULL
;
194 ((struct branch
*)current
)->child
= NULL
;
195 ((struct branch
*)prev
)->next
= (struct branch
*)current
;
197 /* Pass to next one */
198 current
= ((struct branch
*)current
)->next
;
202 /* Lookup leaf or branch in next level */
203 ret
= lookupLeaf(&(((struct branch
*)current
)->child
), key
, index
+ 1);
206 /* Lookup node matching key or allocate it */
207 while(((struct leaf
*)current
)->key
!= key
[index
] - ZERO_OFFSET
) {
208 /* End of horizontal search */
209 if (((struct leaf
*)current
)->next
== NULL
) {
210 /* Backup current in prev */
212 /* Create new leaf with key */
213 current
= malloc(sizeof(struct leaf
));
214 ((struct leaf
*)current
)->key
= key
[index
] - ZERO_OFFSET
;
215 ((struct leaf
*)current
)->next
= NULL
;
216 ((struct leaf
*)current
)->count
= 0;
217 ((struct leaf
*)prev
)->next
= (struct leaf
*)current
;
219 /* Pass to next one */
220 current
= ((struct leaf
*)current
)->next
;
224 /* Found leaf, return it */
225 ret
= (struct leaf
*)current
;