f4dfa2b31ac6b72f9c835e077bb1136c7c071a8a
[ric-plt/resource-status-manager.git] / RSM / 3rdparty / asn1codec / e2ap_engine / constr_SET_OF.c
1
2 /*
3  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
4  * All rights reserved.
5  * Redistribution and modifications are permitted subject to BSD license.
6  */
7 #include <asn_internal.h>
8 #include <constr_SET_OF.h>
9 #include <asn_SET_OF.h>
10
11 /*
12  * Number of bytes left for this structure.
13  * (ctx->left) indicates the number of bytes _transferred_ for the structure.
14  * (size) contains the number of bytes in the buffer passed.
15  */
16 #define LEFT    ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
17
18 /*
19  * If the subprocessor function returns with an indication that it wants
20  * more data, it may well be a fatal decoding problem, because the
21  * size is constrained by the <TLV>'s L, even if the buffer size allows
22  * reading more data.
23  * For example, consider the buffer containing the following TLVs:
24  * <T:5><L:1><V> <T:6>...
25  * The TLV length clearly indicates that one byte is expected in V, but
26  * if the V processor returns with "want more data" even if the buffer
27  * contains way more data than the V processor have seen.
28  */
29 #define SIZE_VIOLATION  (ctx->left >= 0 && (size_t)ctx->left <= size)
30
31 /*
32  * This macro "eats" the part of the buffer which is definitely "consumed",
33  * i.e. was correctly converted into local representation or rightfully skipped.
34  */
35 #undef  ADVANCE
36 #define ADVANCE(num_bytes)      do {            \
37                 size_t num = num_bytes;         \
38                 ptr = ((const char *)ptr) + num;\
39                 size -= num;                    \
40                 if(ctx->left >= 0)              \
41                         ctx->left -= num;       \
42                 consumed_myself += num;         \
43         } while(0)
44
45 /*
46  * Switch to the next phase of parsing.
47  */
48 #undef  NEXT_PHASE
49 #undef  PHASE_OUT
50 #define NEXT_PHASE(ctx) do {                    \
51                 ctx->phase++;                   \
52                 ctx->step = 0;                  \
53         } while(0)
54 #define PHASE_OUT(ctx)  do { ctx->phase = 10; } while(0)
55
56 /*
57  * Return a standardized complex structure.
58  */
59 #undef  RETURN
60 #define RETURN(_code)   do {                    \
61                 rval.code = _code;              \
62                 rval.consumed = consumed_myself;\
63                 return rval;                    \
64         } while(0)
65
66 /*
67  * The decoder of the SET OF type.
68  */
69 asn_dec_rval_t
70 SET_OF_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
71                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
72                   const void *ptr, size_t size, int tag_mode) {
73     /*
74          * Bring closer parts of structure description.
75          */
76         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
77     const asn_TYPE_member_t *elm = td->elements; /* Single one */
78
79     /*
80          * Parts of the structure being constructed.
81          */
82         void *st = *struct_ptr; /* Target structure. */
83         asn_struct_ctx_t *ctx;  /* Decoder context */
84
85         ber_tlv_tag_t tlv_tag;  /* T from TLV */
86         asn_dec_rval_t rval;    /* Return code from subparsers */
87
88         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
89
90         ASN_DEBUG("Decoding %s as SET OF", td->name);
91         
92         /*
93          * Create the target structure if it is not present already.
94          */
95         if(st == 0) {
96                 st = *struct_ptr = CALLOC(1, specs->struct_size);
97                 if(st == 0) {
98                         RETURN(RC_FAIL);
99                 }
100         }
101
102         /*
103          * Restore parsing context.
104          */
105         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
106         
107         /*
108          * Start to parse where left previously
109          */
110         switch(ctx->phase) {
111         case 0:
112                 /*
113                  * PHASE 0.
114                  * Check that the set of tags associated with given structure
115                  * perfectly fits our expectations.
116                  */
117
118                 rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
119                         tag_mode, 1, &ctx->left, 0);
120                 if(rval.code != RC_OK) {
121                         ASN_DEBUG("%s tagging check failed: %d",
122                                 td->name, rval.code);
123                         return rval;
124                 }
125
126                 if(ctx->left >= 0)
127                         ctx->left += rval.consumed; /* ?Substracted below! */
128                 ADVANCE(rval.consumed);
129
130                 ASN_DEBUG("Structure consumes %ld bytes, "
131                         "buffer %ld", (long)ctx->left, (long)size);
132
133                 NEXT_PHASE(ctx);
134                 /* Fall through */
135         case 1:
136                 /*
137                  * PHASE 1.
138                  * From the place where we've left it previously,
139                  * try to decode the next item.
140                  */
141           for(;; ctx->step = 0) {
142                 ssize_t tag_len;        /* Length of TLV's T */
143
144                 if(ctx->step & 1)
145                         goto microphase2;
146
147                 /*
148                  * MICROPHASE 1: Synchronize decoding.
149                  */
150
151                 if(ctx->left == 0) {
152                         ASN_DEBUG("End of SET OF %s", td->name);
153                         /*
154                          * No more things to decode.
155                          * Exit out of here.
156                          */
157                         PHASE_OUT(ctx);
158                         RETURN(RC_OK);
159                 }
160
161                 /*
162                  * Fetch the T from TLV.
163                  */
164                 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
165                 switch(tag_len) {
166                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
167                         /* Fall through */
168                 case -1: RETURN(RC_FAIL);
169                 }
170
171                 if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
172                         if(LEFT < 2) {
173                                 if(SIZE_VIOLATION)
174                                         RETURN(RC_FAIL);
175                                 else
176                                         RETURN(RC_WMORE);
177                         } else if(((const uint8_t *)ptr)[1] == 0) {
178                                 /*
179                                  * Found the terminator of the
180                                  * indefinite length structure.
181                                  */
182                                 break;
183                         }
184                 }
185
186                 /* Outmost tag may be unknown and cannot be fetched/compared */
187                 if(elm->tag != (ber_tlv_tag_t)-1) {
188                     if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
189                         /*
190                          * The new list member of expected type has arrived.
191                          */
192                     } else {
193                         ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
194                                 ber_tlv_tag_string(tlv_tag), td->name);
195                         ASN_DEBUG("%s SET OF has tag %s",
196                                 td->name, ber_tlv_tag_string(elm->tag));
197                         RETURN(RC_FAIL);
198                     }
199                 }
200
201                 /*
202                  * MICROPHASE 2: Invoke the member-specific decoder.
203                  */
204                 ctx->step |= 1;         /* Confirm entering next microphase */
205         microphase2:
206                 
207                 /*
208                  * Invoke the member fetch routine according to member's type
209                  */
210                 rval = elm->type->op->ber_decoder(opt_codec_ctx,
211                                 elm->type, &ctx->ptr, ptr, LEFT, 0);
212                 ASN_DEBUG("In %s SET OF %s code %d consumed %d",
213                         td->name, elm->type->name,
214                         rval.code, (int)rval.consumed);
215                 switch(rval.code) {
216                 case RC_OK:
217                         {
218                                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
219                                 if(ASN_SET_ADD(list, ctx->ptr) != 0)
220                                         RETURN(RC_FAIL);
221                                 else
222                                         ctx->ptr = 0;
223                         }
224                         break;
225                 case RC_WMORE: /* More data expected */
226                         if(!SIZE_VIOLATION) {
227                                 ADVANCE(rval.consumed);
228                                 RETURN(RC_WMORE);
229                         }
230                         /* Fall through */
231                 case RC_FAIL: /* Fatal error */
232                         ASN_STRUCT_FREE(*elm->type, ctx->ptr);
233                         ctx->ptr = 0;
234                         RETURN(RC_FAIL);
235                 } /* switch(rval) */
236                 
237                 ADVANCE(rval.consumed);
238           }     /* for(all list members) */
239
240                 NEXT_PHASE(ctx);
241         case 2:
242                 /*
243                  * Read in all "end of content" TLVs.
244                  */
245                 while(ctx->left < 0) {
246                         if(LEFT < 2) {
247                                 if(LEFT > 0 && ((const char *)ptr)[0] != 0) {
248                                         /* Unexpected tag */
249                                         RETURN(RC_FAIL);
250                                 } else {
251                                         RETURN(RC_WMORE);
252                                 }
253                         }
254                         if(((const char *)ptr)[0] == 0
255                         && ((const char *)ptr)[1] == 0) {
256                                 ADVANCE(2);
257                                 ctx->left++;
258                         } else {
259                                 RETURN(RC_FAIL);
260                         }
261                 }
262
263                 PHASE_OUT(ctx);
264         }
265         
266         RETURN(RC_OK);
267 }
268
269 /*
270  * Internally visible buffer holding a single encoded element.
271  */
272 struct _el_buffer {
273         uint8_t *buf;
274         size_t length;
275         size_t allocated_size;
276     unsigned bits_unused;
277 };
278 /* Append bytes to the above structure */
279 static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
280     struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
281
282     if(el_buf->length + size > el_buf->allocated_size) {
283         size_t new_size = el_buf->allocated_size ? el_buf->allocated_size : 8;
284         void *p;
285
286         do {
287             new_size <<= 2;
288         } while(el_buf->length + size > new_size);
289
290         p = REALLOC(el_buf->buf, new_size);
291         if(p) {
292             el_buf->buf = p;
293             el_buf->allocated_size = new_size;
294         } else {
295             return -1;
296         }
297     }
298
299     memcpy(el_buf->buf + el_buf->length, buffer, size);
300
301     el_buf->length += size;
302     return 0;
303 }
304
305 static void assert_unused_bits(const struct _el_buffer* p) {
306     if(p->length) {
307         assert((p->buf[p->length-1] & ~(0xff << p->bits_unused)) == 0);
308     } else {
309         assert(p->bits_unused == 0);
310     }
311 }
312
313 static int _el_buf_cmp(const void *ap, const void *bp) {
314     const struct _el_buffer *a = (const struct _el_buffer *)ap;
315     const struct _el_buffer *b = (const struct _el_buffer *)bp;
316     size_t common_len;
317     int ret = 0;
318
319     if(a->length < b->length)
320         common_len = a->length;
321     else
322         common_len = b->length;
323
324     if (a->buf && b->buf) {
325         ret = memcmp(a->buf, b->buf, common_len);
326     }
327     if(ret == 0) {
328         if(a->length < b->length)
329             ret = -1;
330         else if(a->length > b->length)
331             ret = 1;
332         /* Ignore unused bits. */
333         assert_unused_bits(a);
334         assert_unused_bits(b);
335     }
336
337     return ret;
338 }
339
340 static void
341 SET_OF__encode_sorted_free(struct _el_buffer *el_buf, size_t count) {
342     size_t i;
343
344     for(i = 0; i < count; i++) {
345         FREEMEM(el_buf[i].buf);
346     }
347
348     FREEMEM(el_buf);
349 }
350
351 enum SET_OF__encode_method {
352     SOES_DER,   /* Distinguished Encoding Rules */
353     SOES_CUPER  /* Canonical Unaligned Packed Encoding Rules */
354 };
355
356 static struct _el_buffer *
357 SET_OF__encode_sorted(const asn_TYPE_member_t *elm,
358                       const asn_anonymous_set_ *list,
359                       enum SET_OF__encode_method method) {
360     struct _el_buffer *encoded_els;
361     int edx;
362
363     encoded_els =
364         (struct _el_buffer *)CALLOC(list->count, sizeof(encoded_els[0]));
365     if(encoded_els == NULL) {
366         return NULL;
367     }
368
369         /*
370          * Encode all members.
371          */
372     for(edx = 0; edx < list->count; edx++) {
373         const void *memb_ptr = list->array[edx];
374         struct _el_buffer *encoding_el = &encoded_els[edx];
375         asn_enc_rval_t erval = {0,0,0};
376
377         if(!memb_ptr) break;
378
379         /*
380                  * Encode the member into the prepared space.
381                  */
382         switch(method) {
383         case SOES_DER:
384             erval = elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag,
385                                                _el_addbytes, encoding_el);
386             break;
387         case SOES_CUPER:
388             erval = uper_encode(elm->type,
389                                 elm->encoding_constraints.per_constraints,
390                                 memb_ptr, _el_addbytes, encoding_el);
391             if(erval.encoded != -1) {
392                 size_t extra_bits = erval.encoded % 8;
393                 assert(encoding_el->length == (size_t)(erval.encoded + 7) / 8);
394                 encoding_el->bits_unused = (8 - extra_bits) & 0x7;
395             }
396             break;
397         default:
398             assert(!"Unreachable");
399             break;
400         }
401         if(erval.encoded < 0) break;
402         }
403
404     if(edx == list->count) {
405         /*
406          * Sort the encoded elements according to their encoding.
407          */
408         qsort(encoded_els, list->count, sizeof(encoded_els[0]), _el_buf_cmp);
409
410         return encoded_els;
411     } else {
412         SET_OF__encode_sorted_free(encoded_els, edx);
413         return NULL;
414     }
415 }
416
417
418 /*
419  * The DER encoder of the SET OF type.
420  */
421 asn_enc_rval_t
422 SET_OF_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
423                   int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb,
424                   void *app_key) {
425     const asn_TYPE_member_t *elm = td->elements;
426     const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
427     size_t computed_size = 0;
428     ssize_t encoding_size = 0;
429     struct _el_buffer *encoded_els;
430     int edx;
431
432         ASN_DEBUG("Estimating size for SET OF %s", td->name);
433
434     /*
435      * Gather the length of the underlying members sequence.
436      */
437     for(edx = 0; edx < list->count; edx++) {
438         void *memb_ptr = list->array[edx];
439         asn_enc_rval_t erval = {0,0,0};
440
441         if(!memb_ptr) ASN__ENCODE_FAILED;
442
443         erval =
444             elm->type->op->der_encoder(elm->type, memb_ptr, 0, elm->tag, 0, 0);
445         if(erval.encoded == -1) return erval;
446         computed_size += erval.encoded;
447         }
448
449
450     /*
451      * Encode the TLV for the sequence itself.
452      */
453     encoding_size =
454         der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
455     if(encoding_size < 0) {
456         ASN__ENCODE_FAILED;
457     }
458     computed_size += encoding_size;
459
460     if(!cb || list->count == 0) {
461         asn_enc_rval_t erval = {0,0,0};
462         erval.encoded = computed_size;
463         ASN__ENCODED_OK(erval);
464     }
465
466     ASN_DEBUG("Encoding members of %s SET OF", td->name);
467
468     /*
469      * DER mandates dynamic sorting of the SET OF elements
470      * according to their encodings. Build an array of the
471      * encoded elements.
472      */
473     encoded_els = SET_OF__encode_sorted(elm, list, SOES_DER);
474
475     /*
476      * Report encoded elements to the application.
477      * Dispose of temporary sorted members table.
478      */
479     for(edx = 0; edx < list->count; edx++) {
480         struct _el_buffer *encoded_el = &encoded_els[edx];
481         /* Report encoded chunks to the application */
482         if(cb(encoded_el->buf, encoded_el->length, app_key) < 0) {
483             break;
484         } else {
485             encoding_size += encoded_el->length;
486         }
487     }
488
489     SET_OF__encode_sorted_free(encoded_els, list->count);
490
491     if(edx == list->count) {
492         asn_enc_rval_t erval = {0,0,0};
493         assert(computed_size == (size_t)encoding_size);
494         erval.encoded = computed_size;
495         ASN__ENCODED_OK(erval);
496     } else {
497         ASN__ENCODE_FAILED;
498     }
499 }
500
501 #undef  XER_ADVANCE
502 #define XER_ADVANCE(num_bytes)  do {                    \
503                 size_t num = num_bytes;                 \
504                 buf_ptr = ((const char *)buf_ptr) + num;\
505                 size -= num;                            \
506                 consumed_myself += num;                 \
507         } while(0)
508
509 /*
510  * Decode the XER (XML) data.
511  */
512 asn_dec_rval_t
513 SET_OF_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
514                   const asn_TYPE_descriptor_t *td, void **struct_ptr,
515                   const char *opt_mname, const void *buf_ptr, size_t size) {
516     /*
517          * Bring closer parts of structure description.
518          */
519         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
520         const asn_TYPE_member_t *element = td->elements;
521         const char *elm_tag;
522         const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
523
524         /*
525          * ... and parts of the structure being constructed.
526          */
527         void *st = *struct_ptr; /* Target structure. */
528         asn_struct_ctx_t *ctx;  /* Decoder context */
529
530         asn_dec_rval_t rval = {RC_OK, 0};/* Return value from a decoder */
531         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
532
533         /*
534          * Create the target structure if it is not present already.
535          */
536         if(st == 0) {
537                 st = *struct_ptr = CALLOC(1, specs->struct_size);
538                 if(st == 0) RETURN(RC_FAIL);
539         }
540
541         /* Which tag is expected for the downstream */
542         if(specs->as_XMLValueList) {
543                 elm_tag = (specs->as_XMLValueList == 1) ? 0 : "";
544         } else {
545                 elm_tag = (*element->name)
546                                 ? element->name : element->type->xml_tag;
547         }
548
549         /*
550          * Restore parsing context.
551          */
552         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
553
554         /*
555          * Phases of XER/XML processing:
556          * Phase 0: Check that the opening tag matches our expectations.
557          * Phase 1: Processing body and reacting on closing tag.
558          * Phase 2: Processing inner type.
559          */
560         for(; ctx->phase <= 2;) {
561                 pxer_chunk_type_e ch_type;      /* XER chunk type */
562                 ssize_t ch_size;                /* Chunk size */
563                 xer_check_tag_e tcv;            /* Tag check value */
564
565                 /*
566                  * Go inside the inner member of a set.
567                  */
568                 if(ctx->phase == 2) {
569                         asn_dec_rval_t tmprval = {RC_OK, 0};
570
571                         /* Invoke the inner type decoder, m.b. multiple times */
572                         ASN_DEBUG("XER/SET OF element [%s]", elm_tag);
573                         tmprval = element->type->op->xer_decoder(opt_codec_ctx,
574                                         element->type, &ctx->ptr, elm_tag,
575                                         buf_ptr, size);
576                         if(tmprval.code == RC_OK) {
577                                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
578                                 if(ASN_SET_ADD(list, ctx->ptr) != 0)
579                                         RETURN(RC_FAIL);
580                                 ctx->ptr = 0;
581                                 XER_ADVANCE(tmprval.consumed);
582                         } else {
583                                 XER_ADVANCE(tmprval.consumed);
584                                 RETURN(tmprval.code);
585                         }
586                         ctx->phase = 1; /* Back to body processing */
587                         ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
588                         /* Fall through */
589                 }
590
591                 /*
592                  * Get the next part of the XML stream.
593                  */
594                 ch_size = xer_next_token(&ctx->context,
595                         buf_ptr, size, &ch_type);
596                 if(ch_size == -1) {
597             RETURN(RC_FAIL);
598         } else {
599                         switch(ch_type) {
600             case PXER_WMORE:
601                 RETURN(RC_WMORE);
602                         case PXER_COMMENT:      /* Got XML comment */
603                         case PXER_TEXT:         /* Ignore free-standing text */
604                                 XER_ADVANCE(ch_size);   /* Skip silently */
605                                 continue;
606                         case PXER_TAG:
607                                 break;  /* Check the rest down there */
608                         }
609                 }
610
611                 tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
612                 ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s",
613                         tcv, ctx->phase, xml_tag);
614                 switch(tcv) {
615                 case XCT_CLOSING:
616                         if(ctx->phase == 0) break;
617                         ctx->phase = 0;
618                         /* Fall through */
619                 case XCT_BOTH:
620                         if(ctx->phase == 0) {
621                                 /* No more things to decode */
622                                 XER_ADVANCE(ch_size);
623                                 ctx->phase = 3; /* Phase out */
624                                 RETURN(RC_OK);
625                         }
626                         /* Fall through */
627                 case XCT_OPENING:
628                         if(ctx->phase == 0) {
629                                 XER_ADVANCE(ch_size);
630                                 ctx->phase = 1; /* Processing body phase */
631                                 continue;
632                         }
633                         /* Fall through */
634                 case XCT_UNKNOWN_OP:
635                 case XCT_UNKNOWN_BO:
636
637                         ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase);
638                         if(ctx->phase == 1) {
639                                 /*
640                                  * Process a single possible member.
641                                  */
642                                 ctx->phase = 2;
643                                 continue;
644                         }
645                         /* Fall through */
646                 default:
647                         break;
648                 }
649
650                 ASN_DEBUG("Unexpected XML tag in SET OF");
651                 break;
652         }
653
654         ctx->phase = 3; /* "Phase out" on hard failure */
655         RETURN(RC_FAIL);
656 }
657
658
659
660 typedef struct xer_tmp_enc_s {
661         void *buffer;
662         size_t offset;
663         size_t size;
664 } xer_tmp_enc_t;
665 static int
666 SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) {
667         xer_tmp_enc_t *t = (xer_tmp_enc_t *)key;
668         if(t->offset + size >= t->size) {
669                 size_t newsize = (t->size << 2) + size;
670                 void *p = REALLOC(t->buffer, newsize);
671                 if(!p) return -1;
672                 t->buffer = p;
673                 t->size = newsize;
674         }
675         memcpy((char *)t->buffer + t->offset, buffer, size);
676         t->offset += size;
677         return 0;
678 }
679 static int
680 SET_OF_xer_order(const void *aptr, const void *bptr) {
681         const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr;
682         const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr;
683         size_t minlen = a->offset;
684         int ret;
685         if(b->offset < minlen) minlen = b->offset;
686         /* Well-formed UTF-8 has this nice lexicographical property... */
687         ret = memcmp(a->buffer, b->buffer, minlen);
688         if(ret != 0) return ret;
689         if(a->offset == b->offset)
690                 return 0;
691         if(a->offset == minlen)
692                 return -1;
693         return 1;
694 }
695
696
697 asn_enc_rval_t
698 SET_OF_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
699                   enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
700                   void *app_key) {
701     asn_enc_rval_t er = {0,0,0};
702         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
703         const asn_TYPE_member_t *elm = td->elements;
704     const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
705     const char *mname = specs->as_XMLValueList
706                 ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
707         size_t mlen = mname ? strlen(mname) : 0;
708         int xcan = (flags & XER_F_CANONICAL);
709         xer_tmp_enc_t *encs = 0;
710         size_t encs_count = 0;
711         void *original_app_key = app_key;
712         asn_app_consume_bytes_f *original_cb = cb;
713         int i;
714
715         if(!sptr) ASN__ENCODE_FAILED;
716
717         if(xcan) {
718                 encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0]));
719                 if(!encs) ASN__ENCODE_FAILED;
720                 cb = SET_OF_encode_xer_callback;
721         }
722
723         er.encoded = 0;
724
725         for(i = 0; i < list->count; i++) {
726                 asn_enc_rval_t tmper = {0,0,0};
727
728                 void *memb_ptr = list->array[i];
729                 if(!memb_ptr) continue;
730
731                 if(encs) {
732                         memset(&encs[encs_count], 0, sizeof(encs[0]));
733                         app_key = &encs[encs_count];
734                         encs_count++;
735                 }
736
737                 if(mname) {
738                         if(!xcan) ASN__TEXT_INDENT(1, ilevel);
739                         ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
740                 }
741
742                 if(!xcan && specs->as_XMLValueList == 1)
743                         ASN__TEXT_INDENT(1, ilevel + 1);
744                 tmper = elm->type->op->xer_encoder(elm->type, memb_ptr,
745                                 ilevel + (specs->as_XMLValueList != 2),
746                                 flags, cb, app_key);
747                 if(tmper.encoded == -1) return tmper;
748                 er.encoded += tmper.encoded;
749                 if(tmper.encoded == 0 && specs->as_XMLValueList) {
750                         const char *name = elm->type->xml_tag;
751                         size_t len = strlen(name);
752                         ASN__CALLBACK3("<", 1, name, len, "/>", 2);
753                 }
754
755                 if(mname) {
756                         ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
757                 }
758
759         }
760
761         if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
762
763         if(encs) {
764                 xer_tmp_enc_t *enc = encs;
765                 xer_tmp_enc_t *end = encs + encs_count;
766                 ssize_t control_size = 0;
767
768                 er.encoded = 0;
769                 cb = original_cb;
770                 app_key = original_app_key;
771                 qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order);
772
773                 for(; enc < end; enc++) {
774                         ASN__CALLBACK(enc->buffer, enc->offset);
775                         FREEMEM(enc->buffer);
776                         enc->buffer = 0;
777                         control_size += enc->offset;
778                 }
779                 assert(control_size == er.encoded);
780         }
781
782         goto cleanup;
783 cb_failed:
784         ASN__ENCODE_FAILED;
785 cleanup:
786         if(encs) {
787                 size_t n;
788                 for(n = 0; n < encs_count; n++) {
789                         FREEMEM(encs[n].buffer);
790                 }
791                 FREEMEM(encs);
792         }
793         ASN__ENCODED_OK(er);
794 }
795
796 int
797 SET_OF_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
798              asn_app_consume_bytes_f *cb, void *app_key) {
799     asn_TYPE_member_t *elm = td->elements;
800         const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
801         int ret;
802         int i;
803
804         if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
805
806         /* Dump preamble */
807         if(cb(td->name, strlen(td->name), app_key) < 0
808         || cb(" ::= {", 6, app_key) < 0)
809                 return -1;
810
811         for(i = 0; i < list->count; i++) {
812                 const void *memb_ptr = list->array[i];
813                 if(!memb_ptr) continue;
814
815                 _i_INDENT(1);
816
817                 ret = elm->type->op->print_struct(elm->type, memb_ptr,
818                         ilevel + 1, cb, app_key);
819                 if(ret) return ret;
820         }
821
822         ilevel--;
823         _i_INDENT(1);
824
825         return (cb("}", 1, app_key) < 0) ? -1 : 0;
826 }
827
828 void
829 SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr,
830             enum asn_struct_free_method method) {
831     if(td && ptr) {
832                 const asn_SET_OF_specifics_t *specs;
833                 asn_TYPE_member_t *elm = td->elements;
834                 asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
835                 asn_struct_ctx_t *ctx;  /* Decoder context */
836                 int i;
837
838                 /*
839                  * Could not use set_of_empty() because of (*free)
840                  * incompatibility.
841                  */
842                 for(i = 0; i < list->count; i++) {
843                         void *memb_ptr = list->array[i];
844                         if(memb_ptr)
845                         ASN_STRUCT_FREE(*elm->type, memb_ptr);
846                 }
847                 list->count = 0;        /* No meaningful elements left */
848
849                 asn_set_empty(list);    /* Remove (list->array) */
850
851                 specs = (const asn_SET_OF_specifics_t *)td->specifics;
852                 ctx = (asn_struct_ctx_t *)((char *)ptr + specs->ctx_offset);
853                 if(ctx->ptr) {
854                         ASN_STRUCT_FREE(*elm->type, ctx->ptr);
855                         ctx->ptr = 0;
856                 }
857
858         switch(method) {
859         case ASFM_FREE_EVERYTHING:
860             FREEMEM(ptr);
861             break;
862         case ASFM_FREE_UNDERLYING:
863             break;
864         case ASFM_FREE_UNDERLYING_AND_RESET:
865             memset(ptr, 0, specs->struct_size);
866             break;
867         }
868     }
869 }
870
871 int
872 SET_OF_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
873                   asn_app_constraint_failed_f *ctfailcb, void *app_key) {
874     const asn_TYPE_member_t *elm = td->elements;
875         asn_constr_check_f *constr;
876         const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
877         int i;
878
879         if(!sptr) {
880                 ASN__CTFAIL(app_key, td, sptr,
881                         "%s: value not given (%s:%d)",
882                         td->name, __FILE__, __LINE__);
883                 return -1;
884         }
885
886         constr = elm->encoding_constraints.general_constraints;
887         if(!constr) constr = elm->type->encoding_constraints.general_constraints;
888
889         /*
890          * Iterate over the members of an array.
891          * Validate each in turn, until one fails.
892          */
893         for(i = 0; i < list->count; i++) {
894                 const void *memb_ptr = list->array[i];
895                 int ret;
896
897                 if(!memb_ptr) continue;
898
899                 ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
900                 if(ret) return ret;
901         }
902
903         return 0;
904 }
905
906 #ifndef ASN_DISABLE_PER_SUPPORT
907
908 asn_dec_rval_t
909 SET_OF_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
910                    const asn_TYPE_descriptor_t *td,
911                    const asn_per_constraints_t *constraints, void **sptr,
912                    asn_per_data_t *pd) {
913     asn_dec_rval_t rv = {RC_OK, 0};
914         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
915     const asn_TYPE_member_t *elm = td->elements; /* Single one */
916     void *st = *sptr;
917         asn_anonymous_set_ *list;
918         const asn_per_constraint_t *ct;
919         int repeat = 0;
920         ssize_t nelems;
921
922         if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
923                 ASN__DECODE_FAILED;
924
925         /*
926          * Create the target structure if it is not present already.
927          */
928         if(!st) {
929                 st = *sptr = CALLOC(1, specs->struct_size);
930                 if(!st) ASN__DECODE_FAILED;
931         }                                                                       
932         list = _A_SET_FROM_VOID(st);
933
934         /* Figure out which constraints to use */
935         if(constraints) ct = &constraints->size;
936         else if(td->encoding_constraints.per_constraints)
937                 ct = &td->encoding_constraints.per_constraints->size;
938         else ct = 0;
939
940         if(ct && ct->flags & APC_EXTENSIBLE) {
941                 int value = per_get_few_bits(pd, 1);
942                 if(value < 0) ASN__DECODE_STARVED;
943                 if(value) ct = 0;       /* Not restricted! */
944         }
945
946         if(ct && ct->effective_bits >= 0) {
947                 /* X.691, #19.5: No length determinant */
948                 nelems = per_get_few_bits(pd, ct->effective_bits);
949                 ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
950                         (long)nelems, ct->lower_bound, td->name);
951                 if(nelems < 0)  ASN__DECODE_STARVED;
952                 nelems += ct->lower_bound;
953         } else {
954                 nelems = -1;
955         }
956
957         do {
958                 int i;
959                 if(nelems < 0) {
960                         nelems = uper_get_length(pd, -1, 0, &repeat);
961             ASN_DEBUG("Got to decode %" ASN_PRI_SSIZE " elements (eff %d)",
962                       nelems, (int)(ct ? ct->effective_bits : -1));
963             if(nelems < 0) ASN__DECODE_STARVED;
964                 }
965
966                 for(i = 0; i < nelems; i++) {
967                         void *ptr = 0;
968                         ASN_DEBUG("SET OF %s decoding", elm->type->name);
969                         rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,
970                                 elm->encoding_constraints.per_constraints, &ptr, pd);
971                         ASN_DEBUG("%s SET OF %s decoded %d, %p",
972                                 td->name, elm->type->name, rv.code, ptr);
973                         if(rv.code == RC_OK) {
974                                 if(ASN_SET_ADD(list, ptr) == 0) {
975                     if(rv.consumed == 0 && nelems > 200) {
976                         /* Protect from SET OF NULL compression bombs. */
977                         ASN__DECODE_FAILED;
978                     }
979                                         continue;
980                 }
981                                 ASN_DEBUG("Failed to add element into %s",
982                                         td->name);
983                                 /* Fall through */
984                                 rv.code = RC_FAIL;
985                         } else {
986                                 ASN_DEBUG("Failed decoding %s of %s (SET OF)",
987                                         elm->type->name, td->name);
988                         }
989                         if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
990                         return rv;
991                 }
992
993                 nelems = -1;    /* Allow uper_get_length() */
994         } while(repeat);
995
996         ASN_DEBUG("Decoded %s as SET OF", td->name);
997
998         rv.code = RC_OK;
999         rv.consumed = 0;
1000         return rv;
1001 }
1002
1003 asn_enc_rval_t
1004 SET_OF_encode_uper(const asn_TYPE_descriptor_t *td,
1005                    const asn_per_constraints_t *constraints, const void *sptr,
1006                    asn_per_outp_t *po) {
1007     const asn_anonymous_set_ *list;
1008     const asn_per_constraint_t *ct;
1009     const asn_TYPE_member_t *elm = td->elements;
1010     struct _el_buffer *encoded_els;
1011     asn_enc_rval_t er = {0,0,0};
1012     size_t encoded_edx;
1013
1014     if(!sptr) ASN__ENCODE_FAILED;
1015
1016     list = _A_CSET_FROM_VOID(sptr);
1017
1018     er.encoded = 0;
1019
1020     ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count);
1021
1022     if(constraints) ct = &constraints->size;
1023     else if(td->encoding_constraints.per_constraints)
1024         ct = &td->encoding_constraints.per_constraints->size;
1025     else ct = 0;
1026
1027     /* If extensible constraint, check if size is in root */
1028     if(ct) {
1029         int not_in_root =
1030             (list->count < ct->lower_bound || list->count > ct->upper_bound);
1031         ASN_DEBUG("lb %ld ub %ld %s", ct->lower_bound, ct->upper_bound,
1032                   ct->flags & APC_EXTENSIBLE ? "ext" : "fix");
1033         if(ct->flags & APC_EXTENSIBLE) {
1034             /* Declare whether size is in extension root */
1035             if(per_put_few_bits(po, not_in_root, 1)) ASN__ENCODE_FAILED;
1036             if(not_in_root) ct = 0;
1037         } else if(not_in_root && ct->effective_bits >= 0) {
1038             ASN__ENCODE_FAILED;
1039         }
1040
1041     }
1042
1043     if(ct && ct->effective_bits >= 0) {
1044         /* X.691, #19.5: No length determinant */
1045         if(per_put_few_bits(po, list->count - ct->lower_bound,
1046                             ct->effective_bits))
1047             ASN__ENCODE_FAILED;
1048     } else if(list->count == 0) {
1049         /* When the list is empty add only the length determinant
1050          * X.691, #20.6 and #11.9.4.1
1051          */
1052         if (uper_put_length(po, 0, 0)) {
1053             ASN__ENCODE_FAILED;
1054         }
1055         ASN__ENCODED_OK(er);
1056     }
1057
1058
1059     /*
1060      * Canonical UPER #22.1 mandates dynamic sorting of the SET OF elements
1061      * according to their encodings. Build an array of the encoded elements.
1062      */
1063     encoded_els = SET_OF__encode_sorted(elm, list, SOES_CUPER);
1064
1065     for(encoded_edx = 0; (ssize_t)encoded_edx < list->count;) {
1066         ssize_t may_encode;
1067         size_t edx;
1068         int need_eom = 0;
1069
1070         if(ct && ct->effective_bits >= 0) {
1071             may_encode = list->count;
1072         } else {
1073             may_encode =
1074                 uper_put_length(po, list->count - encoded_edx, &need_eom);
1075             if(may_encode < 0) ASN__ENCODE_FAILED;
1076         }
1077
1078         for(edx = encoded_edx; edx < encoded_edx + may_encode; edx++) {
1079             const struct _el_buffer *el = &encoded_els[edx];
1080             if(asn_put_many_bits(po, el->buf,
1081                                  (8 * el->length) - el->bits_unused) < 0) {
1082                 break;
1083             }
1084         }
1085
1086         if(need_eom && uper_put_length(po, 0, 0))
1087             ASN__ENCODE_FAILED; /* End of Message length */
1088
1089         encoded_edx += may_encode;
1090     }
1091
1092     SET_OF__encode_sorted_free(encoded_els, list->count);
1093
1094     if((ssize_t)encoded_edx == list->count) {
1095         ASN__ENCODED_OK(er);
1096     } else {
1097         ASN__ENCODE_FAILED;
1098     }
1099 }
1100
1101 asn_dec_rval_t
1102 SET_OF_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
1103                    const asn_TYPE_descriptor_t *td,
1104                    const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
1105         asn_dec_rval_t rv = {RC_OK, 0};
1106         const asn_SET_OF_specifics_t *specs = (const asn_SET_OF_specifics_t *)td->specifics;
1107         const asn_TYPE_member_t *elm = td->elements; /* Single one */
1108         void *st = *sptr;
1109         asn_anonymous_set_ *list;
1110         const asn_per_constraint_t *ct;
1111         int repeat = 0;
1112         ssize_t nelems;
1113
1114         if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
1115                 ASN__DECODE_FAILED;
1116
1117         /*
1118          * Create the target structure if it is not present already.
1119          */
1120         if(!st) {
1121                 st = *sptr = CALLOC(1, specs->struct_size);
1122                 if(!st) ASN__DECODE_FAILED;
1123         }
1124         list = _A_SET_FROM_VOID(st);
1125
1126         /* Figure out which constraints to use */
1127         if(constraints) ct = &constraints->size;
1128         else if(td->encoding_constraints.per_constraints)
1129                 ct = &td->encoding_constraints.per_constraints->size;
1130         else ct = 0;
1131
1132         if(ct && ct->flags & APC_EXTENSIBLE) {
1133                 int value = per_get_few_bits(pd, 1);
1134                 if(value < 0) ASN__DECODE_STARVED;
1135                 if(value) ct = 0;       /* Not restricted! */
1136         }
1137
1138         if(ct && ct->effective_bits >= 0) {
1139                 /* X.691, #19.5: No length determinant */
1140                 nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound + 1);
1141                 ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s",
1142                           (long)nelems, ct->lower_bound, td->name);
1143                 if(nelems < 0)  ASN__DECODE_STARVED;
1144                 nelems += ct->lower_bound;
1145         } else {
1146                 nelems = -1;
1147         }
1148
1149         do {
1150                 int i;
1151                 if(nelems < 0) {
1152                         nelems = aper_get_length(pd, ct ? ct->upper_bound - ct->lower_bound + 1 : -1,
1153                                                  ct ? ct->effective_bits : -1, &repeat);
1154                         ASN_DEBUG("Got to decode %d elements (eff %d)",
1155                                   (int)nelems, (int)(ct ? ct->effective_bits : -1));
1156                         if(nelems < 0) ASN__DECODE_STARVED;
1157                 }
1158
1159                 for(i = 0; i < nelems; i++) {
1160                         void *ptr = 0;
1161                         ASN_DEBUG("SET OF %s decoding", elm->type->name);
1162                         rv = elm->type->op->aper_decoder(opt_codec_ctx, elm->type,
1163                                                          elm->encoding_constraints.per_constraints, &ptr, pd);
1164                         ASN_DEBUG("%s SET OF %s decoded %d, %p",
1165                                   td->name, elm->type->name, rv.code, ptr);
1166                         if(rv.code == RC_OK) {
1167                                 if(ASN_SET_ADD(list, ptr) == 0)
1168                                         continue;
1169                                 ASN_DEBUG("Failed to add element into %s",
1170                                           td->name);
1171                                 /* Fall through */
1172                                 rv.code = RC_FAIL;
1173                         } else {
1174                                 ASN_DEBUG("Failed decoding %s of %s (SET OF)",
1175                                           elm->type->name, td->name);
1176                         }
1177                         if(ptr) ASN_STRUCT_FREE(*elm->type, ptr);
1178                         return rv;
1179                 }
1180
1181                 nelems = -1;    /* Allow uper_get_length() */
1182         } while(repeat);
1183
1184         ASN_DEBUG("Decoded %s as SET OF", td->name);
1185
1186         rv.code = RC_OK;
1187         rv.consumed = 0;
1188         return rv;
1189 }
1190
1191 #endif  /* ASN_DISABLE_PER_SUPPORT */
1192
1193 struct comparable_ptr {
1194     const asn_TYPE_descriptor_t *td;
1195     const void *sptr;
1196 };
1197
1198 static int
1199 SET_OF__compare_cb(const void *aptr, const void *bptr) {
1200     const struct comparable_ptr *a = aptr;
1201     const struct comparable_ptr *b = bptr;
1202     assert(a->td == b->td);
1203     return a->td->op->compare_struct(a->td, a->sptr, b->sptr);
1204 }
1205
1206 int
1207 SET_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
1208                const void *bptr) {
1209     const asn_anonymous_set_ *a = _A_CSET_FROM_VOID(aptr);
1210     const asn_anonymous_set_ *b = _A_CSET_FROM_VOID(bptr);
1211
1212     if(a && b) {
1213         struct comparable_ptr *asorted;
1214         struct comparable_ptr *bsorted;
1215         ssize_t common_length;
1216         ssize_t idx;
1217
1218         if(a->count == 0) {
1219             if(b->count) return -1;
1220             return 0;
1221         } else if(b->count == 0) {
1222             return 1;
1223         }
1224
1225         asorted = MALLOC(a->count * sizeof(asorted[0]));
1226         bsorted = MALLOC(b->count * sizeof(bsorted[0]));
1227         if(!asorted || !bsorted) {
1228             FREEMEM(asorted);
1229             FREEMEM(bsorted);
1230             return -1;
1231         }
1232
1233         for(idx = 0; idx < a->count; idx++) {
1234             asorted[idx].td = td->elements->type;
1235             asorted[idx].sptr = a->array[idx];
1236         }
1237
1238         for(idx = 0; idx < b->count; idx++) {
1239             bsorted[idx].td = td->elements->type;
1240             bsorted[idx].sptr = b->array[idx];
1241         }
1242
1243         qsort(asorted, a->count, sizeof(asorted[0]), SET_OF__compare_cb);
1244         qsort(bsorted, b->count, sizeof(bsorted[0]), SET_OF__compare_cb);
1245
1246         common_length = (a->count < b->count ? a->count : b->count);
1247         for(idx = 0; idx < common_length; idx++) {
1248             int ret = td->elements->type->op->compare_struct(
1249                 td->elements->type, asorted[idx].sptr, bsorted[idx].sptr);
1250             if(ret) {
1251                 FREEMEM(asorted);
1252                 FREEMEM(bsorted);
1253                 return ret;
1254             }
1255         }
1256
1257         FREEMEM(asorted);
1258         FREEMEM(bsorted);
1259
1260         if(idx < b->count) /* more elements in b */
1261             return -1;     /* a is shorter, so put it first */
1262         if(idx < a->count) return 1;
1263     } else if(!a) {
1264         return -1;
1265     } else if(!b) {
1266         return 1;
1267     }
1268
1269         return 0;
1270 }
1271
1272
1273 asn_TYPE_operation_t asn_OP_SET_OF = {
1274         SET_OF_free,
1275         SET_OF_print,
1276         SET_OF_compare,
1277         SET_OF_decode_ber,
1278         SET_OF_encode_der,
1279         SET_OF_decode_xer,
1280         SET_OF_encode_xer,
1281 #ifdef ASN_DISABLE_OER_SUPPORT
1282         0,
1283         0,
1284 #else
1285         SET_OF_decode_oer,
1286         SET_OF_encode_oer,
1287 #endif
1288 #ifdef ASN_DISABLE_PER_SUPPORT
1289         0,
1290         0,
1291         0,
1292         0,
1293 #else
1294         SET_OF_decode_uper,
1295         SET_OF_encode_uper,
1296         SET_OF_decode_aper,
1297         0,      /* SET_OF_encode_aper */
1298 #endif /* ASN_DISABLE_PER_SUPPORT */
1299         SET_OF_random_fill,
1300         0       /* Use generic outmost tag fetcher */
1301 };
1302
1303
1304 asn_random_fill_result_t
1305 SET_OF_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
1306                    const asn_encoding_constraints_t *constraints,
1307                    size_t max_length) {
1308     const asn_SET_OF_specifics_t *specs =
1309         (const asn_SET_OF_specifics_t *)td->specifics;
1310     asn_random_fill_result_t res_ok = {ARFILL_OK, 0};
1311     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
1312     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
1313     const asn_TYPE_member_t *elm = td->elements;
1314     void *st = *sptr;
1315     long max_elements = 5;
1316     long slb = 0;   /* Lower size bound */
1317     long sub = 0;   /* Upper size bound */
1318     size_t rnd_len;
1319
1320     if(max_length == 0) return result_skipped;
1321
1322     if(st == NULL) {
1323         st = (*sptr = CALLOC(1, specs->struct_size));
1324         if(st == NULL) {
1325             return result_failed;
1326         }
1327     }
1328
1329     switch(asn_random_between(0, 6)) {
1330     case 0: max_elements = 0; break;
1331     case 1: max_elements = 1; break;
1332     case 2: max_elements = 5; break;
1333     case 3: max_elements = max_length; break;
1334     case 4: max_elements = max_length / 2; break;
1335     case 5: max_elements = max_length / 4; break;
1336     default: break;
1337     }
1338     sub = slb + max_elements;
1339
1340     if(!constraints || !constraints->per_constraints)
1341         constraints = &td->encoding_constraints;
1342     if(constraints->per_constraints) {
1343         const asn_per_constraint_t *pc = &constraints->per_constraints->size;
1344         if(pc->flags & APC_SEMI_CONSTRAINED) {
1345             slb = pc->lower_bound;
1346             sub = pc->lower_bound + max_elements;
1347         } else if(pc->flags & APC_CONSTRAINED) {
1348             slb = pc->lower_bound;
1349             sub = pc->upper_bound;
1350             if(sub - slb > max_elements) sub = slb + max_elements;
1351         }
1352     }
1353
1354     /* Bias towards edges of allowed space */
1355     switch(asn_random_between(-1, 4)) {
1356     default:
1357     case -1:
1358         /* Prepare lengths somewhat outside of constrained range. */
1359         if(constraints->per_constraints
1360            && (constraints->per_constraints->size.flags & APC_EXTENSIBLE)) {
1361             switch(asn_random_between(0, 5)) {
1362             default:
1363             case 0:
1364                 rnd_len = 0;
1365                 break;
1366             case 1:
1367                 if(slb > 0) {
1368                     rnd_len = slb - 1;
1369                 } else {
1370                     rnd_len = 0;
1371                 }
1372                 break;
1373             case 2:
1374                 rnd_len = asn_random_between(0, slb);
1375                 break;
1376             case 3:
1377                 if(sub < (ssize_t)max_length) {
1378                     rnd_len = sub + 1;
1379                 } else {
1380                     rnd_len = max_length;
1381                 }
1382                 break;
1383             case 4:
1384                 if(sub < (ssize_t)max_length) {
1385                     rnd_len = asn_random_between(sub + 1, max_length);
1386                 } else {
1387                     rnd_len = max_length;
1388                 }
1389                 break;
1390             case 5:
1391                 rnd_len = max_length;
1392                 break;
1393             }
1394             break;
1395         }
1396         /* Fall through */
1397     case 0:
1398         rnd_len = asn_random_between(slb, sub);
1399         break;
1400     case 1:
1401         if(slb < sub) {
1402             rnd_len = asn_random_between(slb + 1, sub);
1403             break;
1404         }
1405         /* Fall through */
1406     case 2:
1407         rnd_len = asn_random_between(slb, slb);
1408         break;
1409     case 3:
1410         if(slb < sub) {
1411             rnd_len = asn_random_between(slb, sub - 1);
1412             break;
1413         }
1414         /* Fall through */
1415     case 4:
1416         rnd_len = asn_random_between(sub, sub);
1417         break;
1418     }
1419
1420     for(; rnd_len > 0; rnd_len--) {
1421         asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);
1422         void *ptr = 0;
1423         asn_random_fill_result_t tmpres = elm->type->op->random_fill(
1424             elm->type, &ptr, &elm->encoding_constraints,
1425             (max_length > res_ok.length ? max_length - res_ok.length : 0)
1426                 / rnd_len);
1427         switch(tmpres.code) {
1428         case ARFILL_OK:
1429             ASN_SET_ADD(list, ptr);
1430             res_ok.length += tmpres.length;
1431             break;
1432         case ARFILL_SKIPPED:
1433             break;
1434         case ARFILL_FAILED:
1435             assert(ptr == 0);
1436             return tmpres;
1437         }
1438     }
1439
1440     return res_ok;
1441 }
1442