blob: 6c73eef5a1410b48f120eb5fad08f3641dd979bc [file] [log] [blame]
Lev Walkinf6853ce2017-08-11 00:50:27 -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 <per_opentype.h>
9#include <errno.h>
10
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080011asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
12 OPEN_TYPE_free,
13 OPEN_TYPE_print,
14 OPEN_TYPE_compare,
15 OPEN_TYPE_constraint,
16 OPEN_TYPE_decode_ber,
17 OPEN_TYPE_encode_der,
18 OPEN_TYPE_decode_xer,
19 OPEN_TYPE_encode_xer,
20 0, 0, /* No OER support, use "-gen-OER" to enable */
21 OPEN_TYPE_decode_uper,
22 OPEN_TYPE_encode_uper,
23 0, /* Use generic outmost tag fetcher */
24};
Lev Walkinf6853ce2017-08-11 00:50:27 -070025
Lev Walkinf59dac92017-08-26 21:26:51 -070026#undef XER_ADVANCE
27#define XER_ADVANCE(num_bytes) \
28 do { \
29 size_t num = num_bytes; \
30 ptr = ((const char *)ptr) + num; \
31 size -= num; \
32 consumed_myself += num; \
33 } while(0)
34
35asn_dec_rval_t
36OPEN_TYPE_xer_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
37 void *sptr, asn_TYPE_member_t *elm, const void *ptr,
38 size_t size) {
39 size_t consumed_myself = 0;
40 asn_type_selector_result_t selected;
41 void *memb_ptr; /* Pointer to the member */
42 void **memb_ptr2; /* Pointer to that pointer */
43 void *inner_value;
44 const char *xml_tag;
45 asn_dec_rval_t rv;
46
47 int xer_context = 0;
48 ssize_t ch_size;
49 pxer_chunk_type_e ch_type;
50
51 if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) {
52 ASN__DECODE_FAILED;
53 }
54
55 selected = elm->type_selector(td, sptr);
56 if(!selected.presence_index) {
57 ASN__DECODE_FAILED;
58 }
59
60 /* Fetch the pointer to this member */
61 assert(elm->flags == ATF_OPEN_TYPE);
62 if(elm->flags & ATF_POINTER) {
63 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
64 } else {
65 memb_ptr = (char *)sptr + elm->memb_offset;
66 memb_ptr2 = &memb_ptr;
67 }
68 if(*memb_ptr2 != NULL) {
69 /* Make sure we reset the structure first before encoding */
70 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
71 != 0) {
72 ASN__DECODE_FAILED;
73 }
74 }
75
76 /*
77 * Confirm wrapper.
78 */
79 for(;;) {
80 ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
81 if(ch_size <= 0) {
82 ASN__DECODE_FAILED;
83 } else {
84 switch(ch_type) {
85 case PXER_WMORE:
86 ASN__DECODE_STARVED;
87 case PXER_COMMENT:
88 case PXER_TEXT:
89 XER_ADVANCE(ch_size);
90 continue;
91 case PXER_TAG:
92 break;
93 }
94 break;
95 }
96 }
97
98 /*
99 * Wrapper value confirmed.
100 */
101 switch(xer_check_tag(ptr, ch_size, elm->name)) {
102 case XCT_OPENING:
103 XER_ADVANCE(ch_size);
104 break;
105 case XCT_BROKEN:
106 default:
107 ASN__DECODE_FAILED;
108 }
109
110 inner_value =
111 (char *)*memb_ptr2
112 + elm->type->elements[selected.presence_index - 1].memb_offset;
113
114 rv = selected.type_descriptor->op->xer_decoder(
115 opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
116 XER_ADVANCE(rv.consumed);
117 rv.consumed = 0;
118 switch(rv.code) {
119 case RC_OK:
120 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
121 selected.presence_index)
122 == 0) {
123 break;
124 } else {
125 rv.code = RC_FAIL;
126 }
127 /* Fall through */
128 case RC_FAIL:
129 /* Point to a best position where failure occurred */
130 rv.consumed = consumed_myself;
131 /* Fall through */
132 case RC_WMORE:
133 /* Wrt. rv.consumed==0:
134 * In case a genuine RC_WMORE, the whole Open Type decoding
135 * will have to be restarted.
136 */
137 if(*memb_ptr2) {
138 asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
139 if(elm->flags & ATF_POINTER) {
140 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
141 *memb_ptr2 = NULL;
142 } else {
143 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
144 inner_value);
145 memset(*memb_ptr2, 0, specs->struct_size);
146 }
147 }
148 return rv;
149 }
150
151 /*
152 * Finalize wrapper.
153 */
154 for(;;) {
155 ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
156 if(ch_size <= 0) {
157 ASN__DECODE_FAILED;
158 } else {
159 switch(ch_type) {
160 case PXER_WMORE:
161 ASN__DECODE_STARVED;
162 case PXER_COMMENT:
163 case PXER_TEXT:
164 XER_ADVANCE(ch_size);
165 continue;
166 case PXER_TAG:
167 break;
168 }
169 break;
170 }
171 }
172
173 /*
174 * Wrapper value confirmed.
175 */
176 switch(xer_check_tag(ptr, ch_size, elm->name)) {
177 case XCT_CLOSING:
178 XER_ADVANCE(ch_size);
179 break;
180 case XCT_BROKEN:
181 default:
182 ASN__DECODE_FAILED;
183 }
184
185 rv.consumed += consumed_myself;
186
187 return rv;
188}
189
190
Lev Walkin69033802017-08-25 12:15:58 -0700191#ifndef ASN_DISABLE_PER_SUPPORT
192
Lev Walkinf6853ce2017-08-11 00:50:27 -0700193asn_dec_rval_t
194OPEN_TYPE_uper_get(asn_codec_ctx_t *opt_codec_ctx,
195 asn_TYPE_descriptor_t *td, void *sptr,
196 asn_TYPE_member_t *elm, asn_per_data_t *pd) {
197 asn_type_selector_result_t selected;
198 void *memb_ptr; /* Pointer to the member */
199 void **memb_ptr2; /* Pointer to that pointer */
Lev Walkinf59dac92017-08-26 21:26:51 -0700200 void *inner_value;
Lev Walkinf6853ce2017-08-11 00:50:27 -0700201 asn_dec_rval_t rv;
202
203 if(!(elm->flags & ATF_OPEN_TYPE) || !elm->type_selector) {
204 ASN__DECODE_FAILED;
205 }
206
207 selected = elm->type_selector(td, sptr);
208 if(!selected.presence_index) {
209 ASN__DECODE_FAILED;
210 }
211
212 /* Fetch the pointer to this member */
213 assert(elm->flags == ATF_OPEN_TYPE);
214 if(elm->flags & ATF_POINTER) {
215 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
216 } else {
217 memb_ptr = (char *)sptr + elm->memb_offset;
218 memb_ptr2 = &memb_ptr;
219 }
220 if(*memb_ptr2 != NULL) {
221 /* Make sure we reset the structure first before encoding */
222 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
223 != 0) {
224 ASN__DECODE_FAILED;
225 }
226 }
227
Lev Walkinf59dac92017-08-26 21:26:51 -0700228 inner_value =
Lev Walkinf6853ce2017-08-11 00:50:27 -0700229 (char *)*memb_ptr2
230 + elm->type->elements[selected.presence_index - 1].memb_offset;
231
232 rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
233 &inner_value, pd);
234 switch(rv.code) {
235 case RC_OK:
236 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
237 selected.presence_index)
238 == 0) {
239 break;
240 } else {
241 rv.code = RC_FAIL;
242 }
243 /* Fall through */
244 case RC_WMORE:
245 case RC_FAIL:
246 if(*memb_ptr2) {
247 asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
248 if(elm->flags & ATF_POINTER) {
249 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
250 *memb_ptr2 = NULL;
251 } else {
252 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
253 inner_value);
254 memset(*memb_ptr2, 0, specs->struct_size);
255 }
256 }
257 }
258 return rv;
259}
260
Lev Walkin69033802017-08-25 12:15:58 -0700261#endif /* ASN_DISABLE_PER_SUPPORT */