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