2  * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
 
   4  * Redistribution and modifications are permitted subject to BSD license.
 
   6 #include <asn_internal.h>
 
   7 #include <constr_CHOICE.h>
 
  10  * Number of bytes left for this structure.
 
  11  * (ctx->left) indicates the number of bytes _transferred_ for the structure.
 
  12  * (size) contains the number of bytes in the buffer passed.
 
  14 #define LEFT    ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
 
  17  * If the subprocessor function returns with an indication that it wants
 
  18  * more data, it may well be a fatal decoding problem, because the
 
  19  * size is constrained by the <TLV>'s L, even if the buffer size allows
 
  21  * For example, consider the buffer containing the following TLVs:
 
  22  * <T:5><L:1><V> <T:6>...
 
  23  * The TLV length clearly indicates that one byte is expected in V, but
 
  24  * if the V processor returns with "want more data" even if the buffer
 
  25  * contains way more data than the V processor have seen.
 
  27 #define SIZE_VIOLATION  (ctx->left >= 0 && (size_t)ctx->left <= size)
 
  30  * This macro "eats" the part of the buffer which is definitely "consumed",
 
  31  * i.e. was correctly converted into local representation or rightfully skipped.
 
  34 #define ADVANCE(num_bytes)      do {            \
 
  35                 size_t num = num_bytes;         \
 
  36                 ptr = ((const char *)ptr) + num;\
 
  40                 consumed_myself += num;         \
 
  44  * Switch to the next phase of parsing.
 
  47 #define NEXT_PHASE(ctx) do {                    \
 
  53  * Return a standardized complex structure.
 
  56 #define RETURN(_code)   do {                    \
 
  58                 rval.consumed = consumed_myself;\
 
  63  * See the definitions.
 
  65 static int _fetch_present_idx(const void *struct_ptr, int off, int size);
 
  66 static void _set_present_idx(void *sptr, int offset, int size, int pres);
 
  69  * Tags are canonically sorted in the tag to member table.
 
  72 _search4tag(const void *ap, const void *bp) {
 
  73         const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
 
  74         const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
 
  76         int a_class = BER_TAG_CLASS(a->el_tag);
 
  77         int b_class = BER_TAG_CLASS(b->el_tag);
 
  79         if(a_class == b_class) {
 
  80                 ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
 
  81                 ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
 
  83                 if(a_value == b_value)
 
  85                 else if(a_value < b_value)
 
  89         } else if(a_class < b_class) {
 
  97  * The decoder of the CHOICE type.
 
 100 CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 
 101         void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
 
 103          * Bring closer parts of structure description.
 
 105         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 106         asn_TYPE_member_t *elements = td->elements;
 
 109          * Parts of the structure being constructed.
 
 111         void *st = *struct_ptr; /* Target structure. */
 
 112         asn_struct_ctx_t *ctx;  /* Decoder context */
 
 114         ber_tlv_tag_t tlv_tag;  /* T from TLV */
 
 115         ssize_t tag_len;        /* Length of TLV's T */
 
 116         asn_dec_rval_t rval;    /* Return code from subparsers */
 
 118         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
 
 120         ASN_DEBUG("Decoding %s as CHOICE", td->name);
 
 123          * Create the target structure if it is not present already.
 
 126                 st = *struct_ptr = CALLOC(1, specs->struct_size);
 
 133          * Restore parsing context.
 
 135         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
 
 138          * Start to parse where left previously
 
 144                  * Check that the set of tags associated with given structure
 
 145                  * perfectly fits our expectations.
 
 148                 if(tag_mode || td->tags_count) {
 
 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);
 
 158                                 /* ?Substracted below! */
 
 159                                 ctx->left += rval.consumed;
 
 161                         ADVANCE(rval.consumed);
 
 168                 ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
 
 169                         (long)ctx->left, (long)size);
 
 174                  * Fetch the T from TLV.
 
 176                 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
 
 177                 ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
 
 179                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
 181                 case -1: RETURN(RC_FAIL);
 
 185                         asn_TYPE_tag2member_t *t2m;
 
 186                         asn_TYPE_tag2member_t key;
 
 188                         key.el_tag = tlv_tag;
 
 189                         t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
 
 190                                         specs->tag2el, specs->tag2el_count,
 
 191                                         sizeof(specs->tag2el[0]), _search4tag);
 
 194                                  * Found the element corresponding to the tag.
 
 197                                 ctx->step = t2m->el_no;
 
 199                         } else if(specs->ext_start == -1) {
 
 200                                 ASN_DEBUG("Unexpected tag %s "
 
 201                                         "in non-extensible CHOICE %s",
 
 202                                         ber_tlv_tag_string(tlv_tag), td->name);
 
 208                                 ASN_DEBUG("Skipping unknown tag %s",
 
 209                                         ber_tlv_tag_string(tlv_tag));
 
 211                                 skip = ber_skip_length(opt_codec_ctx,
 
 212                                         BER_TLV_CONSTRUCTED(ptr),
 
 213                                         (const char *)ptr + tag_len,
 
 217                                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
 219                                 case -1: RETURN(RC_FAIL);
 
 222                                 ADVANCE(skip + tag_len);
 
 230                  * Read in the element.
 
 233                 asn_TYPE_member_t *elm;/* CHOICE's element */
 
 234                 void *memb_ptr;         /* Pointer to the member */
 
 235                 void **memb_ptr2;       /* Pointer to that pointer */
 
 237                 elm = &elements[ctx->step];
 
 240                  * Compute the position of the member inside a structure,
 
 241                  * and also a type of containment (it may be contained
 
 242                  * as pointer or using inline inclusion).
 
 244                 if(elm->flags & ATF_POINTER) {
 
 245                         /* Member is a pointer to another structure */
 
 246                         memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 
 249                          * A pointer to a pointer
 
 250                          * holding the start of the structure
 
 252                         memb_ptr = (char *)st + elm->memb_offset;
 
 253                         memb_ptr2 = &memb_ptr;
 
 255                 /* Set presence to be able to free it properly at any time */
 
 256                 _set_present_idx(st, specs->pres_offset,
 
 257                                 specs->pres_size, ctx->step + 1);
 
 259                  * Invoke the member fetch routine according to member's type
 
 261                 rval = elm->type->ber_decoder(opt_codec_ctx, elm->type,
 
 262                                 memb_ptr2, ptr, LEFT, elm->tag_mode);
 
 266                 case RC_WMORE: /* More data expected */
 
 267                         if(!SIZE_VIOLATION) {
 
 268                                 ADVANCE(rval.consumed);
 
 272                 case RC_FAIL: /* Fatal error */
 
 276                 ADVANCE(rval.consumed);
 
 283                 ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
 
 284                         td->name, (long)ctx->left, (long)size,
 
 285                         tag_mode, td->tags_count);
 
 289                          * The type must be fully decoded
 
 290                          * by the CHOICE member-specific decoder.
 
 296                 && !(tag_mode || td->tags_count)) {
 
 298                          * This is an untagged CHOICE.
 
 299                          * It doesn't contain nothing
 
 300                          * except for the member itself, including all its tags.
 
 301                          * The decoding is completed.
 
 308                  * Read in the "end of data chunks"'s.
 
 310                 while(ctx->left < 0) {
 
 313                         tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
 
 315                         case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
 317                         case -1: RETURN(RC_FAIL);
 
 323                         if(((const uint8_t *)ptr)[0] == 0) {
 
 329                                 } else if(((const uint8_t *)ptr)[1] == 0) {
 
 331                                          * Correctly finished with <0><0>.
 
 338                                 ASN_DEBUG("Unexpected continuation in %s",
 
 348                 /* No meaningful work here */
 
 356 CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
 
 357                 int tag_mode, ber_tlv_tag_t tag,
 
 358                 asn_app_consume_bytes_f *cb, void *app_key) {
 
 359         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 360         asn_TYPE_member_t *elm; /* CHOICE element */
 
 361         asn_enc_rval_t erval;
 
 363         size_t computed_size = 0;
 
 366         if(!sptr) _ASN_ENCODE_FAILED;
 
 368         ASN_DEBUG("%s %s as CHOICE",
 
 369                 cb?"Encoding":"Estimating", td->name);
 
 371         present = _fetch_present_idx(sptr,
 
 372                 specs->pres_offset, specs->pres_size);
 
 375          * If the structure was not initialized, it cannot be encoded:
 
 376          * can't deduce what to encode in the choice type.
 
 378         if(present <= 0 || present > td->elements_count) {
 
 379                 if(present == 0 && td->elements_count == 0) {
 
 380                         /* The CHOICE is empty?! */
 
 382                         _ASN_ENCODED_OK(erval);
 
 388          * Seek over the present member of the structure.
 
 390         elm = &td->elements[present-1];
 
 391         if(elm->flags & ATF_POINTER) {
 
 392                 memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
 396                                 _ASN_ENCODED_OK(erval);
 
 398                         /* Mandatory element absent */
 
 402                 memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
 406          * If the CHOICE itself is tagged EXPLICIT:
 
 407          * T ::= [2] EXPLICIT CHOICE { ... }
 
 408          * Then emit the appropriate tags.
 
 410         if(tag_mode == 1 || td->tags_count) {
 
 412                  * For this, we need to pre-compute the member.
 
 416                 /* Encode member with its tag */
 
 417                 erval = elm->type->der_encoder(elm->type, memb_ptr,
 
 418                         elm->tag_mode, elm->tag, 0, 0);
 
 419                 if(erval.encoded == -1)
 
 422                 /* Encode CHOICE with parent or my own tag */
 
 423                 ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
 
 427                 computed_size += ret;
 
 431          * Encode the single underlying member.
 
 433         erval = elm->type->der_encoder(elm->type, memb_ptr,
 
 434                 elm->tag_mode, elm->tag, cb, app_key);
 
 435         if(erval.encoded == -1)
 
 438         ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)",
 
 439                 (long)erval.encoded, (long)computed_size);
 
 441         erval.encoded += computed_size;
 
 447 CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) {
 
 448         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 451         assert(tag_mode == 0); (void)tag_mode;
 
 452         assert(tag == 0); (void)tag;
 
 455          * Figure out which CHOICE element is encoded.
 
 457         present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
 
 459         if(present > 0 || present <= td->elements_count) {
 
 460                 asn_TYPE_member_t *elm = &td->elements[present-1];
 
 461                 const void *memb_ptr;
 
 463                 if(elm->flags & ATF_POINTER) {
 
 464                         memb_ptr = *(const void * const *)
 
 465                                         ((const char *)ptr + elm->memb_offset);
 
 467                         memb_ptr = (const void *)
 
 468                                         ((const char *)ptr + elm->memb_offset);
 
 471                 return asn_TYPE_outmost_tag(elm->type, memb_ptr,
 
 472                         elm->tag_mode, elm->tag);
 
 474                 return (ber_tlv_tag_t)-1;
 
 479 CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 
 480                 asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 
 481         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 485                 _ASN_CTFAIL(app_key, td,
 
 486                         "%s: value not given (%s:%d)",
 
 487                         td->name, __FILE__, __LINE__);
 
 492          * Figure out which CHOICE element is encoded.
 
 494         present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
 
 495         if(present > 0 && present <= td->elements_count) {
 
 496                 asn_TYPE_member_t *elm = &td->elements[present-1];
 
 497                 const void *memb_ptr;
 
 499                 if(elm->flags & ATF_POINTER) {
 
 500                         memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 
 504                                 _ASN_CTFAIL(app_key, td,
 
 505                                         "%s: mandatory CHOICE element %s absent (%s:%d)",
 
 506                                         td->name, elm->name, __FILE__, __LINE__);
 
 510                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 
 513                 if(elm->memb_constraints) {
 
 514                         return elm->memb_constraints(elm->type, memb_ptr,
 
 517                         int ret = elm->type->check_constraints(elm->type,
 
 518                                         memb_ptr, ctfailcb, app_key);
 
 520                          * Cannot inherit it eralier:
 
 521                          * need to make sure we get the updated version.
 
 523                         elm->memb_constraints = elm->type->check_constraints;
 
 527                 _ASN_CTFAIL(app_key, td,
 
 528                         "%s: no CHOICE element given (%s:%d)",
 
 529                         td->name, __FILE__, __LINE__);
 
 535 #define XER_ADVANCE(num_bytes)  do {                    \
 
 536                 size_t num = num_bytes;                 \
 
 537                 buf_ptr = ((const char *)buf_ptr) + num;\
 
 539                 consumed_myself += num;                 \
 
 543  * Decode the XER (XML) data.
 
 546 CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 
 547         void **struct_ptr, const char *opt_mname,
 
 548                 const void *buf_ptr, size_t size) {
 
 550          * Bring closer parts of structure description.
 
 552         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 553         const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 
 556          * Parts of the structure being constructed.
 
 558         void *st = *struct_ptr; /* Target structure. */
 
 559         asn_struct_ctx_t *ctx;  /* Decoder context */
 
 561         asn_dec_rval_t rval;            /* Return value of a decoder */
 
 562         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
 
 563         int edx;                        /* Element index */
 
 566          * Create the target structure if it is not present already.
 
 569                 st = *struct_ptr = CALLOC(1, specs->struct_size);
 
 570                 if(st == 0) RETURN(RC_FAIL);
 
 574          * Restore parsing context.
 
 576         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
 
 577         if(ctx->phase == 0 && !*xml_tag)
 
 578                 ctx->phase = 1; /* Skip the outer tag checking phase */
 
 581          * Phases of XER/XML processing:
 
 582          * Phase 0: Check that the opening tag matches our expectations.
 
 583          * Phase 1: Processing body and reacting on closing tag.
 
 584          * Phase 2: Processing inner type.
 
 585          * Phase 3: Only waiting for closing tag.
 
 586          * Phase 4: Skipping unknown extensions.
 
 587          * Phase 5: PHASED OUT
 
 589         for(edx = ctx->step; ctx->phase <= 4;) {
 
 590                 pxer_chunk_type_e ch_type;      /* XER chunk type */
 
 591                 ssize_t ch_size;                /* Chunk size */
 
 592                 xer_check_tag_e tcv;            /* Tag check value */
 
 593                 asn_TYPE_member_t *elm;
 
 596                  * Go inside the member.
 
 598                 if(ctx->phase == 2) {
 
 599                         asn_dec_rval_t tmprval;
 
 600                         void *memb_ptr;         /* Pointer to the member */
 
 601                         void **memb_ptr2;       /* Pointer to that pointer */
 
 603                         elm = &td->elements[edx];
 
 605                         if(elm->flags & ATF_POINTER) {
 
 606                                 /* Member is a pointer to another structure */
 
 607                                 memb_ptr2 = (void **)((char *)st
 
 610                                 memb_ptr = (char *)st + elm->memb_offset;
 
 611                                 memb_ptr2 = &memb_ptr;
 
 614                         /* Start/Continue decoding the inner member */
 
 615                         tmprval = elm->type->xer_decoder(opt_codec_ctx,
 
 616                                         elm->type, memb_ptr2, elm->name,
 
 618                         XER_ADVANCE(tmprval.consumed);
 
 619                         ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d",
 
 620                                 elm->type->name, tmprval.code);
 
 621                         if(tmprval.code != RC_OK)
 
 622                                 RETURN(tmprval.code);
 
 623                         assert(_fetch_present_idx(st,
 
 624                                 specs->pres_offset, specs->pres_size) == 0);
 
 625                         /* Record what we've got */
 
 627                                 specs->pres_offset, specs->pres_size, edx + 1);
 
 632                 /* No need to wait for closing tag; special mode. */
 
 633                 if(ctx->phase == 3 && !*xml_tag) {
 
 634                         ctx->phase = 5; /* Phase out */
 
 639                  * Get the next part of the XML stream.
 
 641                 ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type);
 
 643                 case -1: RETURN(RC_FAIL);
 
 644                 case 0:  RETURN(RC_WMORE);
 
 647                         case PXER_COMMENT:      /* Got XML comment */
 
 648                         case PXER_TEXT:         /* Ignore free-standing text */
 
 649                                 XER_ADVANCE(ch_size);   /* Skip silently */
 
 652                                 break;  /* Check the rest down there */
 
 656                 tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
 
 657                 ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d",
 
 658                         ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
 
 659                         ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
 
 660                         ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
 
 661                         ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
 
 664                 /* Skip the extensions section */
 
 665                 if(ctx->phase == 4) {
 
 666                         ASN_DEBUG("skip_unknown(%d, %ld)",
 
 667                                 tcv, (long)ctx->left);
 
 668                         switch(xer_skip_unknown(tcv, &ctx->left)) {
 
 677                                 XER_ADVANCE(ch_size);
 
 687                         break;  /* No CHOICE? */
 
 691                         XER_ADVANCE(ch_size);
 
 692                         ctx->phase = 5; /* Phase out */
 
 695                         if(ctx->phase == 0) {
 
 696                                 XER_ADVANCE(ch_size);
 
 697                                 ctx->phase = 1; /* Processing body phase */
 
 705                                 break;  /* Really unexpected */
 
 708                          * Search which inner member corresponds to this tag.
 
 710                         for(edx = 0; edx < td->elements_count; edx++) {
 
 711                                 elm = &td->elements[edx];
 
 712                                 tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
 
 717                                          * Process this member.
 
 726                                         edx = td->elements_count;
 
 727                                         break;  /* Phase out */
 
 731                         if(edx != td->elements_count)
 
 734                         /* It is expected extension */
 
 735                         if(specs->ext_start != -1) {
 
 736                                 ASN_DEBUG("Got anticipated extension");
 
 738                                  * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
 
 739                                  * By using a mask. Only record a pure
 
 742                                 if(tcv & XCT_CLOSING) {
 
 743                                         /* Found </extension> without body */
 
 744                                         ctx->phase = 3; /* Terminating */
 
 747                                         ctx->phase = 4; /* Skip ...'s */
 
 749                                 XER_ADVANCE(ch_size);
 
 758                 ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]"
 
 760                         ch_size>0?((const uint8_t *)buf_ptr)[0]:'?',
 
 761                         ch_size>1?((const uint8_t *)buf_ptr)[1]:'?',
 
 762                         ch_size>2?((const uint8_t *)buf_ptr)[2]:'?',
 
 763                         ch_size>3?((const uint8_t *)buf_ptr)[3]:'?',
 
 764                         td->name, ctx->phase, xml_tag);
 
 768         ctx->phase = 5; /* Phase out, just in case */
 
 774 CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
 
 775         int ilevel, enum xer_encoder_flags_e flags,
 
 776                 asn_app_consume_bytes_f *cb, void *app_key) {
 
 777         asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics;
 
 785          * Figure out which CHOICE element is encoded.
 
 787         present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
 
 789         if(present <= 0 || present > td->elements_count) {
 
 792                 asn_enc_rval_t tmper;
 
 793                 asn_TYPE_member_t *elm = &td->elements[present-1];
 
 795                 const char *mname = elm->name;
 
 796                 unsigned int mlen = strlen(mname);
 
 798                 if(elm->flags & ATF_POINTER) {
 
 799                         memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
 800                         if(!memb_ptr) _ASN_ENCODE_FAILED;
 
 802                         memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
 807                 if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel);
 
 808                 _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
 
 810                 tmper = elm->type->xer_encoder(elm->type, memb_ptr,
 
 811                                 ilevel + 1, flags, cb, app_key);
 
 812                 if(tmper.encoded == -1) return tmper;
 
 814                 _ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
 
 816                 er.encoded += 5 + (2 * mlen) + tmper.encoded;
 
 819         if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel - 1);
 
 827 CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 
 828         asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
 
 829         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 831         asn_per_constraint_t *ct;
 
 832         asn_TYPE_member_t *elm; /* CHOICE's element */
 
 838         if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
 
 842          * Create the target structure if it is not present already.
 
 845                 st = *sptr = CALLOC(1, specs->struct_size);
 
 846                 if(!st) _ASN_DECODE_FAILED;
 
 849         if(constraints) ct = &constraints->value;
 
 850         else if(td->per_constraints) ct = &td->per_constraints->value;
 
 853         if(ct && ct->flags & APC_EXTENSIBLE) {
 
 854                 value = per_get_few_bits(pd, 1);
 
 855                 if(value < 0) _ASN_DECODE_STARVED;
 
 856                 if(value) ct = 0;       /* Not restricted */
 
 859         if(ct && ct->range_bits >= 0) {
 
 860                 value = per_get_few_bits(pd, ct->range_bits);
 
 861                 if(value < 0) _ASN_DECODE_STARVED;
 
 862                 ASN_DEBUG("CHOICE %s got index %d in range %d",
 
 863                         td->name, value, ct->range_bits);
 
 864                 if(value > ct->upper_bound)
 
 867                 if(specs->ext_start == -1)
 
 869                 value = uper_get_nsnnwn(pd);
 
 870                 if(value < 0) _ASN_DECODE_STARVED;
 
 871                 value += specs->ext_start;
 
 872                 if(value >= td->elements_count)
 
 874                 ASN_DEBUG("NOT IMPLEMENTED YET");
 
 878         /* Adjust if canonical order is different from natural order */
 
 879         if(specs->canonical_order)
 
 880                 value = specs->canonical_order[value];
 
 882         /* Set presence to be able to free it later */
 
 883         _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1);
 
 885         elm = &td->elements[value];
 
 886         if(elm->flags & ATF_POINTER) {
 
 887                 /* Member is a pointer to another structure */
 
 888                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 
 890                 memb_ptr = (char *)st + elm->memb_offset;
 
 891                 memb_ptr2 = &memb_ptr;
 
 893         ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name);
 
 895         rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
 
 896                         elm->per_constraints, memb_ptr2, pd);
 
 898                 ASN_DEBUG("Failed to decode %s in %s (CHOICE)",
 
 899                         elm->name, td->name);
 
 904 CHOICE_encode_uper(asn_TYPE_descriptor_t *td,
 
 905         asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
 
 906         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 907         asn_TYPE_member_t *elm; /* CHOICE's element */
 
 908         asn_per_constraint_t *ct;
 
 912         if(!sptr) _ASN_ENCODE_FAILED;
 
 914         ASN_DEBUG("Encoding %s as CHOICE", td->name);
 
 916         if(constraints) ct = &constraints->value;
 
 917         else if(td->per_constraints) ct = &td->per_constraints->value;
 
 920         present = _fetch_present_idx(sptr,
 
 921                 specs->pres_offset, specs->pres_size);
 
 924          * If the structure was not initialized properly, it cannot be encoded:
 
 925          * can't deduce what to encode in the choice type.
 
 927         if(present <= 0 || present > td->elements_count)
 
 932         /* Adjust if canonical order is different from natural order */
 
 933         if(specs->canonical_order)
 
 934                 present = specs->canonical_order[present];
 
 936         ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present);
 
 938         if(ct && ct->range_bits >= 0) {
 
 939                 if(present < ct->lower_bound
 
 940                 || present > ct->upper_bound) {
 
 941                         if(ct->flags & APC_EXTENSIBLE) {
 
 942                                 if(per_put_few_bits(po, 1, 1))
 
 950         if(ct && ct->flags & APC_EXTENSIBLE)
 
 951                 if(per_put_few_bits(po, 0, 1))
 
 954         if(ct && ct->range_bits >= 0) {
 
 955                 if(per_put_few_bits(po, present, ct->range_bits))
 
 958                 if(specs->ext_start == -1)
 
 960                 if(uper_put_nsnnwn(po, present - specs->ext_start))
 
 962                 ASN_DEBUG("NOT IMPLEMENTED YET");
 
 966         elm = &td->elements[present];
 
 967         if(elm->flags & ATF_POINTER) {
 
 968                 /* Member is a pointer to another structure */
 
 969                 memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
 970                 if(!memb_ptr) _ASN_ENCODE_FAILED;
 
 972                 memb_ptr = (char *)sptr + elm->memb_offset;
 
 975         return elm->type->uper_encoder(elm->type, elm->per_constraints,
 
 981 CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 
 982                 asn_app_consume_bytes_f *cb, void *app_key) {
 
 983         asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 
 986         if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 989          * Figure out which CHOICE element is encoded.
 
 991         present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
 
 994          * Print that element.
 
 996         if(present > 0 && present <= td->elements_count) {
 
 997                 asn_TYPE_member_t *elm = &td->elements[present-1];
 
 998                 const void *memb_ptr;
 
1000                 if(elm->flags & ATF_POINTER) {
 
1001                         memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 
1002                         if(!memb_ptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
1004                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 
1007                 /* Print member's name and stuff */
 
1009                         if(cb(elm->name, strlen(elm->name), app_key) < 0
 
1010                         || cb(": ", 2, app_key) < 0)
 
1014                 return elm->type->print_struct(elm->type, memb_ptr, ilevel,
 
1017                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
1022 CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 
1023         asn_CHOICE_specifics_t *specs = td ? (asn_CHOICE_specifics_t *)td->specifics : NULL;
 
1029         ASN_DEBUG("Freeing %s as CHOICE", td->name);
 
1032          * Figure out which CHOICE element is encoded.
 
1034         present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
 
1037          * Free that element.
 
1039         if(present > 0 && present <= td->elements_count) {
 
1040                 asn_TYPE_member_t *elm = &td->elements[present-1];
 
1043                 if(elm->flags & ATF_POINTER) {
 
1044                         memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 
1046                                 ASN_STRUCT_FREE(*elm->type, memb_ptr);
 
1048                         memb_ptr = (void *)((char *)ptr + elm->memb_offset);
 
1049                         ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
 
1053         if(!contents_only) {
 
1060  * The following functions functions offer protection against -fshort-enums,
 
1061  * compatible with little- and big-endian machines.
 
1062  * If assertion is triggered, either disable -fshort-enums, or add an entry
 
1063  * here with the ->pres_size of your target stracture.
 
1064  * Unless the target structure is packed, the ".present" member
 
1065  * is guaranteed to be aligned properly. ASN.1 compiler itself does not
 
1066  * produce packed code.
 
1069 _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) {
 
1070         const void *present_ptr;
 
1073         present_ptr = ((const char *)struct_ptr) + pres_offset;
 
1076         case sizeof(int):       present =   *(const int *)present_ptr; break;
 
1077         case sizeof(short):     present = *(const short *)present_ptr; break;
 
1078         case sizeof(char):      present =  *(const char *)present_ptr; break;
 
1080                 /* ANSI C mandates enum to be equivalent to integer */
 
1081                 assert(pres_size != sizeof(int));
 
1082                 return 0;       /* If not aborted, pass back safe value */
 
1089 _set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) {
 
1091         present_ptr = ((char *)struct_ptr) + pres_offset;
 
1094         case sizeof(int):       *(int *)present_ptr   = present; break;
 
1095         case sizeof(short):     *(short *)present_ptr = present; break;
 
1096         case sizeof(char):      *(char *)present_ptr  = present; break;
 
1098                 /* ANSI C mandates enum to be equivalent to integer */
 
1099                 assert(pres_size != sizeof(int));