]>
Raphaël G. Git Repositories - carabistouilles/blob - analyse.c
08b8e03790fcfcc22c83ab965e7b9f2ef1a882a8
   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                         *base 
= malloc(sizeof(struct branch
)); 
 202                         ((struct branch 
*)*base
)->key 
= key
[index
] - ZERO_OFFSET
; 
 203                         ((struct branch 
*)*base
)->next 
= NULL
; 
 204                         ((struct branch 
*)*base
)->child 
= NULL
; 
 205                         ret 
= lookupLeaf(&(((struct branch 
*)*base
)->child
), key
, index 
+ 1); 
 208                         *base 
= malloc(sizeof(struct leaf
)); 
 209                         ((struct leaf 
*)*base
)->key 
= key
[index
] - ZERO_OFFSET
; 
 210                         ((struct leaf 
*)*base
)->next 
= NULL
; 
 211                         ((struct leaf 
*)*base
)->count 
= 0; 
 212                         ret 
= (struct leaf 
*)*base
; 
 214         /* Search horizontaly next node */ 
 216                 /* Current node for horizontal search */ 
 217                 void *current 
= *base
, *prev
; 
 220                         /* Lookup node matching key or allocate it */ 
 221                         while(((struct branch 
*)current
)->key 
!= key
[index
] - ZERO_OFFSET
) { 
 222                                 /* End of horizontal search */ 
 223                                 if (((struct branch 
*)current
)->next 
== NULL
) { 
 224                                         /* Backup current in prev */ 
 226                                         /* Create new branch with key */ 
 227                                         current 
= malloc(sizeof(struct branch
)); 
 228                                         ((struct branch 
*)current
)->key 
= key
[index
] - ZERO_OFFSET
; 
 229                                         ((struct branch 
*)current
)->next 
= NULL
; 
 230                                         ((struct branch 
*)current
)->child 
= NULL
; 
 231                                         ((struct branch 
*)prev
)->next 
= (struct branch 
*)current
; 
 233                                         /* Pass to next one */ 
 234                                         current 
= ((struct branch 
*)current
)->next
; 
 238                         /* Lookup leaf or branch in next level */ 
 239                         ret 
= lookupLeaf(&(((struct branch 
*)current
)->child
), key
, index 
+ 1); 
 242                         /* Lookup node matching key or allocate it */ 
 243                         while(((struct leaf 
*)current
)->key 
!= key
[index
] - ZERO_OFFSET
) { 
 244                                 /* End of horizontal search */ 
 245                                 if (((struct leaf 
*)current
)->next 
== NULL
) { 
 246                                         /* Backup current in prev */ 
 248                                         /* Create new leaf with key */ 
 249                                         current 
= malloc(sizeof(struct leaf
)); 
 250                                         ((struct leaf 
*)current
)->key 
= key
[index
] - ZERO_OFFSET
; 
 251                                         ((struct leaf 
*)current
)->next 
= NULL
; 
 252                                         ((struct leaf 
*)current
)->count 
= 0; 
 253                                         ((struct leaf 
*)prev
)->next 
= (struct leaf 
*)current
; 
 255                                         /* Pass to next one */ 
 256                                         current 
= ((struct leaf 
*)current
)->next
; 
 260                         /* Found leaf, return it */ 
 261                         ret 
= (struct leaf 
*)current
;