2 * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <constr_SET_OF.h>
9 asn_TYPE_operation_t asn_OP_SET_OF = {
11 #if !defined(ASN_DISABLE_PRINT_SUPPORT)
15 #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
17 #if !defined(ASN_DISABLE_BER_SUPPORT)
23 #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
24 #if !defined(ASN_DISABLE_XER_SUPPORT)
30 #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
31 #if !defined(ASN_DISABLE_JER_SUPPORT)
35 #endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
36 #if !defined(ASN_DISABLE_OER_SUPPORT)
42 #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
43 #if !defined(ASN_DISABLE_UPER_SUPPORT)
49 #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
50 #if !defined(ASN_DISABLE_APER_SUPPORT)
56 #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
57 #if !defined(ASN_DISABLE_RFILL_SUPPORT)
61 #endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
62 0 /* Use generic outmost tag fetcher */
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;
69 if(el_buf->length + size > el_buf->allocated_size) {
70 size_t new_size = el_buf->allocated_size ? el_buf->allocated_size : 8;
75 } while(el_buf->length + size > new_size);
77 p = REALLOC(el_buf->buf, new_size);
80 el_buf->allocated_size = new_size;
86 memcpy(el_buf->buf + el_buf->length, buffer, size);
88 el_buf->length += size;
92 static void assert_unused_bits(const struct _el_buffer* p) {
94 assert((p->buf[p->length-1] & ~(0xff << p->bits_unused)) == 0);
96 assert(p->bits_unused == 0);
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;
106 if(a->length < b->length)
107 common_len = a->length;
109 common_len = b->length;
111 if (a->buf && b->buf) {
112 ret = memcmp(a->buf, b->buf, common_len);
115 if(a->length < b->length)
117 else if(a->length > b->length)
119 /* Ignore unused bits. */
120 assert_unused_bits(a);
121 assert_unused_bits(b);
128 SET_OF__encode_sorted_free(struct _el_buffer *el_buf, size_t count) {
131 for(i = 0; i < count; i++) {
132 FREEMEM(el_buf[i].buf);
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;
146 (struct _el_buffer *)CALLOC(list->count, sizeof(encoded_els[0]));
147 if(encoded_els == NULL) {
152 * Encode all members.
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};
162 * Encode the member into the prepared space.
165 #if !defined(ASN_DISABLE_BER_SUPPORT)
167 erval = elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag,
168 _el_addbytes, encoding_el);
170 #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
171 #if !defined(ASN_DISABLE_UPER_SUPPORT)
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;
182 #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
183 #if !defined(ASN_DISABLE_APER_SUPPORT)
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;
194 #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
197 assert(!"Unreachable");
200 if(erval.encoded < 0) break;
203 if(edx == list->count) {
205 * Sort the encoded elements according to their encoding.
207 qsort(encoded_els, list->count, sizeof(encoded_els[0]), _el_buf_cmp);
211 SET_OF__encode_sorted_free(encoded_els, edx);
217 SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr,
218 enum asn_struct_free_method method) {
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 */
227 * Could not use set_of_empty() because of (*free)
230 for(i = 0; i < list->count; i++) {
231 void *memb_ptr = list->array[i];
233 ASN_STRUCT_FREE(*elm->type, memb_ptr);
235 list->count = 0; /* No meaningful elements left */
237 asn_set_empty(list); /* Remove (list->array) */
239 specs = (const asn_SET_OF_specifics_t *)td->specifics;
240 ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
242 ASN_STRUCT_FREE(*elm->type, ctx->ptr);
247 case ASFM_FREE_EVERYTHING:
250 case ASFM_FREE_UNDERLYING:
252 case ASFM_FREE_UNDERLYING_AND_RESET:
253 memset(ptr, 0, specs->struct_size);
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);
268 ASN__CTFAIL(app_key, td, sptr,
269 "%s: value not given (%s:%d)",
270 td->name, __FILE__, __LINE__);
274 constr = elm->encoding_constraints.general_constraints;
275 if(!constr) constr = elm->type->encoding_constraints.general_constraints;
278 * Iterate over the members of an array.
279 * Validate each in turn, until one fails.
281 for(i = 0; i < list->count; i++) {
282 const void *memb_ptr = list->array[i];
285 if(!memb_ptr) continue;
287 ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
294 struct comparable_ptr {
295 const asn_TYPE_descriptor_t *td;
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);
308 SET_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
310 const asn_anonymous_set_ *a = _A_CSET_FROM_VOID(aptr);
311 const asn_anonymous_set_ *b = _A_CSET_FROM_VOID(bptr);
314 struct comparable_ptr *asorted;
315 struct comparable_ptr *bsorted;
316 ssize_t common_length;
320 if(b->count) return -1;
322 } else if(b->count == 0) {
326 asorted = MALLOC(a->count * sizeof(asorted[0]));
327 bsorted = MALLOC(b->count * sizeof(bsorted[0]));
328 if(!asorted || !bsorted) {
334 for(idx = 0; idx < a->count; idx++) {
335 asorted[idx].td = td->elements->type;
336 asorted[idx].sptr = a->array[idx];
339 for(idx = 0; idx < b->count; idx++) {
340 bsorted[idx].td = td->elements->type;
341 bsorted[idx].sptr = b->array[idx];
344 qsort(asorted, a->count, sizeof(asorted[0]), SET_OF__compare_cb);
345 qsort(bsorted, b->count, sizeof(bsorted[0]), SET_OF__compare_cb);
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);
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;