NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1parser / asn1p_class.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <assert.h>
6
7 #include "asn1parser.h"
8 #include "asn1p_class.h"
9
10 asn1p_ioc_table_t *
11 asn1p_ioc_table_new() {
12     asn1p_ioc_table_t *it = calloc(1, sizeof(*it));
13     assert(it);
14     return it;
15 }
16
17 void
18 asn1p_ioc_table_add(asn1p_ioc_table_t *it, asn1p_ioc_row_t *row) {
19     assert(it);
20
21     asn1p_ioc_row_t **new_rows =
22         realloc(it->row, (it->rows + 1) * sizeof(it->row[0]));
23     assert(new_rows);
24     it->row = new_rows;
25     it->row[it->rows++] = row;
26 }
27
28 void
29 asn1p_ioc_table_append(asn1p_ioc_table_t *it, asn1p_ioc_table_t *src) {
30
31     if(!src || !it) return;
32
33     for(size_t i = 0; i < src->rows; i++) {
34         asn1p_ioc_table_add(it, asn1p_ioc_row_clone(src->row[i]));
35     }
36 }
37
38 void
39 asn1p_ioc_table_free(asn1p_ioc_table_t *it) {
40     if(it) {
41         for(size_t i = 0; i < it->rows; i++) {
42             asn1p_ioc_row_delete(it->row[i]);
43         }
44         free(it->row);
45         free(it);
46     }
47 }
48
49 size_t
50 asn1p_ioc_table_max_identifier_length(asn1p_ioc_table_t *it) {
51     size_t max_length = 0;
52     if(it) {
53         for(size_t i = 0; i < it->rows; i++) {
54             size_t len = asn1p_ioc_row_max_identifier_length(it->row[i]);
55             if(len > max_length) max_length = len;
56         }
57     }
58     return max_length;
59 }
60
61 size_t
62 asn1p_ioc_row_max_identifier_length(asn1p_ioc_row_t *row) {
63     size_t max_length = 0;
64     if(row) {
65         for(size_t i = 0; i < row->columns; i++) {
66             if(row->column[i].value) {
67                 size_t len = strlen(row->column[i].value->Identifier);
68                 if(len > max_length) max_length = len;
69             }
70         }
71     }
72     return max_length;
73 }
74
75 asn1p_ioc_row_t *
76 asn1p_ioc_row_new(asn1p_expr_t *oclass) {
77         asn1p_ioc_row_t *row;
78         asn1p_expr_t *field;
79         int columns = 0;
80
81         assert(oclass->expr_type == A1TC_CLASSDEF);
82
83         row = calloc(1, sizeof *row);
84         if(!row) return NULL;
85
86         TQ_FOR(field, &oclass->members, next)
87                 columns++;
88
89         row->column = calloc(columns, sizeof *row->column);
90         if(!row->column) {
91                 free(row);
92                 return NULL;
93         }
94         row->columns = columns;
95
96         columns = 0;
97         TQ_FOR(field, &oclass->members, next) {
98                 row->column[columns].field = field;
99                 row->column[columns].value = NULL;
100                 columns++;
101         }
102
103         return row;
104 }
105
106 asn1p_ioc_row_t *
107 asn1p_ioc_row_clone(asn1p_ioc_row_t *src) {
108         asn1p_ioc_row_t *row;
109
110         row = calloc(1, sizeof *row);
111         if(!row) return NULL;
112
113         row->column = calloc(src->columns, sizeof *src->column);
114         if(!row->column) {
115                 free(row);
116                 return NULL;
117         }
118         row->columns = src->columns;
119
120         for(size_t i = 0; i < src->columns; i++) {
121                 row->column[i].field = src->column[i].field;
122                 row->column[i].value = 0;
123                 if(src->column[i].value) {
124                         row->column[i].value = asn1p_expr_clone(src->column[i].value, 0);
125                 }
126                 row->column[i].new_ref = 1;
127         }
128
129         return row;
130 }
131
132 void
133 asn1p_ioc_row_delete(asn1p_ioc_row_t *row) {
134         if(row) {
135                 if(row->column) {
136                         for(size_t i = 0; i < row->columns; i++) {
137                                 if(!row->column[i].new_ref && row->column[i].value) {
138                                         /* 
139                                          * Field 'reference' comes from asn1fix_cws.c :
140                                          * TQ_FIRST(&cell->field->members)->reference
141                                          * so it should not be freed here.
142                                          */
143                                         row->column[i].value->reference = NULL;
144                                 }
145                                 asn1p_expr_free(row->column[i].value);
146                         }
147                         free(row->column);
148                 }
149                 free(row);
150         }
151 }
152
153 int
154 asn1p_ioc_row_match(const asn1p_ioc_row_t *a, const asn1p_ioc_row_t *b) {
155     assert(a && b);
156
157     if(a->columns != b->columns)
158         return -1;  /* Bad! */
159
160     for(size_t i = 0; i < a->columns; i++) {
161         assert(a->column[i].field);
162         assert(b->column[i].field);
163         if(strcmp(a->column[i].field->Identifier,
164                   b->column[i].field->Identifier)
165            != 0) {
166             return -1;  /* Bad! */
167         }
168         if((a->column[i].value && !b->column[i].value)
169            || (!a->column[i].value && b->column[i].value)) {
170             return 1;   /* Not match */
171         }
172         if(a->column[i].value && b->column[i].value) {
173             if(asn1p_expr_compare(a->column[i].value, b->column[i].value)
174                != 0) {
175                 return 1;   /* Not match */
176             }
177         }
178     }
179
180     return 0;
181 }
182
183 struct asn1p_ioc_cell_s *
184 asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *row, const char *fieldname) {
185         for(size_t i = 0; i < row->columns; i++) {
186                 if(strcmp(row->column[i].field->Identifier, fieldname) == 0)
187                         return &row->column[i];
188         }
189         errno = ESRCH;
190         return NULL;
191 }
192
193 asn1p_wsyntx_chunk_t *
194 asn1p_wsyntx_chunk_new() {
195         asn1p_wsyntx_chunk_t *wc;
196
197         wc = calloc(1, sizeof(*wc));
198
199         return wc;
200 }
201
202 void
203 asn1p_wsyntx_chunk_free(asn1p_wsyntx_chunk_t *wc) {
204         if(wc) {
205                 switch(wc->type) {
206                 case WC_LITERAL:
207                 case WC_WHITESPACE:
208                 case WC_FIELD:
209                         free(wc->content.token); break;
210                 case WC_OPTIONALGROUP:
211                         asn1p_wsyntx_free(wc->content.syntax);
212                         break;
213                 }
214                 free(wc);
215         }
216 }
217
218 asn1p_wsyntx_chunk_t *
219 asn1p_wsyntx_chunk_clone(asn1p_wsyntx_chunk_t *wc) {
220         asn1p_wsyntx_chunk_t *nc;
221
222         nc = asn1p_wsyntx_chunk_new();
223         if(nc) {
224                 nc->type = wc->type;
225                 switch(wc->type) {
226                 case WC_LITERAL:
227                 case WC_WHITESPACE:
228                 case WC_FIELD:
229                         nc->content.token = malloc(strlen(wc->content.token)+1);
230                         strcpy(nc->content.token, wc->content.token);
231                         break;
232                 case WC_OPTIONALGROUP:
233                         nc->content.syntax = asn1p_wsyntx_clone(wc->content.syntax);
234                         break;
235                 }
236         }
237
238         return nc;
239 }
240
241 asn1p_wsyntx_t *
242 asn1p_wsyntx_new() {
243         asn1p_wsyntx_t *wx;
244
245         wx = calloc(1, sizeof(*wx));
246         if(wx) {
247                 TQ_INIT(&(wx->chunks));
248         }
249
250         return wx;
251 }
252
253 void
254 asn1p_wsyntx_free(asn1p_wsyntx_t *wx) {
255         if(wx) {
256                 asn1p_wsyntx_chunk_t *wc;
257                 while((wc = TQ_REMOVE(&(wx->chunks), next)))
258                         asn1p_wsyntx_chunk_free(wc);
259                 free(wx);
260         }
261 }
262
263 asn1p_wsyntx_t *
264 asn1p_wsyntx_clone(asn1p_wsyntx_t *wx) {
265         asn1p_wsyntx_t *nw;
266
267         nw = asn1p_wsyntx_new();
268         if(nw) {
269                 asn1p_wsyntx_chunk_t *wc;
270                 asn1p_wsyntx_chunk_t *nc;
271                 TQ_FOR(wc, &(wx->chunks), next) {
272                         nc = asn1p_wsyntx_chunk_clone(wc);
273                         if(nc) {
274                                 TQ_ADD(&(nw->chunks), nc, next);
275                         } else {
276                                 asn1p_wsyntx_free(nw);
277                                 return NULL;
278                         }
279                 }
280         }
281
282         return nw;
283 }
284
285 asn1p_wsyntx_chunk_t *
286 asn1p_wsyntx_chunk_fromstring(char *token, int do_copy) {
287         asn1p_wsyntx_chunk_t *wc;
288
289         if(do_copy) {
290                 static asn1p_wsyntx_chunk_t tmp;
291                 tmp.type = WC_LITERAL;
292                 tmp.content.token = token;
293                 wc = asn1p_wsyntx_chunk_clone(&tmp);
294         } else {
295                 wc = asn1p_wsyntx_chunk_new();
296                 if(wc) {
297                         wc->type = WC_LITERAL;
298                         wc->content.token = token;
299                 }
300         }
301
302         return wc;
303 }
304
305
306 asn1p_wsyntx_chunk_t *
307 asn1p_wsyntx_chunk_fromsyntax(asn1p_wsyntx_t *syntax) {
308         asn1p_wsyntx_chunk_t *wc;
309
310         wc = asn1p_wsyntx_chunk_new();
311         if(wc) {
312                 wc->type = WC_OPTIONALGROUP;
313                 wc->content.syntax = syntax;
314                 syntax->parent = wc;
315         }
316
317         return wc;
318 }
319