ISSUE ID:- RICAPP-216
[ric-app/bouncer.git] / Bouncer / e2sm_kpm / lib / constr_SET.c
1 /*
2  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <constr_SET.h>
8
9 /* Check that all the mandatory members are present */
10 static int _SET_is_populated(const asn_TYPE_descriptor_t *td, const void *st);
11
12 /*
13  * Number of bytes left for this structure.
14  * (ctx->left) indicates the number of bytes _transferred_ for the structure.
15  * (size) contains the number of bytes in the buffer passed.
16  */
17 #define LEFT    ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
18
19 /*
20  * If the subprocessor function returns with an indication that it wants
21  * more data, it may well be a fatal decoding problem, because the
22  * size is constrained by the <TLV>'s L, even if the buffer size allows
23  * reading more data.
24  * For example, consider the buffer containing the following TLVs:
25  * <T:5><L:1><V> <T:6>...
26  * The TLV length clearly indicates that one byte is expected in V, but
27  * if the V processor returns with "want more data" even if the buffer
28  * contains way more data than the V processor have seen.
29  */
30 #define SIZE_VIOLATION  (ctx->left >= 0 && (size_t)ctx->left <= size)
31
32 /*
33  * This macro "eats" the part of the buffer which is definitely "consumed",
34  * i.e. was correctly converted into local representation or rightfully skipped.
35  */
36 #undef  ADVANCE
37 #define ADVANCE(num_bytes)      do {            \
38                 size_t num = num_bytes;         \
39                 ptr = ((const char *)ptr) + num;\
40                 size -= num;                    \
41                 if(ctx->left >= 0)              \
42                         ctx->left -= num;       \
43                 consumed_myself += num;         \
44         } while(0)
45
46 /*
47  * Switch to the next phase of parsing.
48  */
49 #undef  NEXT_PHASE
50 #define NEXT_PHASE(ctx) do {                    \
51                 ctx->phase++;                   \
52                 ctx->step = 0;                  \
53         } while(0)
54
55 /*
56  * Return a standardized complex structure.
57  */
58 #undef  RETURN
59 #define RETURN(_code)   do {                    \
60                 rval.code = _code;              \
61                 rval.consumed = consumed_myself;\
62                 return rval;                    \
63         } while(0)
64
65 /*
66  * Tags are canonically sorted in the tag2element map.
67  */
68 static int
69 _t2e_cmp(const void *ap, const void *bp) {
70         const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
71         const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
72
73         int a_class = BER_TAG_CLASS(a->el_tag);
74         int b_class = BER_TAG_CLASS(b->el_tag);
75
76         if(a_class == b_class) {
77                 ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
78                 ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
79
80                 if(a_value == b_value)
81                         return 0;
82                 else if(a_value < b_value)
83                         return -1;
84                 else
85                         return 1;
86         } else if(a_class < b_class) {
87                 return -1;
88         } else {
89                 return 1;
90         }
91 }
92
93 /*
94  * The decoder of the SET type.
95  */
96 asn_dec_rval_t
97 SET_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
98                const asn_TYPE_descriptor_t *td, void **struct_ptr,
99                const void *ptr, size_t size, int tag_mode) {
100     /*
101          * Bring closer parts of structure description.
102          */
103         const asn_SET_specifics_t *specs = (const asn_SET_specifics_t *)td->specifics;
104         const asn_TYPE_member_t *elements = td->elements;
105
106         /*
107          * Parts of the structure being constructed.
108          */
109         void *st = *struct_ptr; /* Target structure. */
110         asn_struct_ctx_t *ctx;  /* Decoder context */
111
112         ber_tlv_tag_t tlv_tag;  /* T from TLV */
113         asn_dec_rval_t rval;    /* Return code from subparsers */
114
115         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
116         size_t edx;                     /* SET element's index */
117
118         ASN_DEBUG("Decoding %s as SET", td->name);
119
120         if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
121                 ASN__DECODE_FAILED;
122
123         /*
124          * Create the target structure if it is not present already.
125          */
126         if(st == 0) {
127                 st = *struct_ptr = CALLOC(1, specs->struct_size);
128                 if(st == 0) {
129                         RETURN(RC_FAIL);
130                 }
131         }
132
133         /*
134          * Restore parsing context.
135          */
136         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
137         
138         /*
139          * Start to parse where left previously
140          */
141         switch(ctx->phase) {
142         case 0:
143                 /*
144                  * PHASE 0.
145                  * Check that the set of tags associated with given structure
146                  * perfectly fits our expectations.
147                  */
148
149                 rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
150                         tag_mode, 1, &ctx->left, 0);
151                 if(rval.code != RC_OK) {
152                         ASN_DEBUG("%s tagging check failed: %d",
153                                 td->name, rval.code);
154                         return rval;
155                 }
156
157                 if(ctx->left >= 0)
158                         ctx->left += rval.consumed; /* ?Substracted below! */
159                 ADVANCE(rval.consumed);
160
161                 NEXT_PHASE(ctx);
162
163                 ASN_DEBUG("Structure advertised %ld bytes, "
164                         "buffer contains %ld", (long)ctx->left, (long)size);
165
166                 /* Fall through */
167         case 1:
168                 /*
169                  * PHASE 1.
170                  * From the place where we've left it previously,
171                  * try to decode the next member from the list of
172                  * this structure's elements.
173                  * Note that elements in BER may arrive out of
174                  * order, yet DER mandates that they shall arive in the
175                  * canonical order of their tags. So, there is a room
176                  * for optimization.
177                  */
178           for(;; ctx->step = 0) {
179                 const asn_TYPE_tag2member_t *t2m;
180                 asn_TYPE_tag2member_t key;
181                 void *memb_ptr;         /* Pointer to the member */
182                 void **memb_ptr2;       /* Pointer to that pointer */
183                 ssize_t tag_len;        /* Length of TLV's T */
184
185                 if(ctx->step & 1) {
186                         edx = ctx->step >> 1;
187                         goto microphase2;
188                 }
189
190                 /*
191                  * MICROPHASE 1: Synchronize decoding.
192                  */
193
194                 if(ctx->left == 0)
195                         /*
196                          * No more things to decode.
197                          * Exit out of here and check whether all mandatory
198                          * elements have been received (in the next phase).
199                          */
200                         break;
201
202                 /*
203                  * Fetch the T from TLV.
204                  */
205                 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
206                 switch(tag_len) {
207                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
208                         /* Fall through */
209                 case -1: RETURN(RC_FAIL);
210                 }
211
212                 if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
213                         if(LEFT < 2) {
214                                 if(SIZE_VIOLATION)
215                                         RETURN(RC_FAIL);
216                                 else
217                                         RETURN(RC_WMORE);
218                         } else if(((const uint8_t *)ptr)[1] == 0) {
219                                 /*
220                                  * Found the terminator of the
221                                  * indefinite length structure.
222                                  * Invoke the generic finalization function.
223                                  */
224                                 goto phase3;
225                         }
226                 }
227
228                 key.el_tag = tlv_tag;
229                 t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,
230                                 specs->tag2el, specs->tag2el_count,
231                                 sizeof(specs->tag2el[0]), _t2e_cmp);
232                 if(t2m) {
233                         /*
234                          * Found the element corresponding to the tag.
235                          */
236                         edx = t2m->el_no;
237                         ctx->step = (edx << 1) + 1;
238                         ASN_DEBUG("Got tag %s (%s), edx %" ASN_PRI_SSIZE "",
239                                 ber_tlv_tag_string(tlv_tag), td->name, edx);
240                 } else if(specs->extensible == 0) {
241                         ASN_DEBUG("Unexpected tag %s "
242                                 "in non-extensible SET %s",
243                                 ber_tlv_tag_string(tlv_tag), td->name);
244                         RETURN(RC_FAIL);
245                 } else {
246                         /* Skip this tag */
247                         ssize_t skip;
248
249                         ASN_DEBUG("Skipping unknown tag %s",
250                                 ber_tlv_tag_string(tlv_tag));
251
252                         skip = ber_skip_length(opt_codec_ctx,
253                                 BER_TLV_CONSTRUCTED(ptr),
254                                 (const char *)ptr + tag_len, LEFT - tag_len);
255
256                         switch(skip) {
257                         case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
258                                 /* Fall through */
259                         case -1: RETURN(RC_FAIL);
260                         }
261
262                         ADVANCE(skip + tag_len);
263                         continue;  /* Try again with the next tag */
264                 }
265
266                 /*
267                  * MICROPHASE 2: Invoke the member-specific decoder.
268                  */
269         microphase2:
270
271                 /*
272                  * Check for duplications: must not overwrite
273                  * already decoded elements.
274                  */
275                 if(ASN_SET_ISPRESENT2((char *)st + specs->pres_offset, edx)) {
276                         ASN_DEBUG("SET %s: Duplicate element %s (%" ASN_PRI_SSIZE ")",
277                                 td->name, elements[edx].name, edx);
278                         RETURN(RC_FAIL);
279                 }
280                 
281                 /*
282                  * Compute the position of the member inside a structure,
283                  * and also a type of containment (it may be contained
284                  * as pointer or using inline inclusion).
285                  */
286                 if(elements[edx].flags & ATF_POINTER) {
287                         /* Member is a pointer to another structure */
288                         memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
289                 } else {
290                         /*
291                          * A pointer to a pointer
292                          * holding the start of the structure
293                          */
294                         memb_ptr = (char *)st + elements[edx].memb_offset;
295                         memb_ptr2 = &memb_ptr;
296                 }
297                 /*
298                  * Invoke the member fetch routine according to member's type
299                  */
300                 rval = elements[edx].type->op->ber_decoder(opt_codec_ctx,
301                                 elements[edx].type,
302                                 memb_ptr2, ptr, LEFT,
303                                 elements[edx].tag_mode);
304                 switch(rval.code) {
305                 case RC_OK:
306                         ASN_SET_MKPRESENT((char *)st + specs->pres_offset, edx);
307                         break;
308                 case RC_WMORE: /* More data expected */
309                         if(!SIZE_VIOLATION) {
310                                 ADVANCE(rval.consumed);
311                                 RETURN(RC_WMORE);
312                         }
313                         /* Fall through */
314                 case RC_FAIL: /* Fatal error */
315                         RETURN(RC_FAIL);
316                 } /* switch(rval) */
317                 
318                 ADVANCE(rval.consumed);
319           }     /* for(all structure members) */
320
321         phase3:
322                 ctx->phase = 3;
323                 /* Fall through */
324         case 3:
325         case 4: /* Only 00 is expected */
326                 ASN_DEBUG("SET %s Leftover: %ld, size = %ld",
327                         td->name, (long)ctx->left, (long)size);
328
329                 /*
330                  * Skip everything until the end of the SET.
331                  */
332                 while(ctx->left) {
333                         ssize_t tl, ll;
334
335                         tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
336                         switch(tl) {
337                         case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
338                                 /* Fall through */
339                         case -1: RETURN(RC_FAIL);
340                         }
341
342                         /*
343                          * If expected <0><0>...
344                          */
345                         if(ctx->left < 0
346                                 && ((const uint8_t *)ptr)[0] == 0) {
347                                 if(LEFT < 2) {
348                                         if(SIZE_VIOLATION)
349                                                 RETURN(RC_FAIL);
350                                         else
351                                                 RETURN(RC_WMORE);
352                                 } else if(((const uint8_t *)ptr)[1] == 0) {
353                                         /*
354                                          * Correctly finished with <0><0>.
355                                          */
356                                         ADVANCE(2);
357                                         ctx->left++;
358                                         ctx->phase = 4;
359                                         continue;
360                                 }
361                         }
362
363                         if(specs->extensible == 0 || ctx->phase == 4) {
364                                 ASN_DEBUG("Unexpected continuation "
365                                         "of a non-extensible type %s "
366                                         "(ptr=%02x)",
367                                         td->name, *(const uint8_t *)ptr);
368                                 RETURN(RC_FAIL);
369                         }
370
371                         ll = ber_skip_length(opt_codec_ctx,
372                                 BER_TLV_CONSTRUCTED(ptr),
373                                 (const char *)ptr + tl, LEFT - tl);
374                         switch(ll) {
375                         case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
376                                 /* Fall through */
377                         case -1: RETURN(RC_FAIL);
378                         }
379
380                         ADVANCE(tl + ll);
381                 }
382
383                 ctx->phase = 5;
384         /* Fall through */
385         case 5:
386                 /* Check that all mandatory elements are present. */
387                 if(!_SET_is_populated(td, st))
388                         RETURN(RC_FAIL);
389
390                 NEXT_PHASE(ctx);
391         }
392         
393         RETURN(RC_OK);
394 }
395
396 static int
397 _SET_is_populated(const asn_TYPE_descriptor_t *td, const void *st) {
398     const asn_SET_specifics_t *specs = (const asn_SET_specifics_t *)td->specifics;
399         size_t edx;
400
401         /*
402          * Check that all mandatory elements are present.
403          */
404         for(edx = 0; edx < td->elements_count;
405                 edx += (8 * sizeof(specs->_mandatory_elements[0]))) {
406                 unsigned int midx, pres, must;
407
408                 midx = edx/(8 * sizeof(specs->_mandatory_elements[0]));
409         pres = ((const unsigned int *)((const char *)st
410                                        + specs->pres_offset))[midx];
411         must = sys_ntohl(specs->_mandatory_elements[midx]);
412
413                 if((pres & must) == must) {
414                         /*
415                          * Yes, everything seems to be in place.
416                          */
417                 } else {
418                         ASN_DEBUG("One or more mandatory elements "
419                                 "of a SET %s %d (%08x.%08x)=%08x "
420                                 "are not present",
421                                 td->name,
422                                 midx,
423                                 pres,
424                                 must,
425                                 (~(pres & must) & must)
426                         );
427                         return 0;
428                 }
429         }
430
431         return 1;
432 }
433
434 /*
435  * The DER encoder of the SET type.
436  */
437 asn_enc_rval_t
438 SET_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr, int tag_mode,
439                ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) {
440     const asn_SET_specifics_t *specs = (const asn_SET_specifics_t *)td->specifics;
441         size_t computed_size = 0;
442         asn_enc_rval_t er;
443         int t2m_build_own = (specs->tag2el_count != td->elements_count);
444         const asn_TYPE_tag2member_t *t2m;
445         asn_TYPE_tag2member_t *t2m_build;
446         size_t t2m_count;
447         ssize_t ret;
448         size_t edx;
449
450         /*
451          * Use existing, or build our own tags map.
452          */
453         if(t2m_build_own) {
454         t2m_build = (asn_TYPE_tag2member_t *)CALLOC(td->elements_count,
455                                                     sizeof(t2m_build[0]));
456         if(!t2m_build) ASN__ENCODE_FAILED;
457                 t2m_count = 0;
458         } else {
459                 t2m_build = NULL;
460                 /*
461                  * There is no untagged CHOICE in this SET.
462                  * Employ existing table.
463                  */
464         }
465
466         /*
467          * Gather the length of the underlying members sequence.
468          */
469         for(edx = 0; edx < td->elements_count; edx++) {
470                 asn_TYPE_member_t *elm = &td->elements[edx];
471                 asn_enc_rval_t tmper;
472                 const void *memb_ptr_dontuse; /* Pointer to the member */
473         const void *const *memb_ptr2; /* Pointer to that pointer */
474
475         /*
476                  * Compute the length of the encoding of this member.
477                  */
478                 if(elm->flags & ATF_POINTER) {
479             memb_ptr2 =
480                 (const void *const *)((const char *)sptr + elm->memb_offset);
481             if(!*memb_ptr2) {
482                                 if(!elm->optional) {
483                                         /* Mandatory elements missing */
484                                         FREEMEM(t2m_build);
485                                         ASN__ENCODE_FAILED;
486                                 }
487                                 if(t2m_build) {
488                                         t2m_build[t2m_count].el_no = edx;
489                                         t2m_build[t2m_count].el_tag = 0;
490                                         t2m_count++;
491                                 }
492                                 continue;
493                         }
494                 } else {
495             memb_ptr_dontuse =
496                 (const void *)((const char *)sptr + elm->memb_offset);
497             memb_ptr2 = &memb_ptr_dontuse; /* Only use of memb_ptr_dontuse */
498                 }
499
500                 /* Eliminate default values */
501         if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0) {
502             if(t2m_build) {
503                                 t2m_build[t2m_count].el_no = edx;
504                                 t2m_build[t2m_count].el_tag = 0;
505                                 t2m_count++;
506                         }
507                         continue;
508                 }
509
510                 tmper = elm->type->op->der_encoder(elm->type, *memb_ptr2,
511                         elm->tag_mode, elm->tag,
512                         0, 0);
513                 if(tmper.encoded == -1)
514                         return tmper;
515                 computed_size += tmper.encoded;
516
517                 /*
518                  * Remember the outmost tag of this member.
519                  */
520                 if(t2m_build) {
521                         t2m_build[t2m_count].el_no = edx;
522                         t2m_build[t2m_count].el_tag = asn_TYPE_outmost_tag(
523                                 elm->type, *memb_ptr2, elm->tag_mode, elm->tag);
524                         t2m_count++;
525                 } else {
526                         /*
527                          * No dynamic sorting is necessary.
528                          */
529                 }
530         }
531
532         /*
533          * Finalize order of the components.
534          */
535         if(t2m_build) {
536                 /*
537                  * Sort the underlying members according to their
538                  * canonical tags order. DER encoding mandates it.
539                  */
540                 qsort(t2m_build, t2m_count, sizeof(specs->tag2el[0]), _t2e_cmp);
541                 t2m = t2m_build;
542         } else {
543                 /*
544                  * Tags are already sorted by the compiler.
545                  */
546                 t2m = specs->tag2el;
547                 t2m_count = specs->tag2el_count;
548         }
549         assert(t2m_count == td->elements_count);
550
551         /*
552          * Encode the TLV for the sequence itself.
553          */
554         ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
555         if(ret == -1) {
556                 FREEMEM(t2m_build);
557                 ASN__ENCODE_FAILED;
558         }
559         er.encoded = computed_size + ret;
560
561         if(!cb) {
562                 FREEMEM(t2m_build);
563                 ASN__ENCODED_OK(er);
564     }
565
566         /*
567          * Encode all members.
568          */
569         for(edx = 0; edx < td->elements_count; edx++) {
570                 asn_TYPE_member_t *elm;
571                 asn_enc_rval_t tmper;
572
573                 const void *memb_ptr_dontuse;           /* Pointer to the member */
574         const void *const *memb_ptr2;       /* Pointer to that pointer */
575
576         /* Encode according to the tag order */
577                 elm = &td->elements[t2m[edx].el_no];
578
579                 if(elm->flags & ATF_POINTER) {
580             memb_ptr2 =
581                 (const void *const *)((const char *)sptr + elm->memb_offset);
582             if(!*memb_ptr2) continue;
583                 } else {
584             memb_ptr_dontuse =
585                 (const void *)((const char *)sptr + elm->memb_offset);
586             memb_ptr2 = &memb_ptr_dontuse; /* Only use of memb_ptr_dontuse */
587                 }
588
589                 /* Eliminate default values */
590         if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)
591             continue;
592
593                 tmper = elm->type->op->der_encoder(elm->type, *memb_ptr2,
594                         elm->tag_mode, elm->tag, cb, app_key);
595                 if(tmper.encoded == -1)
596                         return tmper;
597                 computed_size -= tmper.encoded;
598         }
599
600         if(computed_size != 0) {
601                 /*
602                  * Encoded size is not equal to the computed size.
603                  */
604                 FREEMEM(t2m_build);
605                 ASN__ENCODE_FAILED;
606         }
607
608     FREEMEM(t2m_build);
609         ASN__ENCODED_OK(er);
610 }
611
612 #undef  XER_ADVANCE
613 #define XER_ADVANCE(num_bytes)  do {                    \
614                 size_t num = num_bytes;                 \
615                 buf_ptr = ((const char *)buf_ptr) + num;\
616                 size -= num;                            \
617                 consumed_myself += num;                 \
618         } while(0)
619
620 /*
621  * Decode the XER (XML) data.
622  */
623 asn_dec_rval_t
624 SET_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
625                const asn_TYPE_descriptor_t *td, void **struct_ptr,
626                const char *opt_mname, const void *buf_ptr, size_t size) {
627     /*
628          * Bring closer parts of structure description.
629          */
630         const asn_SET_specifics_t *specs = (const asn_SET_specifics_t *)td->specifics;
631         const asn_TYPE_member_t *elements = td->elements;
632         const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
633
634         /*
635          * ... and parts of the structure being constructed.
636          */
637         void *st = *struct_ptr; /* Target structure. */
638         asn_struct_ctx_t *ctx;  /* Decoder context */
639
640         asn_dec_rval_t rval;            /* Return value from a decoder */
641         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
642         size_t edx;                     /* Element index */
643
644         /*
645          * Create the target structure if it is not present already.
646          */
647         if(st == 0) {
648                 st = *struct_ptr = CALLOC(1, specs->struct_size);
649                 if(st == 0) RETURN(RC_FAIL);
650         }
651
652         /*
653          * Restore parsing context.
654          */
655         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
656
657         /*
658          * Phases of XER/XML processing:
659          * Phase 0: Check that the opening tag matches our expectations.
660          * Phase 1: Processing body and reacting on closing tag.
661          * Phase 2: Processing inner type.
662          * Phase 3: Skipping unknown extensions.
663          * Phase 4: PHASED OUT
664          */
665         for(edx = ctx->step; ctx->phase <= 3;) {
666                 pxer_chunk_type_e ch_type;      /* XER chunk type */
667                 ssize_t ch_size;                /* Chunk size */
668                 xer_check_tag_e tcv;            /* Tag check value */
669                 const asn_TYPE_member_t *elm;
670
671                 /*
672                  * Go inside the inner member of a set.
673                  */
674                 if(ctx->phase == 2) {
675                         asn_dec_rval_t tmprval;
676                         void *memb_ptr_dontuse; /* Pointer to the member */
677                         void **memb_ptr2;       /* Pointer to that pointer */
678
679                         if(ASN_SET_ISPRESENT2((char *)st + specs->pres_offset,
680                                         edx)) {
681                                 ASN_DEBUG("SET %s: Duplicate element %s (%" ASN_PRI_SSIZE ")",
682                                 td->name, elements[edx].name, edx);
683                                 RETURN(RC_FAIL);
684                         }
685
686                         elm = &elements[edx];
687
688                         if(elm->flags & ATF_POINTER) {
689                                 /* Member is a pointer to another structure */
690                                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
691                         } else {
692                                 memb_ptr_dontuse = (char *)st + elm->memb_offset;
693                                 memb_ptr2 = &memb_ptr_dontuse; /* Only use of memb_ptr_dontuse */
694                         }
695
696                         /* Invoke the inner type decoder, m.b. multiple times */
697                         tmprval = elm->type->op->xer_decoder(opt_codec_ctx,
698                                         elm->type, memb_ptr2, elm->name,
699                                         buf_ptr, size);
700                         XER_ADVANCE(tmprval.consumed);
701                         if(tmprval.code != RC_OK)
702                                 RETURN(tmprval.code);
703                         ctx->phase = 1; /* Back to body processing */
704                         ASN_SET_MKPRESENT((char *)st + specs->pres_offset, edx);
705                         ASN_DEBUG("XER/SET phase => %d", ctx->phase);
706                         /* Fall through */
707                 }
708
709                 /*
710                  * Get the next part of the XML stream.
711                  */
712                 ch_size = xer_next_token(&ctx->context,
713                         buf_ptr, size, &ch_type);
714                 if(ch_size == -1) {
715                         RETURN(RC_FAIL);
716                 } else {
717                         switch(ch_type) {
718             case PXER_WMORE:
719                 RETURN(RC_WMORE);
720                         case PXER_COMMENT:      /* Got XML comment */
721                         case PXER_TEXT:         /* Ignore free-standing text */
722                                 XER_ADVANCE(ch_size);   /* Skip silently */
723                                 continue;
724                         case PXER_TAG:
725                                 break;  /* Check the rest down there */
726                         }
727                 }
728
729                 tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
730                 ASN_DEBUG("XER/SET: tcv = %d, ph=%d", tcv, ctx->phase);
731
732                 /* Skip the extensions section */
733                 if(ctx->phase == 3) {
734                         switch(xer_skip_unknown(tcv, &ctx->left)) {
735                         case -1:
736                                 ctx->phase = 4;
737                                 RETURN(RC_FAIL);
738                         case 1:
739                                 ctx->phase = 1;
740                                 /* Fall through */
741                         case 0:
742                                 XER_ADVANCE(ch_size);
743                                 continue;
744                         case 2:
745                                 ctx->phase = 1;
746                                 break;
747                         }
748                 }
749
750                 switch(tcv) {
751                 case XCT_CLOSING:
752                         if(ctx->phase == 0) break;
753                         ctx->phase = 0;
754                         /* Fall through */
755                 case XCT_BOTH:
756                         if(ctx->phase == 0) {
757                                 if(_SET_is_populated(td, st)) {
758                                         XER_ADVANCE(ch_size);
759                                         ctx->phase = 4; /* Phase out */
760                                         RETURN(RC_OK);
761                                 } else {
762                                         ASN_DEBUG("Premature end of XER SET");
763                                         RETURN(RC_FAIL);
764                                 }
765                         }
766                         /* Fall through */
767                 case XCT_OPENING:
768                         if(ctx->phase == 0) {
769                                 XER_ADVANCE(ch_size);
770                                 ctx->phase = 1; /* Processing body phase */
771                                 continue;
772                         }
773                         /* Fall through */
774                 case XCT_UNKNOWN_OP:
775                 case XCT_UNKNOWN_BO:
776
777                         ASN_DEBUG("XER/SET: tcv=%d, ph=%d", tcv, ctx->phase);
778                         if(ctx->phase != 1)
779                                 break;  /* Really unexpected */
780
781                         /*
782                          * Search which member corresponds to this tag.
783                          */
784                         for(edx = 0; edx < td->elements_count; edx++) {
785                                 switch(xer_check_tag(buf_ptr, ch_size,
786                                         elements[edx].name)) {
787                                 case XCT_BOTH:
788                                 case XCT_OPENING:
789                                         /*
790                                          * Process this member.
791                                          */
792                                         ctx->step = edx;
793                                         ctx->phase = 2;
794                                         break;
795                                 case XCT_UNKNOWN_OP:
796                                 case XCT_UNKNOWN_BO:
797                                         continue;
798                                 default:
799                                         edx = td->elements_count;
800                                         break;  /* Phase out */
801                                 }
802                                 break;
803                         }
804                         if(edx != td->elements_count)
805                                 continue;
806
807                         /* It is expected extension */
808                         if(specs->extensible) {
809                                 ASN_DEBUG("Got anticipated extension");
810                                 /*
811                                  * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
812                                  * By using a mask. Only record a pure
813                                  * <opening> tags.
814                                  */
815                                 if(tcv & XCT_CLOSING) {
816                                         /* Found </extension> without body */
817                                 } else {
818                                         ctx->left = 1;
819                                         ctx->phase = 3; /* Skip ...'s */
820                                 }
821                                 XER_ADVANCE(ch_size);
822                                 continue;
823                         }
824
825                         /* Fall through */
826                 default:
827                         break;
828                 }
829
830                 ASN_DEBUG("Unexpected XML tag in SET, expected \"%s\"",
831                         xml_tag);
832                 break;
833         }
834
835         ctx->phase = 4; /* "Phase out" on hard failure */
836         RETURN(RC_FAIL);
837 }
838
839 asn_enc_rval_t
840 SET_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
841                enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
842                void *app_key) {
843     const asn_SET_specifics_t *specs = (const asn_SET_specifics_t *)td->specifics;
844         asn_enc_rval_t er;
845         int xcan = (flags & XER_F_CANONICAL);
846         const asn_TYPE_tag2member_t *t2m = specs->tag2el_cxer;
847         size_t t2m_count = specs->tag2el_cxer_count;
848         size_t edx;
849
850         if(!sptr)
851                 ASN__ENCODE_FAILED;
852
853         assert(t2m_count == td->elements_count);
854
855         er.encoded = 0;
856
857         for(edx = 0; edx < t2m_count; edx++) {
858                 asn_enc_rval_t tmper;
859                 asn_TYPE_member_t *elm;
860         const void *memb_ptr;
861         const char *mname;
862                 size_t mlen;
863
864                 elm = &td->elements[t2m[edx].el_no];
865                 mname = elm->name;
866                 mlen = strlen(elm->name);
867
868                 if(elm->flags & ATF_POINTER) {
869             memb_ptr =
870                 *(const void *const *)((const char *)sptr + elm->memb_offset);
871             if(!memb_ptr) {
872                                 if(elm->optional)
873                                         continue;
874                                 /* Mandatory element missing */
875                                 ASN__ENCODE_FAILED;
876                         }
877                 } else {
878             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
879         }
880
881                 if(!xcan)
882                         ASN__TEXT_INDENT(1, ilevel);
883                 ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);
884
885                 /* Print the member itself */
886                 tmper = elm->type->op->xer_encoder(elm->type, memb_ptr,
887                                 ilevel + 1, flags, cb, app_key);
888                 if(tmper.encoded == -1) return tmper;
889                 er.encoded += tmper.encoded;
890
891                 ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);
892         }
893
894         if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
895
896         ASN__ENCODED_OK(er);
897 cb_failed:
898         ASN__ENCODE_FAILED;
899 }
900
901 int
902 SET_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
903           asn_app_consume_bytes_f *cb, void *app_key) {
904     size_t edx;
905         int ret;
906
907         if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
908
909         /* Dump preamble */
910         if(cb(td->name, strlen(td->name), app_key) < 0
911         || cb(" ::= {", 6, app_key) < 0)
912                 return -1;
913
914         for(edx = 0; edx < td->elements_count; edx++) {
915                 asn_TYPE_member_t *elm = &td->elements[edx];
916                 const void *memb_ptr;
917
918                 if(elm->flags & ATF_POINTER) {
919                         memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
920                         if(!memb_ptr) {
921                                 if(elm->optional) continue;
922                                 /* Print <absent> line */
923                                 /* Fall through */
924                         }
925                 } else {
926                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
927                 }
928
929                 _i_INDENT(1);
930
931                 /* Print the member's name and stuff */
932                 if(cb(elm->name, strlen(elm->name), app_key) < 0
933                 || cb(": ", 2, app_key) < 0)
934                         return -1;
935
936                 /* Print the member itself */
937                 ret = elm->type->op->print_struct(elm->type, memb_ptr, ilevel + 1,
938                         cb, app_key);
939                 if(ret) return ret;
940         }
941
942         ilevel--;
943         _i_INDENT(1);
944
945         return (cb("}", 1, app_key) < 0) ? -1 : 0;
946 }
947
948 void
949 SET_free(const asn_TYPE_descriptor_t *td, void *ptr,
950          enum asn_struct_free_method method) {
951     size_t edx;
952
953         if(!td || !ptr)
954                 return;
955
956         ASN_DEBUG("Freeing %s as SET", td->name);
957
958         for(edx = 0; edx < td->elements_count; edx++) {
959                 asn_TYPE_member_t *elm = &td->elements[edx];
960                 void *memb_ptr;
961                 if(elm->flags & ATF_POINTER) {
962                         memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
963                         if(memb_ptr)
964                                 ASN_STRUCT_FREE(*elm->type, memb_ptr);
965                 } else {
966                         memb_ptr = (void *)((char *)ptr + elm->memb_offset);
967                         ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
968                 }
969         }
970
971     switch(method) {
972     case ASFM_FREE_EVERYTHING:
973         FREEMEM(ptr);
974         break;
975     case ASFM_FREE_UNDERLYING:
976         break;
977     case ASFM_FREE_UNDERLYING_AND_RESET:
978         memset(ptr, 0,
979                ((const asn_SET_specifics_t *)(td->specifics))->struct_size);
980         break;
981     }
982 }
983
984 int
985 SET_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
986                asn_app_constraint_failed_f *ctfailcb, void *app_key) {
987     size_t edx;
988
989         if(!sptr) {
990                 ASN__CTFAIL(app_key, td, sptr,
991                         "%s: value not given (%s:%d)",
992                         td->name, __FILE__, __LINE__);
993                 return -1;
994         }
995
996         /*
997          * Iterate over structure members and check their validity.
998          */
999         for(edx = 0; edx < td->elements_count; edx++) {
1000                 asn_TYPE_member_t *elm = &td->elements[edx];
1001                 const void *memb_ptr;
1002
1003                 if(elm->flags & ATF_POINTER) {
1004                         memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
1005                         if(!memb_ptr) {
1006                                 if(elm->optional)
1007                                         continue;
1008                                 ASN__CTFAIL(app_key, td, sptr,
1009                                 "%s: mandatory element %s absent (%s:%d)",
1010                                 td->name, elm->name, __FILE__, __LINE__);
1011                                 return -1;
1012                         }
1013                 } else {
1014                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
1015                 }
1016
1017                 if(elm->encoding_constraints.general_constraints) {
1018                         return elm->encoding_constraints.general_constraints(
1019                                         elm->type, memb_ptr, ctfailcb, app_key);
1020                 } else {
1021                         return elm->type->encoding_constraints.general_constraints(
1022                                         elm->type, memb_ptr, ctfailcb, app_key);
1023                 }
1024         }
1025
1026         return 0;
1027 }
1028
1029 int
1030 SET_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
1031             const void *bptr) {
1032     size_t edx;
1033
1034         for(edx = 0; edx < td->elements_count; edx++) {
1035                 asn_TYPE_member_t *elm = &td->elements[edx];
1036                 const void *amemb;
1037                 const void *bmemb;
1038                 int ret;
1039
1040                 if(elm->flags & ATF_POINTER) {
1041             amemb =
1042                 *(const void *const *)((const char *)aptr + elm->memb_offset);
1043             bmemb =
1044                 *(const void *const *)((const char *)bptr + elm->memb_offset);
1045             if(!amemb) {
1046                 if(!bmemb) continue;
1047                 return -1;
1048             } else if(!bmemb) {
1049                 return 1;
1050             }
1051                 } else {
1052             amemb = (const void *)((const char *)aptr + elm->memb_offset);
1053             bmemb = (const void *)((const char *)bptr + elm->memb_offset);
1054                 }
1055
1056         ret = elm->type->op->compare_struct(elm->type, amemb, bmemb);
1057         if(ret != 0) return ret;
1058     }
1059
1060     return 0;
1061 }
1062
1063
1064 asn_TYPE_operation_t asn_OP_SET = {
1065         SET_free,
1066         SET_print,
1067         SET_compare,
1068         SET_decode_ber,
1069         SET_encode_der,
1070         SET_decode_xer,
1071         SET_encode_xer,
1072         0,      /* SET_decode_oer */
1073         0,      /* SET_encode_oer */
1074         0,      /* SET_decode_uper */
1075         0,      /* SET_encode_uper */
1076         0,      /* SET_decode_aper */
1077         0,      /* SET_encode_aper */
1078         SET_random_fill,
1079         0       /* Use generic outmost tag fetcher */
1080 };
1081
1082
1083 asn_random_fill_result_t
1084 SET_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
1085                    const asn_encoding_constraints_t *constr,
1086                    size_t max_length) {
1087     const asn_SET_specifics_t *specs =
1088         (const asn_SET_specifics_t *)td->specifics;
1089     asn_random_fill_result_t result_ok = {ARFILL_OK, 0};
1090     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
1091     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
1092     void *st = *sptr;
1093     size_t edx;
1094
1095     if(max_length == 0) return result_skipped;
1096
1097     (void)constr;
1098
1099     if(st == NULL) {
1100         st = CALLOC(1, specs->struct_size);
1101         if(st == NULL) {
1102             return result_failed;
1103         }
1104     }
1105
1106     for(edx = 0; edx < td->elements_count; edx++) {
1107         const asn_TYPE_member_t *elm = &td->elements[edx];
1108         void *memb_ptr;   /* Pointer to the member */
1109         void **memb_ptr2; /* Pointer to that pointer */
1110         asn_random_fill_result_t tmpres;
1111
1112         if(elm->optional && asn_random_between(0, 4) == 2) {
1113             /* Sometimes decide not to fill the optional value */
1114             continue;
1115         }
1116
1117         if(elm->flags & ATF_POINTER) {
1118             /* Member is a pointer to another structure */
1119             memb_ptr2 = (void **)((char *)st + elm->memb_offset);
1120         } else {
1121             memb_ptr = (char *)st + elm->memb_offset;
1122             memb_ptr2 = &memb_ptr;
1123         }
1124
1125         tmpres = elm->type->op->random_fill(
1126             elm->type, memb_ptr2, &elm->encoding_constraints,
1127             max_length > result_ok.length ? max_length - result_ok.length : 0);
1128         switch(tmpres.code) {
1129         case ARFILL_OK:
1130             result_ok.length += tmpres.length;
1131             continue;
1132         case ARFILL_SKIPPED:
1133             assert(!(elm->flags & ATF_POINTER) || *memb_ptr2 == NULL);
1134             continue;
1135         case ARFILL_FAILED:
1136             if(st == *sptr) {
1137                 ASN_STRUCT_RESET(*td, st);
1138             } else {
1139                 ASN_STRUCT_FREE(*td, st);
1140             }
1141             return tmpres;
1142         }
1143     }
1144
1145     *sptr = st;
1146
1147     return result_ok;
1148 }
1149