/* * Copyright (c) 2017 Lev Walkin . All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include #include #include asn_dec_rval_t OPEN_TYPE_oer_get(const asn_codec_ctx_t *opt_codec_ctx, const asn_TYPE_descriptor_t *td, void *sptr, asn_TYPE_member_t *elm, const void *ptr, size_t size) { 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; size_t ot_ret; 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; ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL, &inner_value, ptr, size); switch(ot_ret) { default: if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, selected.presence_index) == 0) { rv.code = RC_OK; rv.consumed = ot_ret; return rv; } else { /* Oh, now a full-blown failure failure */ } /* Fall through */ case -1: rv.code = RC_FAIL; rv.consumed = ot_ret; break; case 0: rv.code = RC_WMORE; rv.consumed = 0; break; } if(*memb_ptr2) { const asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics; if(elm->flags & ATF_POINTER) { ASN_STRUCT_FREE(*selected.type_descriptor, inner_value); *memb_ptr2 = NULL; } else { ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor, inner_value); memset(*memb_ptr2, 0, specs->struct_size); } } return rv; }