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