blob: c672992caddad46f1bdeaafba68d63dbfc215d5f [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
Lev Walkina5972be2017-09-29 23:15:58 -070026 0, /* Random fill is not supported for open type */
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080027 0, /* Use generic outmost tag fetcher */
28};
Lev Walkinf6853ce2017-08-11 00:50:27 -070029
Lev Walkinc10d30a2017-08-27 00:38:21 -070030#undef ADVANCE
31#define ADVANCE(num_bytes) \
Lev Walkinf59dac92017-08-26 21:26:51 -070032 do { \
33 size_t num = num_bytes; \
34 ptr = ((const char *)ptr) + num; \
35 size -= num; \
36 consumed_myself += num; \
37 } while(0)
38
39asn_dec_rval_t
Lev Walkin20696a42017-10-17 21:27:33 -070040OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx,
41 const asn_TYPE_descriptor_t *td, void *sptr,
42 const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
Lev Walkinc10d30a2017-08-27 00:38:21 -070043 size_t consumed_myself = 0;
44 asn_type_selector_result_t selected;
45 void *memb_ptr; /* Pointer to the member */
46 void **memb_ptr2; /* Pointer to that pointer */
47 void *inner_value;
48 asn_dec_rval_t rv;
49
Lev Walkin75b6fe42017-08-27 01:03:22 -070050 if(!(elm->flags & ATF_OPEN_TYPE)) {
51 ASN__DECODE_FAILED;
52 }
53
54 if(!elm->type_selector) {
55 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
56 td->name, elm->name, elm->type->name);
Lev Walkinc10d30a2017-08-27 00:38:21 -070057 ASN__DECODE_FAILED;
58 }
59
60 selected = elm->type_selector(td, sptr);
61 if(!selected.presence_index) {
62 ASN__DECODE_FAILED;
63 }
64
65 /* Fetch the pointer to this member */
66 if(elm->flags & ATF_POINTER) {
67 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
68 } else {
69 memb_ptr = (char *)sptr + elm->memb_offset;
70 memb_ptr2 = &memb_ptr;
71 }
72 if(*memb_ptr2 != NULL) {
73 /* Make sure we reset the structure first before encoding */
74 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
75 ASN__DECODE_FAILED;
76 }
77 }
78
79 inner_value =
80 (char *)*memb_ptr2
81 + elm->type->elements[selected.presence_index - 1].memb_offset;
82
83 ASN_DEBUG("presence %d\n", selected.presence_index);
84
85 rv = selected.type_descriptor->op->ber_decoder(
86 opt_codec_ctx, selected.type_descriptor, &inner_value, ptr, size,
87 elm->tag_mode);
88 ADVANCE(rv.consumed);
89 rv.consumed = 0;
90 switch(rv.code) {
91 case RC_OK:
92 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
93 selected.presence_index)
94 == 0) {
95 rv.code = RC_OK;
96 rv.consumed = consumed_myself;
97 return rv;
98 } else {
99 /* Oh, now a full-blown failure failure */
100 }
101 /* Fall through */
102 case RC_FAIL:
103 rv.consumed = consumed_myself;
104 /* Fall through */
105 case RC_WMORE:
106 break;
107 }
108
109 if(*memb_ptr2) {
Lev Walkind84f6032017-10-03 16:33:59 -0700110 const asn_CHOICE_specifics_t *specs =
111 selected.type_descriptor->specifics;
Lev Walkinc10d30a2017-08-27 00:38:21 -0700112 if(elm->flags & ATF_POINTER) {
113 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
114 *memb_ptr2 = NULL;
115 } else {
116 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
117 inner_value);
118 memset(*memb_ptr2, 0, specs->struct_size);
119 }
120 }
121 return rv;
122}
123
124asn_dec_rval_t
Lev Walkin20696a42017-10-17 21:27:33 -0700125OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx,
126 const asn_TYPE_descriptor_t *td, void *sptr,
127 const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
Lev Walkinf59dac92017-08-26 21:26:51 -0700128 size_t consumed_myself = 0;
129 asn_type_selector_result_t selected;
130 void *memb_ptr; /* Pointer to the member */
131 void **memb_ptr2; /* Pointer to that pointer */
132 void *inner_value;
Lev Walkinf59dac92017-08-26 21:26:51 -0700133 asn_dec_rval_t rv;
134
135 int xer_context = 0;
136 ssize_t ch_size;
137 pxer_chunk_type_e ch_type;
138
Lev Walkin75b6fe42017-08-27 01:03:22 -0700139 if(!(elm->flags & ATF_OPEN_TYPE)) {
140 ASN__DECODE_FAILED;
141 }
142
143 if(!elm->type_selector) {
144 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
145 td->name, elm->name, elm->type->name);
Lev Walkinf59dac92017-08-26 21:26:51 -0700146 ASN__DECODE_FAILED;
147 }
148
149 selected = elm->type_selector(td, sptr);
150 if(!selected.presence_index) {
151 ASN__DECODE_FAILED;
152 }
153
154 /* Fetch the pointer to this member */
155 assert(elm->flags == ATF_OPEN_TYPE);
156 if(elm->flags & ATF_POINTER) {
157 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
158 } else {
159 memb_ptr = (char *)sptr + elm->memb_offset;
160 memb_ptr2 = &memb_ptr;
161 }
162 if(*memb_ptr2 != NULL) {
163 /* Make sure we reset the structure first before encoding */
164 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
165 != 0) {
166 ASN__DECODE_FAILED;
167 }
168 }
169
170 /*
171 * Confirm wrapper.
172 */
173 for(;;) {
174 ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
Lev Walkin4ccce3d2017-08-27 00:41:58 -0700175 if(ch_size < 0) {
Lev Walkinf59dac92017-08-26 21:26:51 -0700176 ASN__DECODE_FAILED;
177 } else {
178 switch(ch_type) {
179 case PXER_WMORE:
180 ASN__DECODE_STARVED;
181 case PXER_COMMENT:
182 case PXER_TEXT:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700183 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700184 continue;
185 case PXER_TAG:
186 break;
187 }
188 break;
189 }
190 }
191
192 /*
193 * Wrapper value confirmed.
194 */
195 switch(xer_check_tag(ptr, ch_size, elm->name)) {
196 case XCT_OPENING:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700197 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700198 break;
199 case XCT_BROKEN:
200 default:
201 ASN__DECODE_FAILED;
202 }
203
204 inner_value =
205 (char *)*memb_ptr2
206 + elm->type->elements[selected.presence_index - 1].memb_offset;
207
208 rv = selected.type_descriptor->op->xer_decoder(
209 opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
Lev Walkinc10d30a2017-08-27 00:38:21 -0700210 ADVANCE(rv.consumed);
Lev Walkinf59dac92017-08-26 21:26:51 -0700211 rv.consumed = 0;
212 switch(rv.code) {
213 case RC_OK:
214 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
215 selected.presence_index)
216 == 0) {
217 break;
218 } else {
219 rv.code = RC_FAIL;
220 }
221 /* Fall through */
222 case RC_FAIL:
223 /* Point to a best position where failure occurred */
224 rv.consumed = consumed_myself;
225 /* Fall through */
226 case RC_WMORE:
227 /* Wrt. rv.consumed==0:
228 * In case a genuine RC_WMORE, the whole Open Type decoding
229 * will have to be restarted.
230 */
231 if(*memb_ptr2) {
Lev Walkind84f6032017-10-03 16:33:59 -0700232 const asn_CHOICE_specifics_t *specs =
233 selected.type_descriptor->specifics;
Lev Walkinf59dac92017-08-26 21:26:51 -0700234 if(elm->flags & ATF_POINTER) {
235 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
236 *memb_ptr2 = NULL;
237 } else {
238 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
239 inner_value);
240 memset(*memb_ptr2, 0, specs->struct_size);
241 }
242 }
243 return rv;
244 }
245
246 /*
247 * Finalize wrapper.
248 */
249 for(;;) {
250 ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
Lev Walkin4ccce3d2017-08-27 00:41:58 -0700251 if(ch_size < 0) {
Lev Walkinf59dac92017-08-26 21:26:51 -0700252 ASN__DECODE_FAILED;
253 } else {
254 switch(ch_type) {
255 case PXER_WMORE:
256 ASN__DECODE_STARVED;
257 case PXER_COMMENT:
258 case PXER_TEXT:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700259 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700260 continue;
261 case PXER_TAG:
262 break;
263 }
264 break;
265 }
266 }
267
268 /*
269 * Wrapper value confirmed.
270 */
271 switch(xer_check_tag(ptr, ch_size, elm->name)) {
272 case XCT_CLOSING:
Lev Walkinc10d30a2017-08-27 00:38:21 -0700273 ADVANCE(ch_size);
Lev Walkinf59dac92017-08-26 21:26:51 -0700274 break;
275 case XCT_BROKEN:
276 default:
277 ASN__DECODE_FAILED;
278 }
279
280 rv.consumed += consumed_myself;
281
282 return rv;
283}
284
285
Lev Walkin69033802017-08-25 12:15:58 -0700286#ifndef ASN_DISABLE_PER_SUPPORT
287
Lev Walkinf6853ce2017-08-11 00:50:27 -0700288asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700289OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin20696a42017-10-17 21:27:33 -0700290 const asn_TYPE_descriptor_t *td, void *sptr,
291 const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700292 asn_type_selector_result_t selected;
293 void *memb_ptr; /* Pointer to the member */
294 void **memb_ptr2; /* Pointer to that pointer */
Lev Walkinf59dac92017-08-26 21:26:51 -0700295 void *inner_value;
Lev Walkinf6853ce2017-08-11 00:50:27 -0700296 asn_dec_rval_t rv;
297
Lev Walkin75b6fe42017-08-27 01:03:22 -0700298 if(!(elm->flags & ATF_OPEN_TYPE)) {
299 ASN__DECODE_FAILED;
300 }
301
302 if(!elm->type_selector) {
303 ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
304 td->name, elm->name, elm->type->name);
Lev Walkinf6853ce2017-08-11 00:50:27 -0700305 ASN__DECODE_FAILED;
306 }
307
308 selected = elm->type_selector(td, sptr);
309 if(!selected.presence_index) {
310 ASN__DECODE_FAILED;
311 }
312
313 /* Fetch the pointer to this member */
314 assert(elm->flags == ATF_OPEN_TYPE);
315 if(elm->flags & ATF_POINTER) {
316 memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
317 } else {
318 memb_ptr = (char *)sptr + elm->memb_offset;
319 memb_ptr2 = &memb_ptr;
320 }
321 if(*memb_ptr2 != NULL) {
322 /* Make sure we reset the structure first before encoding */
323 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
324 != 0) {
325 ASN__DECODE_FAILED;
326 }
327 }
328
Lev Walkinf59dac92017-08-26 21:26:51 -0700329 inner_value =
Lev Walkinf6853ce2017-08-11 00:50:27 -0700330 (char *)*memb_ptr2
331 + elm->type->elements[selected.presence_index - 1].memb_offset;
332
333 rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
334 &inner_value, pd);
335 switch(rv.code) {
336 case RC_OK:
337 if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
338 selected.presence_index)
339 == 0) {
340 break;
341 } else {
342 rv.code = RC_FAIL;
343 }
344 /* Fall through */
345 case RC_WMORE:
346 case RC_FAIL:
347 if(*memb_ptr2) {
Lev Walkind84f6032017-10-03 16:33:59 -0700348 const asn_CHOICE_specifics_t *specs =
349 selected.type_descriptor->specifics;
Lev Walkinf6853ce2017-08-11 00:50:27 -0700350 if(elm->flags & ATF_POINTER) {
351 ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
352 *memb_ptr2 = NULL;
353 } else {
354 ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
355 inner_value);
356 memset(*memb_ptr2, 0, specs->struct_size);
357 }
358 }
359 }
360 return rv;
361}
362
Lev Walkin35ace192017-08-26 23:33:14 -0700363asn_enc_rval_t
Lev Walkin20696a42017-10-17 21:27:33 -0700364OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td,
365 const asn_per_constraints_t *constraints,
366 const void *sptr, asn_per_outp_t *po) {
367 const void *memb_ptr; /* Pointer to the member */
Lev Walkin35ace192017-08-26 23:33:14 -0700368 asn_TYPE_member_t *elm; /* CHOICE's element */
369 asn_enc_rval_t er;
370 unsigned present;
371
372 (void)constraints;
373
374 present = CHOICE_variant_get_presence(td, sptr);
375 if(present == 0 || present > td->elements_count) {
376 ASN__ENCODE_FAILED;
377 } else {
378 present--;
379 }
380
381 ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
382
383 elm = &td->elements[present];
384 if(elm->flags & ATF_POINTER) {
385 /* Member is a pointer to another structure */
Lev Walkin20696a42017-10-17 21:27:33 -0700386 memb_ptr =
387 *(const void *const *)((const char *)sptr + elm->memb_offset);
Lev Walkin35ace192017-08-26 23:33:14 -0700388 if(!memb_ptr) ASN__ENCODE_FAILED;
389 } else {
Lev Walkin20696a42017-10-17 21:27:33 -0700390 memb_ptr = (const char *)sptr + elm->memb_offset;
Lev Walkin35ace192017-08-26 23:33:14 -0700391 }
392
393 if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
394 ASN__ENCODE_FAILED;
395 }
396
397 er.encoded = 0;
398 ASN__ENCODED_OK(er);
399}
400
401
Lev Walkin69033802017-08-25 12:15:58 -0700402#endif /* ASN_DISABLE_PER_SUPPORT */