blob: 4e5426208d49e996385349b86352193537d76403 [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
11OPEN_TYPE_oer_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
12 void *sptr, asn_TYPE_member_t *elm, const void *ptr,
13 size_t size) {
14 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
21 if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) {
22 ASN__DECODE_FAILED;
23 }
24
25 selected = elm->type_selector(td, sptr);
26 if(!selected.presence_index) {
27 ASN__DECODE_FAILED;
28 }
29
30 /* Fetch the pointer to this member */
31 if(elm->flags & ATF_POINTER) {
32 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
33 } else {
34 memb_ptr = (char *)sptr + elm->memb_offset;
35 memb_ptr2 = &memb_ptr;
36 }
37 if(*memb_ptr2 != NULL) {
38 /* Make sure we reset the structure first before encoding */
39 if(CHOICE_variant_set_presence(selected.type_descriptor, *memb_ptr2, 0)
40 != 0) {
41 ASN__DECODE_FAILED;
42 }
43 }
44
45 inner_value =
46 (char *)*memb_ptr2
47 + elm->type->elements[selected.presence_index - 1].memb_offset;
48
49 ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
50 &inner_value, ptr, size);
51 switch(ot_ret) {
52 default:
53 if(CHOICE_variant_set_presence(selected.type_descriptor, *memb_ptr2,
54 selected.presence_index)
55 == 0) {
56 rv.code = RC_OK;
57 rv.consumed = ot_ret;
58 return rv;
59 } else {
60 /* Oh, now a full-blown failure failure */
61 }
62 /* Fall through */
63 case -1:
64 rv.code = RC_FAIL;
65 rv.consumed = 0;
66 break;
67 case 0:
68 rv.code = RC_WMORE;
69 rv.consumed = 0;
70 break;
71 }
72
73 if(*memb_ptr2) {
74 asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
75 if(elm->flags & ATF_POINTER) {
76 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
77 *memb_ptr2 = NULL;
78 } else {
79 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
80 inner_value);
81 memset(*memb_ptr2, 0, specs->struct_size);
82 }
83 }
84 return rv;
85}