diff --git a/examples/sample.source.J2735/Makefile b/examples/sample.source.J2735/Makefile index f952b40f..2c0d4e0a 100644 --- a/examples/sample.source.J2735/Makefile +++ b/examples/sample.source.J2735/Makefile @@ -974,6 +974,9 @@ ASN_MODULE_HEADERS= \ ASN_MODULE_HEADERS+=ANY.h ASN_MODULE_SOURCES+=ANY.c +ASN_MODULE_HEADERS+=OPEN_TYPE.h +ASN_MODULE_SOURCES+=OPEN_TYPE.c +ASN_MODULE_HEADERS+=constr_CHOICE.h ASN_MODULE_HEADERS+=BOOLEAN.h ASN_MODULE_SOURCES+=BOOLEAN.c ASN_MODULE_HEADERS+=INTEGER.h @@ -988,7 +991,6 @@ ASN_MODULE_HEADERS+=asn_SEQUENCE_OF.h ASN_MODULE_SOURCES+=asn_SEQUENCE_OF.c ASN_MODULE_HEADERS+=asn_SET_OF.h ASN_MODULE_SOURCES+=asn_SET_OF.c -ASN_MODULE_HEADERS+=constr_CHOICE.h ASN_MODULE_SOURCES+=constr_CHOICE.c ASN_MODULE_HEADERS+=constr_SEQUENCE.h ASN_MODULE_SOURCES+=constr_SEQUENCE.c diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c index 25ba4e5a..8ec21404 100644 --- a/libasn1compiler/asn1c_C.c +++ b/libasn1compiler/asn1c_C.c @@ -38,6 +38,7 @@ static int asn1c_lang_C_type_SEQUENCE_def( static int asn1c_lang_C_type_SET_def(arg_t *arg); static int asn1c_lang_C_type_CHOICE_def(arg_t *arg); static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of); +static int asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name); static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p); static int compute_extensions_start(asn1p_expr_t *expr); static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr); @@ -301,6 +302,30 @@ asn1c_lang_C_type_BIT_STRING(arg_t *arg) { return asn1c_lang_C_type_SIMPLE_TYPE(arg); } +/* + * Check if it is a true open type. That is, type is taken from + * the Information Object Set driven constraints. + */ +static int +is_open_type(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) { + + (void)arg; + + if(!opt_ioc) { + return 0; + } + + if(expr->meta_type == AMT_TYPEREF + && expr->expr_type == A1TC_REFERENCE + && expr->reference->comp_count == 2 + && expr->reference->components[1].lex_type + == RLT_AmpUppercase) { + return 1; + } + + return 0; +} + int asn1c_lang_C_type_SEQUENCE(arg_t *arg) { asn1p_expr_t *expr = arg->expr; @@ -343,7 +368,21 @@ asn1c_lang_C_type_SEQUENCE(arg_t *arg) { if(comp_mode == 1) v->marker.flags |= EM_OMITABLE | EM_INDIRECT; try_inline_default(arg, v, 1); - EMBED_WITH_IOCT(v, ioc_tao); + if(is_open_type(arg, v, ioc_tao.ioct ? &ioc_tao : 0)) { + arg_t tmp_arg = *arg; + tmp_arg.embed++; + INDENT(+1); + tmp_arg.expr = v; + const char *column_name = v->reference->components[1].name; + if(asn1c_lang_C_OpenType(&tmp_arg, &ioc_tao, column_name)) { + return -1; + } + INDENT(-1); + tmp_arg.embed--; + if(v->expr_type != A1TC_EXTENSIBLE) OUT(";\n"); + } else { + EMBED_WITH_IOCT(v, ioc_tao); + } } PCTX_DEF; @@ -1032,6 +1071,62 @@ asn1c_lang_C_type_CHOICE(arg_t *arg) { return asn1c_lang_C_type_CHOICE_def(arg); } +static ssize_t +find_column_index(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name) { + (void)arg; + + if(!opt_ioc || !opt_ioc->ioct || !column_name) { + return -1; + } + + if(opt_ioc->ioct->rows == 0) { + return 0; /* No big deal. Just no data */ + } else { + for(size_t clmn = 0; clmn < opt_ioc->ioct->row[0]->columns; clmn++) { + if(strcmp(opt_ioc->ioct->row[0]->column[clmn].field->Identifier, + column_name) == 0) { + return clmn; + } + } + return -1; + } + +} + +static int +asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, + const char *column_name) { + arg_t tmp_arg = *arg; + + ssize_t column_index = find_column_index(arg, opt_ioc, column_name); + if(column_index < 0) { + FATAL("Open type generation attempted for %s, incomplete", column_name); + return -1; + } + + asn1p_expr_t *open_type_choice = + asn1p_expr_new(arg->expr->_lineno, arg->expr->module); + + open_type_choice->Identifier = strdup(arg->expr->Identifier); + open_type_choice->meta_type = AMT_TYPE; + open_type_choice->expr_type = ASN_CONSTR_OPEN_TYPE; + open_type_choice->_type_unique_index = arg->expr->_type_unique_index; + + for(size_t row = 0; row < opt_ioc->ioct->rows; row++) { + struct asn1p_ioc_cell_s *cell = + &opt_ioc->ioct->row[row]->column[column_index]; + + asn1p_expr_t *m = asn1p_expr_clone(cell->value, 0); + asn1p_expr_add(open_type_choice, m); + } + + tmp_arg.expr = open_type_choice; + GEN_INCLUDE_STD("OPEN_TYPE"); + asn1c_lang_C_type_CHOICE(&tmp_arg); + asn1p_expr_free(tmp_arg.expr); + return 0; +} + static int asn1c_lang_C_type_CHOICE_def(arg_t *arg) { asn1p_expr_t *expr = arg->expr; @@ -1085,7 +1180,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) { int i; cmap = compute_canonical_members_order(arg, elements); if(cmap) { - OUT("static const int asn_MAP_%s_cmap_%d[] = {", + OUT("static const unsigned asn_MAP_%s_cmap_%d[] = {", MKID(expr), expr->_type_unique_index); for(i = 0; i < elements; i++) { @@ -2652,10 +2747,11 @@ emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_ob assert(opt_ioc != NULL); - asn1p_expr_t *constraining_memb = NULL; - TQ_FOR(constraining_memb, &(parent_expr->members), next) { - if(strcmp(constraining_memb->Identifier, cname) == 0) + asn1p_expr_t *constraining_memb = NULL; + TQ_FOR(constraining_memb, &(parent_expr->members), next) { + if(strcmp(constraining_memb->Identifier, cname) == 0) { break; + } } if(!constraining_memb) { FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr), @@ -2728,10 +2824,11 @@ emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_ob REDIR(OT_CODE); - OUT("static asn_TYPE_descriptor_t *\n"); + OUT("static asn_type_selector_result_t\n"); OUT("select_%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID_safe(expr)); INDENT(+1); + OUT("asn_type_selector_result_t result = {0, 0};\n"); OUT("const asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset), opt_ioc->objset->_type_unique_index); OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield); @@ -2744,7 +2841,7 @@ emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_ob OUT("((const char *)parent_sptr + offsetof(struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(", %s));", MKID_safe(constraining_memb)); - OUT("if(!memb_ptr) return NULL;\n"); + OUT("if(!memb_ptr) return result;\n"); OUT("\n"); } @@ -2774,13 +2871,15 @@ emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_ob OUT(" const asn_ioc_cell_t *type_cell = &itable->rows[row * itable->columns_count + for_column];\n"); OUT("\n"); OUT(" if(constraining_cell->type_descriptor->compare_struct(constraining_cell->type_descriptor, constraining_value, constraining_cell->value_sptr) == 0) {\n"); - OUT(" return type_cell->type_descriptor;\n"); + OUT(" result.type_descriptor = type_cell->type_descriptor;\n"); + OUT(" result.presence_index = row + 1;\n"); + OUT(" break;\n"); OUT(" }\n"); OUT("}\n"); OUT("\n"); - OUT("return NULL;\n"); + OUT("return result;\n"); INDENT(-1); OUT("}\n"); OUT("\n"); @@ -2810,9 +2909,11 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t * OUT("{ "); - if(outmost_tag && outmost_tag->tag_value == -1) - OUT("ATF_OPEN_TYPE | "); - OUT("%s, ", + if((outmost_tag && outmost_tag->tag_value == -1) + || is_open_type(arg, expr, opt_ioc)) { + OUT("ATF_OPEN_TYPE | "); + } + OUT("%s, ", (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS"); if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) { asn1p_expr_t *tv; @@ -2827,19 +2928,22 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t * } else { OUT("0, "); } - if(expr->_anonymous_type) { - assert(arg->expr->expr_type == ASN_CONSTR_SET_OF - || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF); - OUT("0,\n"); - } else { - OUT("offsetof(struct "); - out_name_chain(arg, ONC_avoid_keywords); - OUT(", "); - if(arg->expr->expr_type == ASN_CONSTR_CHOICE - && (!UNNAMED_UNIONS)) OUT("choice."); - OUT("%s),\n", MKID_safe(expr)); - } - INDENT(+1); + if(expr->_anonymous_type) { + assert(arg->expr->expr_type == ASN_CONSTR_SET_OF + || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF); + OUT("0,\n"); + } else { + OUT("offsetof(struct "); + out_name_chain(arg, ONC_avoid_keywords); + OUT(", "); + if((arg->expr->expr_type == ASN_CONSTR_CHOICE + || arg->expr->expr_type == ASN_CONSTR_OPEN_TYPE) + && (!UNNAMED_UNIONS)) + OUT("choice."); + OUT("%s),\n", MKID_safe(expr)); + } + + INDENT(+1); if(C99_MODE) OUT(".tag = "); if(outmost_tag) { if(outmost_tag->tag_value == -1) @@ -2864,7 +2968,8 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t * } complex_contents = - (expr->expr_type & ASN_CONSTR_MASK) + is_open_type(arg, expr, opt_ioc) + || (expr->expr_type & ASN_CONSTR_MASK) || expr->expr_type == ASN_BASIC_ENUMERATED || (0 /* -- prohibited by X.693:8.3.4 */ && expr->expr_type == ASN_BASIC_INTEGER @@ -2872,15 +2977,16 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t * || (expr->expr_type == ASN_BASIC_INTEGER && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN); if(C99_MODE) OUT(".type = "); - OUT("&asn_DEF_"); - if(complex_contents) { - OUT("%s", MKID(expr)); - if(!(arg->flags & A1C_ALL_DEFS_GLOBAL)) - OUT("_%d", expr->_type_unique_index); - } else { - OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE)); - } - OUT(",\n"); + + OUT("&asn_DEF_"); + if(complex_contents) { + OUT("%s", MKID(expr)); + if(!(arg->flags & A1C_ALL_DEFS_GLOBAL)) + OUT("_%d", expr->_type_unique_index); + } else { + OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE)); + } + OUT(",\n"); if(C99_MODE) OUT(".type_selector = "); @@ -3001,8 +3107,9 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ if(HIDE_INNER_DEFS) OUT("static /* Use -fall-defs-global to expose */\n"); OUT("asn_TYPE_descriptor_t asn_DEF_%s", p); - if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index); - OUT(" = {\n"); + if(HIDE_INNER_DEFS || (arg->flags & A1C_ALL_DEFS_GLOBAL)) + OUT("_%d", expr->_type_unique_index); + OUT(" = {\n"); INDENT(+1); if(expr->_anonymous_type) { diff --git a/libasn1parser/asn1p_expr.h b/libasn1parser/asn1p_expr.h index 213f6a72..3be96722 100644 --- a/libasn1parser/asn1p_expr.h +++ b/libasn1parser/asn1p_expr.h @@ -59,6 +59,7 @@ typedef enum asn1p_expr_type { ASN_CONSTR_SET, /* SET */ ASN_CONSTR_SEQUENCE_OF, /* SEQUENCE OF */ ASN_CONSTR_SET_OF, /* SET OF */ + ASN_CONSTR_OPEN_TYPE, /* * ASN.1 Basic types diff --git a/libasn1parser/asn1p_expr_str.h b/libasn1parser/asn1p_expr_str.h index faa1cf8d..065766e9 100644 --- a/libasn1parser/asn1p_expr_str.h +++ b/libasn1parser/asn1p_expr_str.h @@ -17,6 +17,7 @@ static char *asn1p_expr_type2str[] __attribute__ ((unused)) = { [ ASN_CONSTR_SET ] = "SET", [ ASN_CONSTR_SEQUENCE_OF ] = "SEQUENCE OF", [ ASN_CONSTR_SET_OF ] = "SET OF", + [ ASN_CONSTR_OPEN_TYPE ] = "OPEN TYPE", [ ASN_TYPE_ANY ] = "ANY", [ ASN_BASIC_BOOLEAN ] = "BOOLEAN", [ ASN_BASIC_NULL ] = "NULL", diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c index 57e7c06c..ffad24eb 100644 --- a/skeletons/BOOLEAN.c +++ b/skeletons/BOOLEAN.c @@ -242,7 +242,7 @@ BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, } void -BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { +BOOLEAN_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { if(td && ptr && !contents_only) { FREEMEM(ptr); } diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c index 38d6f5c6..d5c0279f 100644 --- a/skeletons/NativeInteger.c +++ b/skeletons/NativeInteger.c @@ -336,9 +336,9 @@ NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, } void -NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { - - if(!td || !ptr) +NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr, + int contents_only) { + if(!td || !ptr) return; ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)", @@ -356,7 +356,7 @@ NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const v if(aptr && bptr) { const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics; - if(specs->field_unsigned) { + if(specs && specs->field_unsigned) { const unsigned long *a = aptr; const unsigned long *b = bptr; if(*a < *b) { @@ -364,7 +364,7 @@ NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const v } else if(*a > *b) { return 1; } else { - return 1; + return 0; } } else { const long *a = aptr; @@ -374,7 +374,7 @@ NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const v } else if(*a > *b) { return 1; } else { - return 1; + return 0; } } } else if(!aptr) { diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c index d9eac636..f305d8bd 100644 --- a/skeletons/NativeReal.c +++ b/skeletons/NativeReal.c @@ -377,9 +377,8 @@ NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr, } void -NativeReal_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { - - if(!td || !ptr) +NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + if(!td || !ptr) return; ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)", diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c index 7cc7ebd4..57a0c1eb 100644 --- a/skeletons/OCTET_STRING.c +++ b/skeletons/OCTET_STRING.c @@ -1726,8 +1726,9 @@ OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr, } void -OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { - OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; +OCTET_STRING_free(const asn_TYPE_descriptor_t *td, void *sptr, + int contents_only) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; asn_OCTET_STRING_specifics_t *specs; asn_struct_ctx_t *ctx; struct _stack *stck; diff --git a/skeletons/OPEN_TYPE.c b/skeletons/OPEN_TYPE.c new file mode 100644 index 00000000..7a53ac31 --- /dev/null +++ b/skeletons/OPEN_TYPE.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include +#include +#include + + +asn_dec_rval_t +OPEN_TYPE_uper_get(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void *sptr, + 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 */ + asn_dec_rval_t rv; + + if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) { + 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; + } + } + + void *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) { + 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; +} + +asn_dec_rval_t +OPEN_TYPE_oer_get(asn_codec_ctx_t *opt_codec_ctx, 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 */ + asn_dec_rval_t rv; + size_t ot_ret; + + if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) { + 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(selected.type_descriptor, *memb_ptr2, 0) + != 0) { + ASN__DECODE_FAILED; + } + } + + ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL, + memb_ptr2, ptr, size); + switch(ot_ret) { + default: + if(CHOICE_variant_set_presence(selected.type_descriptor, *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 = 0; + break; + case 0: + rv.code = RC_WMORE; + rv.consumed = 0; + break; + } + + if(*memb_ptr2) { + asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics; + if(elm->flags & ATF_POINTER) { + ASN_STRUCT_FREE(*selected.type_descriptor, *memb_ptr2); + *memb_ptr2 = NULL; + } else { + ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor, + *memb_ptr2); + memset(*memb_ptr2, 0, specs->struct_size); + } + } + return rv; +} diff --git a/skeletons/asn_codecs_prim.c b/skeletons/asn_codecs_prim.c index 426339c9..cf7ea020 100644 --- a/skeletons/asn_codecs_prim.c +++ b/skeletons/asn_codecs_prim.c @@ -115,9 +115,9 @@ der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr, } void -ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr, - int contents_only) { - ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; +ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr, + int contents_only) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; if(!td || !sptr) return; diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c index 435d592f..71936c96 100644 --- a/skeletons/constr_CHOICE.c +++ b/skeletons/constr_CHOICE.c @@ -63,8 +63,10 @@ /* * See the definitions. */ -static signed _fetch_present_idx(const void *struct_ptr, int off, int size); -static void _set_present_idx(void *sptr, int offset, int size, int pres); +static unsigned _fetch_present_idx(const void *struct_ptr, unsigned off, + unsigned size); +static void _set_present_idx(void *sptr, unsigned offset, unsigned size, + unsigned pres); static const void *_get_member_ptr(const asn_TYPE_descriptor_t *, const void *sptr, asn_TYPE_member_t **elm, unsigned *present); @@ -1035,8 +1037,8 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, } void -CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { - asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; +CHOICE_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; unsigned present; if(!td || !ptr) @@ -1081,17 +1083,18 @@ CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { * is guaranteed to be aligned properly. ASN.1 compiler itself does not * produce packed code. */ -static signed -_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { - const void *present_ptr; +static unsigned +_fetch_present_idx(const void *struct_ptr, unsigned pres_offset, + unsigned pres_size) { + const void *present_ptr; unsigned present; present_ptr = ((const char *)struct_ptr) + pres_offset; switch(pres_size) { - case sizeof(int): present = *(const int *)present_ptr; break; - case sizeof(short): present = *(const short *)present_ptr; break; - case sizeof(char): present = *(const char *)present_ptr; break; + case sizeof(int): present = *(const unsigned int *)present_ptr; break; + case sizeof(short): present = *(const unsigned short *)present_ptr; break; + case sizeof(char): present = *(const unsigned char *)present_ptr; break; default: /* ANSI C mandates enum to be equivalent to integer */ assert(pres_size != sizeof(int)); @@ -1102,14 +1105,15 @@ _fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { } static void -_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) { - void *present_ptr; +_set_present_idx(void *struct_ptr, unsigned pres_offset, unsigned pres_size, + unsigned present) { + void *present_ptr; present_ptr = ((char *)struct_ptr) + pres_offset; switch(pres_size) { - case sizeof(int): *(int *)present_ptr = present; break; - case sizeof(short): *(short *)present_ptr = present; break; - case sizeof(char): *(char *)present_ptr = present; break; + case sizeof(int): *(unsigned int *)present_ptr = present; break; + case sizeof(short): *(unsigned short *)present_ptr = present; break; + case sizeof(char): *(unsigned char *)present_ptr = present; break; default: /* ANSI C mandates enum to be equivalent to integer */ assert(pres_size != sizeof(int)); @@ -1181,3 +1185,50 @@ CHOICE_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bp return 1; } } + +/* + * Return the 1-based choice variant presence index. + * Returns 0 in case of error. + */ +unsigned +CHOICE_variant_get_presence(const asn_TYPE_descriptor_t *td, const void *sptr) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + return _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size); +} + +/* + * Sets or resets the 1-based choice variant presence index. + * In case a previous index is not zero, the currently selected structure + * member is freed and zeroed-out first. + * Returns 0 on success and -1 on error. + */ +int +CHOICE_variant_set_presence(const asn_TYPE_descriptor_t *td, void *sptr, + unsigned present) { + extern asn_CHOICE_specifics_t asn_SPC_value_specs_3; + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + unsigned old_present; + + if(!sptr) { + return -1; + } + + if(present > td->elements_count) + return -1; + + old_present = + _fetch_present_idx(sptr, specs->pres_offset, specs->pres_size); + if(present == old_present) + return 0; + + if(old_present == 0) { + assert(old_present <= td->elements_count); + ASN_STRUCT_FREE_CONTENTS_ONLY(*td, sptr); + memset(sptr, 0, specs->struct_size); + } + + _set_present_idx(sptr, specs->pres_offset, specs->pres_size, present); + + return 0; +} + diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h index 3c3b6cae..0aedcf79 100644 --- a/skeletons/constr_CHOICE.h +++ b/skeletons/constr_CHOICE.h @@ -28,7 +28,7 @@ typedef const struct asn_CHOICE_specifics_s { unsigned tag2el_count; /* Canonical ordering of CHOICE elements, for PER */ - const int *canonical_order; + const unsigned *canonical_order; /* * Extensions-related stuff. @@ -51,6 +51,22 @@ per_type_decoder_f CHOICE_decode_uper; per_type_encoder_f CHOICE_encode_uper; asn_outmost_tag_f CHOICE_outmost_tag; +/* + * Return the 1-based choice variant presence index. + * Returns 0 in case of error. + */ +unsigned CHOICE_variant_get_presence(const asn_TYPE_descriptor_t *td, + const void *structure_ptr); + +/* + * Sets or resets the 1-based choice variant presence index. + * In case a previous index is not zero, the currently selected structure + * member is freed and zeroed-out first. + * Returns 0 on success and -1 on error. + */ +int CHOICE_variant_set_presence(const asn_TYPE_descriptor_t *td, + void *structure_ptr, unsigned present); + #ifdef __cplusplus } #endif diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c index 9859e25d..e1c57d3c 100644 --- a/skeletons/constr_SEQUENCE.c +++ b/skeletons/constr_SEQUENCE.c @@ -5,6 +5,7 @@ */ #include #include +#include #include /* @@ -201,7 +202,7 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, /* * MICROPHASE 1: Synchronize decoding. */ - ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d" + ASN_DEBUG("In %s SEQUENCE left %d, edx=%u flags=%d" " opt=%d ec=%d", td->name, (int)ctx->left, edx, elements[edx].flags, elements[edx].optional, @@ -948,8 +949,8 @@ SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, } void -SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { - size_t edx; +SEQUENCE_free(const asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { + size_t edx; if(!td || !sptr) return; @@ -1118,15 +1119,10 @@ SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, } /* Fetch the member from the stream */ - ASN_DEBUG("Decoding member %s in %s", elm->name, td->name); + ASN_DEBUG("Decoding member \"%s\" in %s", elm->name, td->name); if((elm->flags & ATF_OPEN_TYPE) && elm->type_selector) { - asn_TYPE_descriptor_t *et = elm->type_selector(td, st); - if(!et) { - FREEMEM(opres); - ASN__DECODE_FAILED; - } - rv = uper_open_type_get(opt_codec_ctx, et, NULL, memb_ptr2, pd); + rv = OPEN_TYPE_uper_get(opt_codec_ctx, td, st, elm, pd); } else { rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, elm->per_constraints, memb_ptr2, pd); diff --git a/skeletons/constr_SEQUENCE_oer.c b/skeletons/constr_SEQUENCE_oer.c index 84b0db9e..7f162ae7 100644 --- a/skeletons/constr_SEQUENCE_oer.c +++ b/skeletons/constr_SEQUENCE_oer.c @@ -7,6 +7,7 @@ #include #include +#include #include /* @@ -150,8 +151,6 @@ SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, for(edx = (ctx->step >> 1); edx < td->elements_count; edx++, ctx->step = (ctx->step & ~1) + 2) { asn_TYPE_member_t *elm = &td->elements[edx]; - void *memb_tmpptr; /* Temporary reference. */ - void **memb_ptr2; /* Pointer to a pointer to a memmber */ ASN_DEBUG("Decoding %s->%s", td->name, elm->name); @@ -188,37 +187,20 @@ SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, */ ctx->step |= 1; /* Confirm entering next microphase */ microphase2_decode_continues: - if(elm->flags & ATF_POINTER) { - /* Member is a pointer to another structure */ - memb_ptr2 = (void **)((char *)st + elm->memb_offset); - } else { - memb_tmpptr = (char *)st + elm->memb_offset; - memb_ptr2 = &memb_tmpptr; /* Ensure this & remains in scope! */ - } - if((elm->flags & ATF_OPEN_TYPE) && elm->type_selector) { - asn_TYPE_descriptor_t *et = elm->type_selector(td, st); - ssize_t ot_ret; - if(!et) { - ASN__DECODE_FAILED; - } - ot_ret = oer_open_type_get(opt_codec_ctx, et, NULL, memb_ptr2, - ptr, size); - switch(ot_ret) { - case -1: - rval.code = RC_FAIL; - rval.consumed = 0; - break; - case 0: - rval.code = RC_WMORE; - rval.consumed = 1; - break; - default: - rval.code = RC_OK; - rval.consumed = ot_ret; - break; - } + rval = OPEN_TYPE_oer_get(opt_codec_ctx, td, st, elm, ptr, size); } else { + void *memb_tmpptr; /* Temporary reference. */ + void **memb_ptr2; /* Pointer to a pointer to a memmber */ + + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + memb_tmpptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_tmpptr; /* Ensure remains in scope! */ + } + rval = elm->type->oer_decoder(opt_codec_ctx, elm->type, elm->oer_constraints, memb_ptr2, ptr, size); diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c index 226bef32..4f370bf0 100644 --- a/skeletons/constr_SET.c +++ b/skeletons/constr_SET.c @@ -910,8 +910,8 @@ SET_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, } void -SET_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { - size_t edx; +SET_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + size_t edx; if(!td || !ptr) return; diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c index 62973ac1..1a268dfd 100644 --- a/skeletons/constr_SET_OF.c +++ b/skeletons/constr_SET_OF.c @@ -788,7 +788,7 @@ SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, } void -SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { +SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { if(td && ptr) { asn_SET_OF_specifics_t *specs; asn_TYPE_member_t *elm = td->elements; diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h index d11b8591..a7db7b0b 100644 --- a/skeletons/constr_TYPE.h +++ b/skeletons/constr_TYPE.h @@ -53,7 +53,7 @@ typedef struct asn_struct_ctx_s { * dynamically.) */ typedef void (asn_struct_free_f)( - struct asn_TYPE_descriptor_s *type_descriptor, + const struct asn_TYPE_descriptor_s *type_descriptor, void *struct_ptr, int free_contents_only); #define ASN_STRUCT_FREE(asn_DEF, ptr) (asn_DEF).free_struct(&(asn_DEF),ptr,0) #define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \ @@ -95,7 +95,11 @@ asn_outmost_tag_f asn_TYPE_outmost_tag; * Fetch the desired type of the Open Type based on the * Information Object Set driven constraints. */ -typedef struct asn_TYPE_descriptor_s *(asn_type_selector_f)( +typedef struct asn_type_selector_result_s { + struct asn_TYPE_descriptor_s *type_descriptor; /* Type encoded. */ + unsigned presence_index; /* Associated choice variant. */ +} asn_type_selector_result_t; +typedef asn_type_selector_result_t(asn_type_selector_f)( const struct asn_TYPE_descriptor_s *parent_type_descriptor, const void *parent_structure_ptr); @@ -168,7 +172,7 @@ typedef struct asn_TYPE_member_s { ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ asn_TYPE_descriptor_t *type; /* Member type descriptor */ - asn_type_selector_f *type_selector; /* IoS selector */ + asn_type_selector_f *type_selector; /* IoS runtime type selector */ asn_constr_check_f *memb_constraints; /* Constraints validator */ asn_oer_constraints_t *oer_constraints; /* OER compiled constraints */ asn_per_constraints_t *per_constraints; /* PER compiled constraints */ diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies index d3c4d0e4..10022f54 100644 --- a/skeletons/file-dependencies +++ b/skeletons/file-dependencies @@ -5,6 +5,7 @@ # ANY.h ANY.c +OPEN_TYPE.h OPEN_TYPE.c constr_CHOICE.h BMPString.h BMPString.c UTF8String.h BOOLEAN.h BOOLEAN.c ENUMERATED.h ENUMERATED.c INTEGER.h NativeEnumerated.h @@ -34,7 +35,7 @@ VisibleString.h VisibleString.c asn_SEQUENCE_OF.h asn_SEQUENCE_OF.c asn_SET_OF.h asn_SET_OF.h asn_SET_OF.c constr_CHOICE.h constr_CHOICE.c -constr_SEQUENCE.h constr_SEQUENCE.c +constr_SEQUENCE.h constr_SEQUENCE.c OPEN_TYPE.h constr_SEQUENCE_OF.h constr_SEQUENCE_OF.c asn_SEQUENCE_OF.h constr_SET_OF.h constr_SET.h constr_SET.c constr_SET_OF.h constr_SET_OF.c asn_SET_OF.h diff --git a/tests/tests-asn1c-compiler/141-component-relation-OK.asn1 b/tests/tests-asn1c-compiler/141-component-relation-OK.asn1 index 8d5868cc..e1f1d0dc 100755 --- a/tests/tests-asn1c-compiler/141-component-relation-OK.asn1 +++ b/tests/tests-asn1c-compiler/141-component-relation-OK.asn1 @@ -8,7 +8,7 @@ ModuleComponentRelationConstraint { iso org(3) dod(6) internet (1) private(4) enterprise(1) spelio(9363) software(1) asn1c(5) test(1) 141 } - DEFINITIONS ::= + DEFINITIONS AUTOMATIC TAGS ::= BEGIN Frame ::= SEQUENCE {