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