/* * Copyright (c) 2017 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include #include #include #include asn_TYPE_operation_t asn_OP_OPEN_TYPE = { OPEN_TYPE_free, OPEN_TYPE_print, OPEN_TYPE_compare, OPEN_TYPE_decode_ber, OPEN_TYPE_encode_der, OPEN_TYPE_decode_xer, OPEN_TYPE_encode_xer, #ifdef ASN_DISABLE_OER_SUPPORT 0, 0, /* No OER support, use "-gen-OER" to enable */ #else OPEN_TYPE_decode_oer, OPEN_TYPE_encode_oer, #endif #ifdef ASN_DISABLE_PER_SUPPORT 0, 0, 0, 0, #else OPEN_TYPE_decode_uper, OPEN_TYPE_encode_uper, OPEN_TYPE_decode_aper, OPEN_TYPE_encode_aper, #endif 0, /* Random fill is not supported for open type */ 0 /* Use generic outmost tag fetcher */ }; #undef ADVANCE #define ADVANCE(num_bytes) \ do { \ size_t num = num_bytes; \ ptr = ((const char *)ptr) + num; \ size -= num; \ consumed_myself += num; \ } while(0) asn_dec_rval_t OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td, void *sptr, const asn_TYPE_member_t *elm, const void *ptr, size_t size) { size_t consumed_myself = 0; asn_type_selector_result_t selected; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ void *inner_value; asn_dec_rval_t rv; if(!(elm->flags & ATF_OPEN_TYPE)) { ASN__DECODE_FAILED; } if(!elm->type_selector) { ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s", td->name, elm->name, elm->type->name); ASN__DECODE_FAILED; } selected = elm->type_selector(td, sptr); if(!selected.presence_index) { ASN__DECODE_FAILED; } /* Fetch the pointer to this member */ if(elm->flags & ATF_POINTER) { memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); } else { memb_ptr = (char *)sptr + elm->memb_offset; memb_ptr2 = &memb_ptr; } if(*memb_ptr2 != NULL) { /* Make sure we reset the structure first before encoding */ if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) { ASN__DECODE_FAILED; } } inner_value = (char *)*memb_ptr2 + elm->type->elements[selected.presence_index - 1].memb_offset; ASN_DEBUG("presence %d\n", selected.presence_index); rv = selected.type_descriptor->op->ber_decoder( opt_codec_ctx, selected.type_descriptor, &inner_value, ptr, size, elm->tag_mode); ADVANCE(rv.consumed); rv.consumed = 0; switch(rv.code) { case RC_OK: if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, selected.presence_index) == 0) { rv.code = RC_OK; rv.consumed = consumed_myself; return rv; } else { /* Oh, now a full-blown failure failure */ } /* Fall through */ case RC_FAIL: rv.consumed = consumed_myself; /* Fall through */ case RC_WMORE: break; } if(*memb_ptr2) { if(elm->flags & ATF_POINTER) { ASN_STRUCT_FREE(*selected.type_descriptor, inner_value); *memb_ptr2 = NULL; } else { ASN_STRUCT_RESET(*selected.type_descriptor, inner_value); } } return rv; } asn_dec_rval_t OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td, void *sptr, const asn_TYPE_member_t *elm, const void *ptr, size_t size) { size_t consumed_myself = 0; asn_type_selector_result_t selected; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ void *inner_value; asn_dec_rval_t rv; int xer_context = 0; ssize_t ch_size; pxer_chunk_type_e ch_type; if(!(elm->flags & ATF_OPEN_TYPE)) { ASN__DECODE_FAILED; } if(!elm->type_selector) { ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s", td->name, elm->name, elm->type->name); ASN__DECODE_FAILED; } selected = elm->type_selector(td, sptr); if(!selected.presence_index) { ASN__DECODE_FAILED; } /* Fetch the pointer to this member */ assert(elm->flags == ATF_OPEN_TYPE); if(elm->flags & ATF_POINTER) { memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); } else { memb_ptr = (char *)sptr + elm->memb_offset; memb_ptr2 = &memb_ptr; } if(*memb_ptr2 != NULL) { /* Make sure we reset the structure first before encoding */ if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) { ASN__DECODE_FAILED; } } /* * Confirm wrapper. */ for(;;) { ch_size = xer_next_token(&xer_context, ptr, size, &ch_type); if(ch_size < 0) { ASN__DECODE_FAILED; } else { switch(ch_type) { case PXER_WMORE: ASN__DECODE_STARVED; case PXER_COMMENT: case PXER_TEXT: ADVANCE(ch_size); continue; case PXER_TAG: break; } break; } } /* * Wrapper value confirmed. */ switch(xer_check_tag(ptr, ch_size, elm->name)) { case XCT_OPENING: ADVANCE(ch_size); break; case XCT_BROKEN: default: ASN__DECODE_FAILED; } inner_value = (char *)*memb_ptr2 + elm->type->elements[selected.presence_index - 1].memb_offset; rv = selected.type_descriptor->op->xer_decoder( opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size); ADVANCE(rv.consumed); rv.consumed = 0; switch(rv.code) { case RC_OK: if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, selected.presence_index) == 0) { break; } else { rv.code = RC_FAIL; } /* Fall through */ case RC_FAIL: /* Point to a best position where failure occurred */ rv.consumed = consumed_myself; /* Fall through */ case RC_WMORE: /* Wrt. rv.consumed==0: * In case a genuine RC_WMORE, the whole Open Type decoding * will have to be restarted. */ if(*memb_ptr2) { if(elm->flags & ATF_POINTER) { ASN_STRUCT_FREE(*selected.type_descriptor, inner_value); *memb_ptr2 = NULL; } else { ASN_STRUCT_RESET(*selected.type_descriptor, inner_value); } } return rv; } /* * Finalize wrapper. */ for(;;) { ch_size = xer_next_token(&xer_context, ptr, size, &ch_type); if(ch_size < 0) { ASN__DECODE_FAILED; } else { switch(ch_type) { case PXER_WMORE: ASN__DECODE_STARVED; case PXER_COMMENT: case PXER_TEXT: ADVANCE(ch_size); continue; case PXER_TAG: break; } break; } } /* * Wrapper value confirmed. */ switch(xer_check_tag(ptr, ch_size, elm->name)) { case XCT_CLOSING: ADVANCE(ch_size); break; case XCT_BROKEN: default: ASN__DECODE_FAILED; } rv.consumed += consumed_myself; return rv; } #ifndef ASN_DISABLE_PER_SUPPORT asn_dec_rval_t OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td, void *sptr, const asn_TYPE_member_t *elm, asn_per_data_t *pd) { asn_type_selector_result_t selected; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ void *inner_value; asn_dec_rval_t rv; if(!(elm->flags & ATF_OPEN_TYPE)) { ASN__DECODE_FAILED; } if(!elm->type_selector) { ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s", td->name, elm->name, elm->type->name); ASN__DECODE_FAILED; } selected = elm->type_selector(td, sptr); if(!selected.presence_index) { ASN__DECODE_FAILED; } /* Fetch the pointer to this member */ assert(elm->flags == ATF_OPEN_TYPE); if(elm->flags & ATF_POINTER) { memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); } else { memb_ptr = (char *)sptr + elm->memb_offset; memb_ptr2 = &memb_ptr; } if(*memb_ptr2 != NULL) { /* Make sure we reset the structure first before encoding */ if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) { ASN__DECODE_FAILED; } } inner_value = (char *)*memb_ptr2 + elm->type->elements[selected.presence_index - 1].memb_offset; rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL, &inner_value, pd); switch(rv.code) { case RC_OK: if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, selected.presence_index) == 0) { break; } else { rv.code = RC_FAIL; } /* Fall through */ case RC_WMORE: case RC_FAIL: if(*memb_ptr2) { if(elm->flags & ATF_POINTER) { ASN_STRUCT_FREE(*selected.type_descriptor, inner_value); *memb_ptr2 = NULL; } else { ASN_STRUCT_RESET(*selected.type_descriptor, inner_value); } } } return rv; } asn_enc_rval_t OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, const void *sptr, asn_per_outp_t *po) { const void *memb_ptr; /* Pointer to the member */ asn_TYPE_member_t *elm; /* CHOICE's element */ asn_enc_rval_t er = {0,0,0}; unsigned present; (void)constraints; present = CHOICE_variant_get_presence(td, sptr); if(present == 0 || present > td->elements_count) { ASN__ENCODE_FAILED; } else { present--; } ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present); elm = &td->elements[present]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ memb_ptr = *(const void *const *)((const char *)sptr + elm->memb_offset); if(!memb_ptr) ASN__ENCODE_FAILED; } else { memb_ptr = (const char *)sptr + elm->memb_offset; } if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) { ASN__ENCODE_FAILED; } er.encoded = 0; ASN__ENCODED_OK(er); } asn_dec_rval_t OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td, void *sptr, const asn_TYPE_member_t *elm, asn_per_data_t *pd) { asn_type_selector_result_t selected; void *memb_ptr; /* Pointer to the member */ void **memb_ptr2; /* Pointer to that pointer */ void *inner_value; asn_dec_rval_t rv; if(!(elm->flags & ATF_OPEN_TYPE)) { ASN__DECODE_FAILED; } if(!elm->type_selector) { ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s", td->name, elm->name, elm->type->name); ASN__DECODE_FAILED; } selected = elm->type_selector(td, sptr); if(!selected.presence_index) { ASN__DECODE_FAILED; } /* Fetch the pointer to this member */ assert(elm->flags == ATF_OPEN_TYPE); if(elm->flags & ATF_POINTER) { memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); } else { memb_ptr = (char *)sptr + elm->memb_offset; memb_ptr2 = &memb_ptr; } if(*memb_ptr2 != NULL) { /* Make sure we reset the structure first before encoding */ if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) { ASN__DECODE_FAILED; } } inner_value = (char *)*memb_ptr2 + elm->type->elements[selected.presence_index - 1].memb_offset; rv = aper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL, &inner_value, pd); switch(rv.code) { case RC_OK: if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, selected.presence_index) == 0) { break; } else { rv.code = RC_FAIL; } /* Fall through */ case RC_WMORE: case RC_FAIL: if(*memb_ptr2) { if(elm->flags & ATF_POINTER) { ASN_STRUCT_FREE(*selected.type_descriptor, inner_value); *memb_ptr2 = NULL; } else { ASN_STRUCT_RESET(*selected.type_descriptor, inner_value); } } } return rv; } asn_enc_rval_t OPEN_TYPE_encode_aper(const asn_TYPE_descriptor_t *td, const asn_per_constraints_t *constraints, const void *sptr, asn_per_outp_t *po) { const void *memb_ptr; /* Pointer to the member */ asn_TYPE_member_t *elm; /* CHOICE's element */ asn_enc_rval_t er = {0,0,0}; unsigned present; (void)constraints; present = CHOICE_variant_get_presence(td, sptr); if(present == 0 || present > td->elements_count) { ASN__ENCODE_FAILED; } else { present--; } ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present); elm = &td->elements[present]; if(elm->flags & ATF_POINTER) { /* Member is a pointer to another structure */ memb_ptr = *(const void *const *)((const char *)sptr + elm->memb_offset); if(!memb_ptr) ASN__ENCODE_FAILED; } else { memb_ptr = (const char *)sptr + elm->memb_offset; } if(aper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) { ASN__ENCODE_FAILED; } er.encoded = 0; ASN__ENCODED_OK(er); } #endif /* ASN_DISABLE_PER_SUPPORT */