blob: dd2f5c6445cff948369b8f0f0d775f4c16e83a31 [file] [log] [blame]
Lev Walkin6cd0d562017-08-25 11:57:01 -07001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <asn_internal.h>
6#include <OPEN_TYPE.h>
7#include <constr_CHOICE.h>
Lev Walkin6cd0d562017-08-25 11:57:01 -07008#include <errno.h>
9
10asn_dec_rval_t
Lev Walkin20696a42017-10-17 21:27:33 -070011OPEN_TYPE_oer_get(const asn_codec_ctx_t *opt_codec_ctx,
12 const asn_TYPE_descriptor_t *td, void *sptr,
13 asn_TYPE_member_t *elm, const void *ptr, size_t size) {
Lev Walkin6cd0d562017-08-25 11:57:01 -070014 asn_type_selector_result_t selected;
15 void *memb_ptr; /* Pointer to the member */
16 void **memb_ptr2; /* Pointer to that pointer */
17 void *inner_value;
18 asn_dec_rval_t rv;
19 size_t ot_ret;
20
Lev Walkin75b6fe42017-08-27 01:03:22 -070021
22 if(!(elm->flags & ATF_OPEN_TYPE)) {
23 ASN__DECODE_FAILED;
24 }
25
26 if(!elm->type_selector) {
27 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
28 td->name, elm->name, elm->type->name);
Lev Walkin6cd0d562017-08-25 11:57:01 -070029 ASN__DECODE_FAILED;
30 }
31
32 selected = elm->type_selector(td, sptr);
33 if(!selected.presence_index) {
34 ASN__DECODE_FAILED;
35 }
36
37 /* Fetch the pointer to this member */
38 if(elm->flags & ATF_POINTER) {
39 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
40 } else {
41 memb_ptr = (char *)sptr + elm->memb_offset;
42 memb_ptr2 = &memb_ptr;
43 }
44 if(*memb_ptr2 != NULL) {
45 /* Make sure we reset the structure first before encoding */
Lev Walkin2e5caa52017-08-27 00:38:13 -070046 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
Lev Walkin6cd0d562017-08-25 11:57:01 -070047 ASN__DECODE_FAILED;
48 }
49 }
50
51 inner_value =
52 (char *)*memb_ptr2
53 + elm->type->elements[selected.presence_index - 1].memb_offset;
54
55 ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
56 &inner_value, ptr, size);
57 switch(ot_ret) {
58 default:
Lev Walkin2e5caa52017-08-27 00:38:13 -070059 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
Lev Walkin6cd0d562017-08-25 11:57:01 -070060 selected.presence_index)
61 == 0) {
62 rv.code = RC_OK;
63 rv.consumed = ot_ret;
64 return rv;
65 } else {
66 /* Oh, now a full-blown failure failure */
67 }
68 /* Fall through */
69 case -1:
70 rv.code = RC_FAIL;
Lev Walkin2e5caa52017-08-27 00:38:13 -070071 rv.consumed = ot_ret;
Lev Walkin6cd0d562017-08-25 11:57:01 -070072 break;
73 case 0:
74 rv.code = RC_WMORE;
75 rv.consumed = 0;
76 break;
77 }
78
79 if(*memb_ptr2) {
Lev Walkind84f6032017-10-03 16:33:59 -070080 const asn_CHOICE_specifics_t *specs =
81 selected.type_descriptor->specifics;
Lev Walkin6cd0d562017-08-25 11:57:01 -070082 if(elm->flags & ATF_POINTER) {
83 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
84 *memb_ptr2 = NULL;
85 } else {
86 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
87 inner_value);
88 memset(*memb_ptr2, 0, specs->struct_size);
89 }
90 }
91 return rv;
92}