1 /* Copyright © Євгеній Мещеряков <eugen@debian.org>
2  *
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 #define _POSIX_C_SOURCE 200809L
17 #include "unicode_blocks.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
read_blocks(const char * file_name,int * n)22 struct unicode_block *read_blocks(const char *file_name, int *n)
23 {
24     int nalloc = 256;
25     struct unicode_block *blocks = calloc(nalloc, sizeof(struct unicode_block));
26     *n = 0;
27 
28     FILE *input_file = fopen(file_name, "r");
29     if (!input_file) {
30         perror("fopen");
31         exit(7);
32     }
33 
34     char *line = NULL;
35     size_t len = 0;
36     ssize_t nread;
37 
38     while ((nread = getline(&line, &len, input_file)) != -1) {
39         unsigned long block_start, block_end;
40         char block_name[256];
41 
42         if (nread >= (ssize_t)sizeof(block_name))
43             continue;
44 
45         int matched = sscanf(line, "%lx..%lx; %[^\r\n]", &block_start, &block_end, block_name);
46         if (matched == 3) {
47             struct unicode_block *b = blocks + *n;
48             b->start = block_start;
49             b->end = block_end;
50             b->name = strdup(block_name);
51             if (b->name == NULL) {
52                 perror("strdup");
53                 exit(8);
54             }
55 
56             *n += 1;
57             if (*n >= nalloc) {
58                 int new_nalloc = nalloc + 256;
59                 struct unicode_block *new_blocks = realloc(blocks,
60                                                            new_nalloc * sizeof(struct unicode_block));
61                 if (new_blocks == NULL) {
62                     perror("realloc");
63                     exit(9);
64                 }
65                 memset(new_blocks + nalloc, 0, (new_nalloc - nalloc) * sizeof(struct unicode_block));
66                 nalloc = new_nalloc;
67                 blocks = new_blocks;
68             }
69         }
70     }
71     free(line);
72 
73     if (*n == 0) {
74         free(blocks);
75         return NULL;
76     } else if (*n < nalloc) {
77         blocks = realloc(blocks, *n * sizeof(struct unicode_block));
78     }
79 
80     return blocks;
81 }
82