open5gs/lib/asn1c/common/OPEN_TYPE.c

510 lines
14 KiB
C

/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OPEN_TYPE.h>
#include <constr_CHOICE.h>
#include <per_opentype.h>
#include <errno.h>
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;
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;
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 */