blob: 9417d9a58491a2c9f5e91f29e78babf123209b77 [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,
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080015 OPEN_TYPE_decode_ber,
16 OPEN_TYPE_encode_der,
17 OPEN_TYPE_decode_xer,
18 OPEN_TYPE_encode_xer,
19 0, 0, /* No OER support, use "-gen-OER" to enable */
Lev Walkina4db2af2017-08-27 01:27:07 -070020#ifdef ASN_DISABLE_PER_SUPPORT
21 0, 0,
22#else
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080023 OPEN_TYPE_decode_uper,
24 OPEN_TYPE_encode_uper,
Lev Walkina4db2af2017-08-27 01:27:07 -070025#endif
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080026 0, /* Use generic outmost tag fetcher */
27};
Lev Walkinf6853ce2017-08-11 00:50:27 -070028
Lev Walkinc10d30a2017-08-27 00:38:21 -070029#undef ADVANCE
30#define ADVANCE(num_bytes) \
Lev Walkinf59dac92017-08-26 21:26:51 -070031 do { \
32 size_t num = num_bytes; \
33 ptr = ((const char *)ptr) + num; \
34 size -= num; \
35 consumed_myself += num; \
36 } while(0)
37
38asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -070039OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
Lev Walkinc10d30a2017-08-27 00:38:21 -070040 void *sptr, asn_TYPE_member_t *elm, const void *ptr,
41 size_t size) {
42 size_t consumed_myself = 0;
43 asn_type_selector_result_t selected;
44 void *memb_ptr; /* Pointer to the member */
45 void **memb_ptr2; /* Pointer to that pointer */
46 void *inner_value;
47 asn_dec_rval_t rv;
48
Lev Walkin75b6fe42017-08-27 01:03:22 -070049 if(!(elm->flags & ATF_OPEN_TYPE)) {
50 ASN__DECODE_FAILED;
51 }
52
53 if(!elm->type_selector) {
54 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
55 td->name, elm->name, elm->type->name);
Lev Walkinc10d30a2017-08-27 00:38:21 -070056 ASN__DECODE_FAILED;
57 }
58
59 selected = elm->type_selector(td, sptr);
60 if(!selected.presence_index) {
61 ASN__DECODE_FAILED;
62 }
63
64 /* Fetch the pointer to this member */
65 if(elm->flags & ATF_POINTER) {
66 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
67 } else {
68 memb_ptr = (char *)sptr + elm->memb_offset;
69 memb_ptr2 = &memb_ptr;
70 }
71 if(*memb_ptr2 != NULL) {
72 /* Make sure we reset the structure first before encoding */
73 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
74 ASN__DECODE_FAILED;
75 }
76 }
77
78 inner_value =
79 (char *)*memb_ptr2
80 + elm->type->elements[selected.presence_index - 1].memb_offset;
81
82 ASN_DEBUG("presence %d\n", selected.presence_index);
83
84 rv = selected.type_descriptor->op->ber_decoder(
85 opt_codec_ctx, selected.type_descriptor, &inner_value, ptr, size,
86 elm->tag_mode);
87 ADVANCE(rv.consumed);
88 rv.consumed = 0;
89 switch(rv.code) {
90 case RC_OK:
91 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
92 selected.presence_index)
93 == 0) {
94 rv.code = RC_OK;
95 rv.consumed = consumed_myself;
96 return rv;
97 } else {
98 /* Oh, now a full-blown failure failure */
99 }
100 /* Fall through */
101 case RC_FAIL:
102 rv.consumed = consumed_myself;
103 /* Fall through */
104 case RC_WMORE:
105 break;
106 }
107
108 if(*memb_ptr2) {
109 asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
110 if(elm->flags & ATF_POINTER) {
111 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
112 *memb_ptr2 = NULL;
113 } else {
114 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
115 inner_value);
116 memset(*memb_ptr2, 0, specs->struct_size);
117 }
118 }
119 return rv;
120}
121
122asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700123OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
Lev Walkinf59dac92017-08-26 21:26:51 -0700124 void *sptr, asn_TYPE_member_t *elm, const void *ptr,
125 size_t size) {
126 size_t consumed_myself = 0;
127 asn_type_selector_result_t selected;
128 void *memb_ptr; /* Pointer to the member */
129 void **memb_ptr2; /* Pointer to that pointer */
130 void *inner_value;
Lev Walkinf59dac92017-08-26 21:26:51 -0700131 asn_dec_rval_t rv;
132
133 int xer_context = 0;
134 ssize_t ch_size;
135 pxer_chunk_type_e ch_type;
136
Lev Walkin75b6fe42017-08-27 01:03:22 -0700137 if(!(elm->flags & ATF_OPEN_TYPE)) {
138 ASN__DECODE_FAILED;
139 }
140
141 if(!elm->type_selector) {
142 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
143 td->name, elm->name, elm->type->name);
Lev Walkinf59dac92017-08-26 21:26:51 -0700144 ASN__DECODE_FAILED;
145 }
146
147 selected = elm->type_selector(td, sptr);
148 if(!selected.presence_index) {
149 ASN__DECODE_FAILED;
150 }
151
152 /* Fetch the pointer to this member */
153 assert(elm->flags == ATF_OPEN_TYPE);
154 if(elm->flags & ATF_POINTER) {
155 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
156 } else {
157 memb_ptr = (char *)sptr + elm->memb_offset;
158 memb_ptr2 = &memb_ptr;
159 }
160 if(*memb_ptr2 != NULL) {
161 /* Make sure we reset the structure first before encoding */
162 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
163 != 0) {
164 ASN__DECODE_FAILED;
165 }
166 }
167
168 /*
169 * Confirm wrapper.
170 */
171 for(;;) {
172 ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
Lev Walkin4ccce3d2017-08-27 00:41:58 -0700173 if(ch_size < 0) {
Lev Walkinf59dac92017-08-26 21:26:51 -0700174 ASN__DECODE_FAILED;
175 } else {
176 switch(ch_type) {
177 case PXER_WMORE:
178 ASN__DECODE_STARVED;
179 case PXER_COMMENT:
180 case PXER_TEXT:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700181 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700182 continue;
183 case PXER_TAG:
184 break;
185 }
186 break;
187 }
188 }
189
190 /*
191 * Wrapper value confirmed.
192 */
193 switch(xer_check_tag(ptr, ch_size, elm->name)) {
194 case XCT_OPENING:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700195 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700196 break;
197 case XCT_BROKEN:
198 default:
199 ASN__DECODE_FAILED;
200 }
201
202 inner_value =
203 (char *)*memb_ptr2
204 + elm->type->elements[selected.presence_index - 1].memb_offset;
205
206 rv = selected.type_descriptor->op->xer_decoder(
207 opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
Lev Walkinc10d30a2017-08-27 00:38:21 -0700208 ADVANCE(rv.consumed);
Lev Walkinf59dac92017-08-26 21:26:51 -0700209 rv.consumed = 0;
210 switch(rv.code) {
211 case RC_OK:
212 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
213 selected.presence_index)
214 == 0) {
215 break;
216 } else {
217 rv.code = RC_FAIL;
218 }
219 /* Fall through */
220 case RC_FAIL:
221 /* Point to a best position where failure occurred */
222 rv.consumed = consumed_myself;
223 /* Fall through */
224 case RC_WMORE:
225 /* Wrt. rv.consumed==0:
226 * In case a genuine RC_WMORE, the whole Open Type decoding
227 * will have to be restarted.
228 */
229 if(*memb_ptr2) {
230 asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
231 if(elm->flags & ATF_POINTER) {
232 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
233 *memb_ptr2 = NULL;
234 } else {
235 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
236 inner_value);
237 memset(*memb_ptr2, 0, specs->struct_size);
238 }
239 }
240 return rv;
241 }
242
243 /*
244 * Finalize wrapper.
245 */
246 for(;;) {
247 ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
Lev Walkin4ccce3d2017-08-27 00:41:58 -0700248 if(ch_size < 0) {
Lev Walkinf59dac92017-08-26 21:26:51 -0700249 ASN__DECODE_FAILED;
250 } else {
251 switch(ch_type) {
252 case PXER_WMORE:
253 ASN__DECODE_STARVED;
254 case PXER_COMMENT:
255 case PXER_TEXT:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700256 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700257 continue;
258 case PXER_TAG:
259 break;
260 }
261 break;
262 }
263 }
264
265 /*
266 * Wrapper value confirmed.
267 */
268 switch(xer_check_tag(ptr, ch_size, elm->name)) {
269 case XCT_CLOSING:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700270 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700271 break;
272 case XCT_BROKEN:
273 default:
274 ASN__DECODE_FAILED;
275 }
276
277 rv.consumed += consumed_myself;
278
279 return rv;
280}
281
282
Lev Walkin69033802017-08-25 12:15:58 -0700283#ifndef ASN_DISABLE_PER_SUPPORT
284
Lev Walkinf6853ce2017-08-11 00:50:27 -0700285asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700286OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkinf6853ce2017-08-11 00:50:27 -0700287 asn_TYPE_descriptor_t *td, void *sptr,
288 asn_TYPE_member_t *elm, asn_per_data_t *pd) {
289 asn_type_selector_result_t selected;
290 void *memb_ptr; /* Pointer to the member */
291 void **memb_ptr2; /* Pointer to that pointer */
Lev Walkinf59dac92017-08-26 21:26:51 -0700292 void *inner_value;
Lev Walkinf6853ce2017-08-11 00:50:27 -0700293 asn_dec_rval_t rv;
294
Lev Walkin75b6fe42017-08-27 01:03:22 -0700295 if(!(elm->flags & ATF_OPEN_TYPE)) {
296 ASN__DECODE_FAILED;
297 }
298
299 if(!elm->type_selector) {
300 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
301 td->name, elm->name, elm->type->name);
Lev Walkinf6853ce2017-08-11 00:50:27 -0700302 ASN__DECODE_FAILED;
303 }
304
305 selected = elm->type_selector(td, sptr);
306 if(!selected.presence_index) {
307 ASN__DECODE_FAILED;
308 }
309
310 /* Fetch the pointer to this member */
311 assert(elm->flags == ATF_OPEN_TYPE);
312 if(elm->flags & ATF_POINTER) {
313 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
314 } else {
315 memb_ptr = (char *)sptr + elm->memb_offset;
316 memb_ptr2 = &memb_ptr;
317 }
318 if(*memb_ptr2 != NULL) {
319 /* Make sure we reset the structure first before encoding */
320 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
321 != 0) {
322 ASN__DECODE_FAILED;
323 }
324 }
325
Lev Walkinf59dac92017-08-26 21:26:51 -0700326 inner_value =
Lev Walkinf6853ce2017-08-11 00:50:27 -0700327 (char *)*memb_ptr2
328 + elm->type->elements[selected.presence_index - 1].memb_offset;
329
330 rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
331 &inner_value, pd);
332 switch(rv.code) {
333 case RC_OK:
334 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
335 selected.presence_index)
336 == 0) {
337 break;
338 } else {
339 rv.code = RC_FAIL;
340 }
341 /* Fall through */
342 case RC_WMORE:
343 case RC_FAIL:
344 if(*memb_ptr2) {
345 asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
346 if(elm->flags & ATF_POINTER) {
347 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
348 *memb_ptr2 = NULL;
349 } else {
350 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
351 inner_value);
352 memset(*memb_ptr2, 0, specs->struct_size);
353 }
354 }
355 }
356 return rv;
357}
358
Lev Walkin35ace192017-08-26 23:33:14 -0700359asn_enc_rval_t
360OPEN_TYPE_encode_uper(asn_TYPE_descriptor_t *td,
361 const asn_per_constraints_t *constraints, void *sptr,
362 asn_per_outp_t *po) {
Lev Walkin35ace192017-08-26 23:33:14 -0700363 void *memb_ptr; /* Pointer to the member */
364 asn_TYPE_member_t *elm; /* CHOICE's element */
365 asn_enc_rval_t er;
366 unsigned present;
367
368 (void)constraints;
369
370 present = CHOICE_variant_get_presence(td, sptr);
371 if(present == 0 || present > td->elements_count) {
372 ASN__ENCODE_FAILED;
373 } else {
374 present--;
375 }
376
377 ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
378
379 elm = &td->elements[present];
380 if(elm->flags & ATF_POINTER) {
381 /* Member is a pointer to another structure */
382 memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
383 if(!memb_ptr) ASN__ENCODE_FAILED;
384 } else {
385 memb_ptr = (char *)sptr + elm->memb_offset;
386 }
387
388 if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
389 ASN__ENCODE_FAILED;
390 }
391
392 er.encoded = 0;
393 ASN__ENCODED_OK(er);
394}
395
396
Lev Walkin69033802017-08-25 12:15:58 -0700397#endif /* ASN_DISABLE_PER_SUPPORT */