03dafe501c5a0a3d4af40b9c197a0a2e26552cb8
[com/asn1c.git] / libasn1parser / asn1p_constr.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6
7 #include "asn1parser.h"
8
9 void
10 asn1p_constraint_set_source(asn1p_constraint_t *ct,
11                             struct asn1p_module_s *module, int lineno) {
12     if(ct) {
13         ct->module = module;
14         ct->_lineno = lineno;
15         asn1p_value_set_source(ct->containedSubtype,module,lineno);
16         asn1p_value_set_source(ct->value,module,lineno);
17         asn1p_value_set_source(ct->range_start,module,lineno);
18         asn1p_value_set_source(ct->range_stop,module,lineno);
19         for(size_t i = 0; i < ct->el_count; i++) {
20             asn1p_constraint_set_source(ct->elements[i], module, lineno);
21         }
22     }
23 }
24
25 int asn1p_constraint_compare(const asn1p_constraint_t *a,
26                              const asn1p_constraint_t *b) {
27     assert((a && b));
28
29     if(a->type != b->type)
30         return -1;
31
32     /* Currently we only check VALUESET as a reference */
33     if(a->type == ACT_EL_TYPE) {
34         return strcmp(a->containedSubtype->value.v_type->reference->components[0].name,
35                       b->containedSubtype->value.v_type->reference->components[0].name);
36     }
37
38     return 0;
39 }
40
41 asn1p_constraint_t *
42 asn1p_constraint_new(int _lineno, asn1p_module_t *mod) {
43         asn1p_constraint_t *ct;
44
45         ct = calloc(1, sizeof(*ct));
46         if(ct) {
47                 ct->_lineno = _lineno;
48                 ct->module = mod;
49         }
50
51         return ct;
52 }
53
54
55 void
56 asn1p_constraint_free(asn1p_constraint_t *ct) {
57         if(ct) {
58
59                 asn1p_value_free(ct->containedSubtype);
60                 asn1p_value_free(ct->value);
61                 asn1p_value_free(ct->range_start);
62                 asn1p_value_free(ct->range_stop);
63
64                 if(ct->elements) {
65                         while(ct->el_count--) {
66                                 asn1p_constraint_free(
67                                         ct->elements[ct->el_count]);
68                         }
69                         free(ct->elements);
70                 }
71
72                 free(ct);
73         }
74 }
75
76 asn1p_constraint_t *
77 asn1p_constraint_clone(asn1p_constraint_t *src) {
78         return asn1p_constraint_clone_with_resolver(src, 0, 0);
79 }
80
81 asn1p_constraint_t *
82 asn1p_constraint_clone_with_resolver(asn1p_constraint_t *src,
83                 asn1p_value_t *(*vr)(asn1p_value_t *, void *varg), void *varg) {
84         asn1p_constraint_t *clone;
85
86 #define CLONE(field, func)      do { if(src->field) {                   \
87                         clone->field = func(src->field, vr, varg);      \
88                         if(clone->field == NULL) {                      \
89                                 asn1p_constraint_free(clone);           \
90                                 return NULL;                            \
91                         }                                               \
92                 } } while(0)
93
94         clone = asn1p_constraint_new(src->_lineno, src->module);
95         if(clone) {
96                 unsigned int i;
97
98                 clone->type = src->type;
99                 clone->presence = src->presence;
100                 CLONE(containedSubtype, asn1p_value_clone_with_resolver);
101                 CLONE(value,            asn1p_value_clone_with_resolver);
102                 CLONE(range_start,      asn1p_value_clone_with_resolver);
103                 CLONE(range_stop,       asn1p_value_clone_with_resolver);
104
105                 for(i = 0; i < src->el_count; i++) {
106                         asn1p_constraint_t *t;
107                         t = asn1p_constraint_clone_with_resolver(src->elements[i], vr, varg);
108                         if(!t) {
109                                 asn1p_constraint_free(clone);
110                                 return NULL;
111                         }
112                         if(asn1p_constraint_insert(clone, t)) {
113                                 asn1p_constraint_free(clone);
114                                 asn1p_constraint_free(t);
115                                 return NULL;
116                         }
117                 }
118                 assert(clone->el_count == src->el_count);
119                 clone->_lineno = src->_lineno;
120         }
121
122         return clone;
123 }
124
125 /*
126  * Make sure there's enough space to add an element.
127  */
128 static int
129 asn1p_constraint_make_memory(asn1p_constraint_t *ct) {
130         if(ct->el_count == ct->el_size) {
131                 unsigned int newsize = ct->el_size ? ct->el_size << 2 : 4;
132                 void *p;
133                 p = realloc(ct->elements, newsize * sizeof(ct->elements[0]));
134                 if(p) {
135                         ct->elements = p;
136                         ct->el_size = newsize;
137                 } else {
138                         return -1;
139                 }
140         }
141         return 0;
142 }
143
144 int
145 asn1p_constraint_insert(asn1p_constraint_t *into, asn1p_constraint_t *what) {
146         assert(into);
147         assert(what);
148
149         if(asn1p_constraint_make_memory(into))
150                 return -1;
151
152         into->elements[into->el_count++] = what;
153         what->parent_ct = into;
154
155         return 0;
156 }
157
158 int
159 asn1p_constraint_prepend(asn1p_constraint_t *before, asn1p_constraint_t *what) {
160         assert(before);
161         assert(what);
162
163         if(asn1p_constraint_make_memory(before))
164                 return -1;
165
166         memmove(&before->elements[1], &before->elements[0],
167                 before->el_count * sizeof(before->elements[0]));
168
169         before->elements[0] = what;
170         before->el_count++;
171         what->parent_ct = before;
172
173         return 0;
174 }
175
176
177 const char *
178 asn1p_constraint_type2str(enum asn1p_constraint_type_e type) {
179         switch(type) {
180         case ACT_INVALID:
181                 return "INVALID";
182         case ACT_EL_TYPE:
183                 return "ContainedSubtype";
184         case ACT_EL_VALUE:
185                 return "SingleValue";
186         case ACT_EL_RANGE:
187         case ACT_EL_LLRANGE:
188         case ACT_EL_RLRANGE:
189         case ACT_EL_ULRANGE:
190                 return "ValueRange";
191         case ACT_EL_EXT:
192                 return "...";
193         case ACT_CT_SIZE:
194                 return "SizeConstraint";
195         case ACT_CT_FROM:
196                 return "PermittedAlphabet";
197         case ACT_CT_WCOMP:
198                 return "SingleTypeConstraint";
199         case ACT_CT_WCOMPS:
200                 return "MultipleTypeConstraints";
201         case ACT_CT_CTDBY:
202                 return "UserDefinedConstraint";
203         case ACT_CT_CTNG:
204                 return "ContentsConstraint";
205         case ACT_CT_PATTERN:
206                 return "PatternConstraint";
207         case ACT_CA_SET:
208                 return "SET";
209         case ACT_CA_CRC:
210                 return "ComponentRelationConstraint";
211         case ACT_CA_CSV:
212                 return "CSV";
213         case ACT_CA_UNI:
214                 return "UNION";
215         case ACT_CA_INT:
216                 return "INTERSECTION";
217         case ACT_CA_EXC:
218                 return "EXCEPT";
219         case ACT_CA_AEX:
220                 return "ALL EXCEPT";
221         }
222         return "UNKNOWN";
223 }
224
225 const asn1p_constraint_t *
226 asn1p_get_component_relation_constraint(asn1p_constraint_t *ct) {
227     if(ct) {
228         if(ct->type == ACT_CA_CRC)
229             return ct;
230         if(ct->type == ACT_CA_SET) {
231             for(size_t i = 0; i < ct->el_count; i++) {
232                 const asn1p_constraint_t *tmp =
233                     asn1p_get_component_relation_constraint(ct->elements[i]);
234                 if(tmp) return tmp;
235             }
236         }
237     }
238     return NULL;
239 }
240