SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / constr_SET_OF.c
1 /*
2  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <constr_SET_OF.h>
8
9 asn_TYPE_operation_t asn_OP_SET_OF = {
10     SET_OF_free,
11 #if !defined(ASN_DISABLE_PRINT_SUPPORT)
12     SET_OF_print,
13 #else
14     0,
15 #endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
16     SET_OF_compare,
17 #if !defined(ASN_DISABLE_BER_SUPPORT)
18     SET_OF_decode_ber,
19     SET_OF_encode_der,
20 #else
21     0,
22     0,
23 #endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
24 #if !defined(ASN_DISABLE_XER_SUPPORT)
25     SET_OF_decode_xer,
26     SET_OF_encode_xer,
27 #else
28     0,
29     0,
30 #endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
31 #if !defined(ASN_DISABLE_JER_SUPPORT)
32     SET_OF_encode_jer,
33 #else
34     0,
35 #endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
36 #if !defined(ASN_DISABLE_OER_SUPPORT)
37     SET_OF_decode_oer,
38     SET_OF_encode_oer,
39 #else
40     0,
41     0,
42 #endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
43 #if !defined(ASN_DISABLE_UPER_SUPPORT)
44     SET_OF_decode_uper,
45     SET_OF_encode_uper,
46 #else
47     0,
48     0,
49 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
50 #if !defined(ASN_DISABLE_APER_SUPPORT)
51     SET_OF_decode_aper,
52     SET_OF_encode_aper,
53 #else
54     0,
55     0,
56 #endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
57 #if !defined(ASN_DISABLE_RFILL_SUPPORT)
58     SET_OF_random_fill,
59 #else
60     0,
61 #endif  /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
62     0  /* Use generic outmost tag fetcher */
63 };
64
65 /* Append bytes to the above structure */
66 static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
67     struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
68
69     if(el_buf->length + size > el_buf->allocated_size) {
70         size_t new_size = el_buf->allocated_size ? el_buf->allocated_size : 8;
71         void *p;
72
73         do {
74             new_size <<= 2;
75         } while(el_buf->length + size > new_size);
76
77         p = REALLOC(el_buf->buf, new_size);
78         if(p) {
79             el_buf->buf = p;
80             el_buf->allocated_size = new_size;
81         } else {
82             return -1;
83         }
84     }
85
86     memcpy(el_buf->buf + el_buf->length, buffer, size);
87
88     el_buf->length += size;
89     return 0;
90 }
91
92 static void assert_unused_bits(const struct _el_buffer* p) {
93     if(p->length) {
94         assert((p->buf[p->length-1] & ~(0xff << p->bits_unused)) == 0);
95     } else {
96         assert(p->bits_unused == 0);
97     }
98 }
99
100 static int _el_buf_cmp(const void *ap, const void *bp) {
101     const struct _el_buffer *a = (const struct _el_buffer *)ap;
102     const struct _el_buffer *b = (const struct _el_buffer *)bp;
103     size_t common_len;
104     int ret = 0;
105
106     if(a->length < b->length)
107         common_len = a->length;
108     else
109         common_len = b->length;
110
111     if (a->buf && b->buf) {
112         ret = memcmp(a->buf, b->buf, common_len);
113     }
114     if(ret == 0) {
115         if(a->length < b->length)
116             ret = -1;
117         else if(a->length > b->length)
118             ret = 1;
119         /* Ignore unused bits. */
120         assert_unused_bits(a);
121         assert_unused_bits(b);
122     }
123
124     return ret;
125 }
126
127 void
128 SET_OF__encode_sorted_free(struct _el_buffer *el_buf, size_t count) {
129     size_t i;
130
131     for(i = 0; i < count; i++) {
132         FREEMEM(el_buf[i].buf);
133     }
134
135     FREEMEM(el_buf);
136 }
137
138 struct _el_buffer *
139 SET_OF__encode_sorted(const asn_TYPE_member_t *elm,
140                       const asn_anonymous_set_ *list,
141                       enum SET_OF__encode_method method) {
142     struct _el_buffer *encoded_els;
143     int edx;
144
145     encoded_els =
146         (struct _el_buffer *)CALLOC(list->count, sizeof(encoded_els[0]));
147     if(encoded_els == NULL) {
148         return NULL;
149     }
150
151         /*
152          * Encode all members.
153          */
154     for(edx = 0; edx < list->count; edx++) {
155         const void *memb_ptr = list->array[edx];
156         struct _el_buffer *encoding_el = &encoded_els[edx];
157         asn_enc_rval_t erval = {0,0,0};
158
159         if(!memb_ptr) break;
160
161         /*
162                  * Encode the member into the prepared space.
163                  */
164         switch(method) {
165 #if !defined(ASN_DISABLE_BER_SUPPORT)
166         case SOES_DER:
167             erval = elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag,
168                                                _el_addbytes, encoding_el);
169             break;
170 #endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
171 #if !defined(ASN_DISABLE_UPER_SUPPORT)
172         case SOES_CUPER:
173             erval = uper_encode(elm->type,
174                                 elm->encoding_constraints.per_constraints,
175                                 memb_ptr, _el_addbytes, encoding_el);
176             if(erval.encoded != -1) {
177                 size_t extra_bits = erval.encoded % 8;
178                 assert(encoding_el->length == (size_t)(erval.encoded + 7) / 8);
179                 encoding_el->bits_unused = (8 - extra_bits) & 0x7;
180             }
181             break;
182 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
183 #if !defined(ASN_DISABLE_APER_SUPPORT)
184         case SOES_CAPER:
185             erval = aper_encode(elm->type,
186                                 elm->encoding_constraints.per_constraints,
187                                 memb_ptr, _el_addbytes, encoding_el);
188             if(erval.encoded != -1) {
189                 size_t extra_bits = erval.encoded % 8;
190                 assert(encoding_el->length == (size_t)(erval.encoded + 7) / 8);
191                 encoding_el->bits_unused = (8 - extra_bits) & 0x7;
192             }
193             break;
194 #endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
195
196         default:
197             assert(!"Unreachable");
198             break;
199         }
200         if(erval.encoded < 0) break;
201         }
202
203     if(edx == list->count) {
204         /*
205          * Sort the encoded elements according to their encoding.
206          */
207         qsort(encoded_els, list->count, sizeof(encoded_els[0]), _el_buf_cmp);
208
209         return encoded_els;
210     } else {
211         SET_OF__encode_sorted_free(encoded_els, edx);
212         return NULL;
213     }
214 }
215
216 void
217 SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr,
218             enum asn_struct_free_method method) {
219     if(td && ptr) {
220                 const asn_SET_OF_specifics_t *specs;
221                 asn_TYPE_member_t *elm = td->elements;
222                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
223                 asn_struct_ctx_t *ctx;  /* Decoder context */
224                 int i;
225
226                 /*
227                  * Could not use set_of_empty() because of (*free)
228                  * incompatibility.
229                  */
230                 for(i = 0; i < list->count; i++) {
231                         void *memb_ptr = list->array[i];
232                         if(memb_ptr)
233                         ASN_STRUCT_FREE(*elm->type, memb_ptr);
234                 }
235                 list->count = 0;        /* No meaningful elements left */
236
237                 asn_set_empty(list);    /* Remove (list->array) */
238
239                 specs = (const asn_SET_OF_specifics_t *)td->specifics;
240                 ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
241                 if(ctx->ptr) {
242                         ASN_STRUCT_FREE(*elm->type, ctx->ptr);
243                         ctx->ptr = 0;
244                 }
245
246         switch(method) {
247         case ASFM_FREE_EVERYTHING:
248             FREEMEM(ptr);
249             break;
250         case ASFM_FREE_UNDERLYING:
251             break;
252         case ASFM_FREE_UNDERLYING_AND_RESET:
253             memset(ptr, 0, specs->struct_size);
254             break;
255         }
256     }
257 }
258
259 int
260 SET_OF_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
261                   asn_app_constraint_failed_f *ctfailcb, void *app_key) {
262     const asn_TYPE_member_t *elm = td->elements;
263         asn_constr_check_f *constr;
264         const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
265         int i;
266
267         if(!sptr) {
268                 ASN__CTFAIL(app_key, td, sptr,
269                         "%s: value not given (%s:%d)",
270                         td->name, __FILE__, __LINE__);
271                 return -1;
272         }
273
274         constr = elm->encoding_constraints.general_constraints;
275         if(!constr) constr = elm->type->encoding_constraints.general_constraints;
276
277         /*
278          * Iterate over the members of an array.
279          * Validate each in turn, until one fails.
280          */
281         for(i = 0; i < list->count; i++) {
282                 const void *memb_ptr = list->array[i];
283                 int ret;
284
285                 if(!memb_ptr) continue;
286
287                 ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
288                 if(ret) return ret;
289         }
290
291         return 0;
292 }
293
294 struct comparable_ptr {
295     const asn_TYPE_descriptor_t *td;
296     const void *sptr;
297 };
298
299 static int
300 SET_OF__compare_cb(const void *aptr, const void *bptr) {
301     const struct comparable_ptr *a = aptr;
302     const struct comparable_ptr *b = bptr;
303     assert(a->td == b->td);
304     return a->td->op->compare_struct(a->td, a->sptr, b->sptr);
305 }
306
307 int
308 SET_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
309                const void *bptr) {
310     const asn_anonymous_set_ *a = _A_CSET_FROM_VOID(aptr);
311     const asn_anonymous_set_ *b = _A_CSET_FROM_VOID(bptr);
312
313     if(a && b) {
314         struct comparable_ptr *asorted;
315         struct comparable_ptr *bsorted;
316         ssize_t common_length;
317         ssize_t idx;
318
319         if(a->count == 0) {
320             if(b->count) return -1;
321             return 0;
322         } else if(b->count == 0) {
323             return 1;
324         }
325
326         asorted = MALLOC(a->count * sizeof(asorted[0]));
327         bsorted = MALLOC(b->count * sizeof(bsorted[0]));
328         if(!asorted || !bsorted) {
329             FREEMEM(asorted);
330             FREEMEM(bsorted);
331             return -1;
332         }
333
334         for(idx = 0; idx < a->count; idx++) {
335             asorted[idx].td = td->elements->type;
336             asorted[idx].sptr = a->array[idx];
337         }
338
339         for(idx = 0; idx < b->count; idx++) {
340             bsorted[idx].td = td->elements->type;
341             bsorted[idx].sptr = b->array[idx];
342         }
343
344         qsort(asorted, a->count, sizeof(asorted[0]), SET_OF__compare_cb);
345         qsort(bsorted, b->count, sizeof(bsorted[0]), SET_OF__compare_cb);
346
347         common_length = (a->count < b->count ? a->count : b->count);
348         for(idx = 0; idx < common_length; idx++) {
349             int ret = td->elements->type->op->compare_struct(
350                 td->elements->type, asorted[idx].sptr, bsorted[idx].sptr);
351             if(ret) {
352                 FREEMEM(asorted);
353                 FREEMEM(bsorted);
354                 return ret;
355             }
356         }
357
358         FREEMEM(asorted);
359         FREEMEM(bsorted);
360
361         if(idx < b->count) /* more elements in b */
362             return -1;     /* a is shorter, so put it first */
363         if(idx < a->count) return 1;
364     } else if(!a) {
365         return -1;
366     } else if(!b) {
367         return 1;
368     }
369
370         return 0;
371 }