blob: 85566a3e52c46130566bb67b85c672e5ef53b412 [file] [log] [blame]
Lev Walkind88bea92017-07-20 11:21:30 +03001/*
2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 * Redistribution and modifications are permitted subject to BSD license.
5 */
6#ifndef ASN_DISABLE_OER_SUPPORT
7
8#include <asn_internal.h>
9#include <constr_SEQUENCE.h>
Lev Walkinf6853ce2017-08-11 00:50:27 -070010#include <OPEN_TYPE.h>
Lev Walkind88bea92017-07-20 11:21:30 +030011#include <errno.h>
12
13/*
14 * This macro "eats" the part of the buffer which is definitely "consumed",
15 * i.e. was correctly converted into local representation or rightfully skipped.
16 */
17#undef ADVANCE
18#define ADVANCE(num_bytes) \
19 do { \
20 size_t num = num_bytes; \
21 ptr = ((const char *)ptr) + num; \
22 size -= num; \
23 consumed_myself += num; \
24 } while(0)
25
26/*
27 * Switch to the next phase of parsing.
28 */
29#undef NEXT_PHASE
30#undef PHASE_OUT
31#define NEXT_PHASE(ctx) \
32 do { \
33 ctx->phase++; \
34 ctx->step = 0; \
35 } while(0)
36
37/*
38 * Check whether we are inside the extensions group.
39 */
40#define IN_EXTENSION_GROUP(specs, memb_idx) \
Lev Walkin494fb702017-08-07 20:07:00 -070041 ( (((ssize_t)(memb_idx)) > (specs)->ext_after) \
42 &&(((ssize_t)(memb_idx)) < (specs)->ext_before))
Lev Walkind88bea92017-07-20 11:21:30 +030043
44/*
45 * Return a standardized complex structure.
46 */
47#undef RETURN
48#define RETURN(_code) do { \
49 rval.code = _code; \
50 rval.consumed = consumed_myself;\
51 return rval; \
52 } while(0)
53
Lev Walkin890e6032017-07-24 01:48:59 +040054/*
55 * Return pointer to a member.
56 */
57static void **element_ptrptr(void *struct_ptr, asn_TYPE_member_t *elm) {
58 assert(elm->flags & ATF_POINTER);
59 /* Member is a pointer to another structure */
60 return (void **)((char *)struct_ptr + elm->memb_offset);
61}
62
63static void *element_ptr(void *struct_ptr, asn_TYPE_member_t *elm) {
64 if(elm->flags & ATF_POINTER) {
65 /* Member is a pointer to another structure */
66 return *(void **)((char *)struct_ptr + elm->memb_offset);
67 } else {
68 return (void *)((char *)struct_ptr + elm->memb_offset);
69 }
70}
71
Lev Walkind88bea92017-07-20 11:21:30 +030072asn_dec_rval_t
73SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -070074 const asn_oer_constraints_t *constraints, void **struct_ptr,
75 const void *ptr, size_t size) {
Lev Walkind88bea92017-07-20 11:21:30 +030076 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
77 asn_dec_rval_t rval = {RC_OK, 0};
78 void *st = *struct_ptr; /* Target structure */
79 asn_struct_ctx_t *ctx; /* Decoder context */
80 size_t consumed_myself = 0; /* Consumed bytes from ptr. */
81
82
83 (void)opt_codec_ctx;
Lev Walkin494fb702017-08-07 20:07:00 -070084 (void)constraints;
Lev Walkind88bea92017-07-20 11:21:30 +030085
86 /*
87 * Create the target structure if it is not present already.
88 */
89 if(st == 0) {
90 st = *struct_ptr = CALLOC(1, specs->struct_size);
91 if(st == 0) {
92 RETURN(RC_FAIL);
93 }
94 }
95
96 /*
97 * Restore parsing context.
98 */
99 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
100 if(ctx->ptr == 0) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700101 ctx->ptr = CALLOC(1, sizeof(asn_bit_data_t));
Lev Walkind88bea92017-07-20 11:21:30 +0300102 if(!ctx->ptr) {
103 RETURN(RC_FAIL);
104 }
105 }
106
107 /*
108 * Start to parse where left previously.
109 */
110 switch(ctx->phase) {
111 case 0: {
112 /*
113 * Fetch preamble.
114 */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700115 asn_bit_data_t *preamble = ctx->ptr;
Lev Walkin890e6032017-07-24 01:48:59 +0400116 int has_extensions_bit = (specs->ext_before >= 0);
117 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
118 size_t preamble_bytes = ((7 + preamble_bits) >> 3);
Lev Walkind88bea92017-07-20 11:21:30 +0300119 uint8_t *pbytes;
120
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700121 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
122
Lev Walkin890e6032017-07-24 01:48:59 +0400123 ASN_DEBUG(
124 "Expecting preamble bits %zu for %s (including %d extension bits)",
125 preamble_bits, td->name, has_extensions_bit);
126
Lev Walkind88bea92017-07-20 11:21:30 +0300127 if(size < preamble_bytes) {
128 ASN__DECODE_STARVED;
129 }
130
131 pbytes = MALLOC(preamble_bytes + 1);
132 if(!pbytes) {
133 RETURN(RC_FAIL);
134 }
135 preamble->buffer = (const void *)pbytes;
136 memcpy(pbytes, ptr, preamble_bytes);
137 pbytes[preamble_bytes] = '\0'; /* Just in case */
Lev Walkin890e6032017-07-24 01:48:59 +0400138 preamble->nboff = has_extensions_bit;
Lev Walkind88bea92017-07-20 11:21:30 +0300139 preamble->nbits = preamble_bits;
140 ADVANCE(preamble_bytes);
141 }
142 NEXT_PHASE(ctx);
143 /* FALL THROUGH */
144 case 1: {
145 /* Decode components of the extension root */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700146 asn_bit_data_t *preamble = ctx->ptr;
Lev Walkind88bea92017-07-20 11:21:30 +0300147 size_t edx;
148
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700149 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
150
Lev Walkind88bea92017-07-20 11:21:30 +0300151 for(edx = (ctx->step >> 1); edx < td->elements_count;
152 edx++, ctx->step = (ctx->step & ~1) + 2) {
153 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkind88bea92017-07-20 11:21:30 +0300154
Lev Walkin890e6032017-07-24 01:48:59 +0400155 ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
156
Lev Walkind88bea92017-07-20 11:21:30 +0300157 if(ctx->step & 1) {
158 goto microphase2_decode_continues;
159 }
160
161
162 if(IN_EXTENSION_GROUP(specs, edx)) {
163 /* Ignore non-root components in PHASE 1 */
Lev Walkin890e6032017-07-24 01:48:59 +0400164 break;
Lev Walkind88bea92017-07-20 11:21:30 +0300165 }
166
167 if(elm->optional) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700168 int32_t present = asn_get_few_bits(preamble, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300169 if(present < 0) {
Lev Walkin890e6032017-07-24 01:48:59 +0400170 ASN_DEBUG("Presence map ended prematurely: %d", present);
Lev Walkind88bea92017-07-20 11:21:30 +0300171 RETURN(RC_FAIL);
172 } else if(present == 0) {
173 if(elm->default_value) {
Lev Walkind88bea92017-07-20 11:21:30 +0300174 /* Fill-in DEFAULT */
Lev Walkin890e6032017-07-24 01:48:59 +0400175 if(elm->default_value(1, element_ptrptr(st, elm))) {
Lev Walkind88bea92017-07-20 11:21:30 +0300176 RETURN(RC_FAIL);
177 }
178 }
179 /* The member is not present. */
180 continue;
181 }
182 /* Present OPTIONAL or DEFAULT component. */
183 }
184
185 /*
186 * MICROPHASE 2: Invoke the member-specific decoder.
187 */
188 ctx->step |= 1; /* Confirm entering next microphase */
189 microphase2_decode_continues:
Lev Walkin14fd3e52017-08-27 01:38:45 -0700190 if(elm->flags & ATF_OPEN_TYPE) {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700191 rval = OPEN_TYPE_oer_get(opt_codec_ctx, td, st, elm, ptr, size);
Lev Walkin7c876302017-08-10 06:11:24 -0700192 } else {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700193 void *memb_tmpptr; /* Temporary reference. */
194 void **memb_ptr2; /* Pointer to a pointer to a memmber */
195
196 if(elm->flags & ATF_POINTER) {
197 /* Member is a pointer to another structure */
198 memb_ptr2 = (void **)((char *)st + elm->memb_offset);
199 } else {
200 memb_tmpptr = (char *)st + elm->memb_offset;
201 memb_ptr2 = &memb_tmpptr; /* Ensure remains in scope! */
202 }
203
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800204 rval = elm->type->op->oer_decoder(opt_codec_ctx, elm->type,
Lev Walkin7c876302017-08-10 06:11:24 -0700205 elm->oer_constraints, memb_ptr2,
206 ptr, size);
207 }
Lev Walkind88bea92017-07-20 11:21:30 +0300208 switch(rval.code) {
209 case RC_OK:
210 ADVANCE(rval.consumed);
211 break;
212 case RC_WMORE:
Lev Walkin890e6032017-07-24 01:48:59 +0400213 ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
214 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300215 ADVANCE(rval.consumed);
216 RETURN(RC_WMORE);
217 case RC_FAIL:
Lev Walkin890e6032017-07-24 01:48:59 +0400218 ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
219 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300220 RETURN(RC_FAIL);
221 }
222 } /* for(all root members) */
223
224 }
225 NEXT_PHASE(ctx);
226 /* FALL THROUGH */
227 case 2: {
228 /* Cleanup preamble. */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700229 asn_bit_data_t *preamble = ctx->ptr;
230 asn_bit_data_t *extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400231 int has_extensions_bit = (specs->ext_before >= 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300232 int extensions_present =
Lev Walkin890e6032017-07-24 01:48:59 +0400233 has_extensions_bit && (((const uint8_t *)preamble->buffer)[0] & 0x80);
Lev Walkind88bea92017-07-20 11:21:30 +0300234 uint8_t unused_bits;
235 size_t len = 0;
236 ssize_t len_len;
237 uint8_t *ebytes;
238
239 union {
240 const uint8_t *cptr;
241 uint8_t *uptr;
242 } unconst;
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700243
244 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
245
Lev Walkind88bea92017-07-20 11:21:30 +0300246 unconst.cptr = preamble->buffer;
247 FREEMEM(unconst.uptr);
248 preamble->buffer = 0;
249
250 if(!extensions_present) {
251 ctx->phase = 10;
252 RETURN(RC_OK);
253 }
254
255 /*
256 * X.696 (08/2015) #16.1 (c), #16.4
257 * Read in the extension addition presence bitmap.
258 */
259
260 len_len = oer_fetch_length(ptr, size, &len);
261 if(len_len > 0) {
262 ADVANCE(len_len);
263 } if(len_len < 0) {
264 RETURN(RC_FAIL);
265 } else {
266 RETURN(RC_WMORE);
267 }
268
269 if(len == 0) {
270 /* 16.4.1-2 */
271 RETURN(RC_FAIL);
272 } else if(len > size) {
273 RETURN(RC_WMORE);
274 }
275
276 /* Account for unused bits */
277 unused_bits = 0x7 & *(const uint8_t *)ptr;
278 ADVANCE(1);
279 len--;
280 if(unused_bits && len == 0) {
281 RETURN(RC_FAIL);
282 }
283
284 /* Get the extensions map */
285 ebytes = MALLOC(len + 1);
286 if(!ebytes) {
287 RETURN(RC_FAIL);
288 }
289 memcpy(ebytes, ptr, len);
290 ebytes[len] = '\0';
291
292 extadds = preamble;
293 memset(extadds, 0, sizeof(*extadds));
294 extadds->buffer = ebytes;
295 extadds->nboff = 0;
296 extadds->nbits = 8 * len - unused_bits;
297
298 ADVANCE(len);
299 }
300 NEXT_PHASE(ctx);
301 ctx->step = (specs->ext_after + 1);
302 /* Fall through */
303 case 3:
Lev Walkin890e6032017-07-24 01:48:59 +0400304 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
305 for(; ctx->step < specs->ext_before - 1; ctx->step++) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700306 asn_bit_data_t *extadds = ctx->ptr;
Lev Walkind88bea92017-07-20 11:21:30 +0300307 size_t edx = ctx->step;
308 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin890e6032017-07-24 01:48:59 +0400309 void **memb_ptr2 = element_ptrptr(st, elm);
Lev Walkind88bea92017-07-20 11:21:30 +0300310
Lev Walkin6cd0d562017-08-25 11:57:01 -0700311 switch(asn_get_few_bits(extadds, 1)) {
Lev Walkind88bea92017-07-20 11:21:30 +0300312 case -1:
313 /*
314 * Not every one of our extensions is known to the remote side.
315 * Continue filling in their defaults though.
316 */
317 /* Fall through */
318 case 0:
319 /* Fill-in DEFAULT */
320 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
321 RETURN(RC_FAIL);
322 }
323 continue;
324 case 1: {
325 /* Read OER open type */
326 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
327 elm->oer_constraints,
328 memb_ptr2, ptr, size);
329 if(ot_size > 0) {
330 ADVANCE(ot_size);
331 } else if(ot_size < 0) {
332 RETURN(RC_FAIL);
333 } else {
334 /* Roll back open type parsing */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700335 asn_get_undo(extadds, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300336 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
337 *memb_ptr2 = NULL;
338 RETURN(RC_WMORE);
339 }
340 break;
341 }
342 default:
343 RETURN(RC_FAIL);
344 }
345 }
346
347 NEXT_PHASE(ctx);
348 /* Fall through */
349 case 4:
Lev Walkin890e6032017-07-24 01:48:59 +0400350 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300351 /* Read in the rest of Open Types while ignoring them */
352 for(;;) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700353 asn_bit_data_t *extadds = ctx->ptr;
354 switch(asn_get_few_bits(extadds, 1)) {
Lev Walkind88bea92017-07-20 11:21:30 +0300355 case 0:
356 continue;
357 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300358 ssize_t skipped = oer_open_type_skip(ptr, size);
359 if(skipped > 0) {
360 ADVANCE(skipped);
361 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300362 RETURN(RC_FAIL);
363 } else {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700364 asn_get_undo(extadds, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300365 RETURN(RC_WMORE);
366 }
367 continue;
368 }
369 case -1:
370 /* No more Open Type encoded components */
371 break;
372 default:
373 RETURN(RC_FAIL);
374 }
375 break;
376 }
377 }
378
379 return rval;
380}
381
382/*
383 * Encode as Canonical OER.
384 */
385asn_enc_rval_t
386SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700387 const asn_oer_constraints_t *constraints, void *sptr,
388 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin890e6032017-07-24 01:48:59 +0400389 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
390 size_t computed_size = 0;
391 int has_extensions_bit = (specs->ext_before >= 0);
392 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
393 uint32_t has_extensions = 0;
394 size_t edx;
395 int ret;
Lev Walkind88bea92017-07-20 11:21:30 +0300396
Lev Walkin494fb702017-08-07 20:07:00 -0700397 (void)constraints;
398
Lev Walkin890e6032017-07-24 01:48:59 +0400399 if(preamble_bits) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700400 asn_bit_outp_t preamble;
Lev Walkind88bea92017-07-20 11:21:30 +0300401
Lev Walkin890e6032017-07-24 01:48:59 +0400402 memset(&preamble, 0, sizeof(preamble));
Lev Walkin6cd0d562017-08-25 11:57:01 -0700403 preamble.output = cb;
Lev Walkin890e6032017-07-24 01:48:59 +0400404 preamble.op_key = app_key;
405
406 if(has_extensions_bit) {
Lev Walkin494fb702017-08-07 20:07:00 -0700407 for(edx = specs->ext_after + 1;
408 (ssize_t)edx < specs->ext_before - 1; edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400409 asn_TYPE_member_t *elm = &td->elements[edx];
410 if(element_ptr(sptr, elm)) {
411 has_extensions = 1;
412 break;
413 }
414 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700415 ret = asn_put_few_bits(&preamble, has_extensions, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400416 assert(ret == 0);
417 if(ret < 0) {
418 ASN__ENCODE_FAILED;
419 }
420 }
421
422 /*
423 * Encode optional components bitmap.
424 */
425 if(specs->roms_count) {
426 for(edx = 0; edx < td->elements_count; edx++) {
427 asn_TYPE_member_t *elm = &td->elements[edx];
428
429 if(IN_EXTENSION_GROUP(specs, edx)) break;
430
431 if(elm->optional) {
432 uint32_t has_component = (element_ptr(sptr, elm) != NULL);
Lev Walkin6cd0d562017-08-25 11:57:01 -0700433 ret = asn_put_few_bits(&preamble, has_component, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400434 if(ret < 0) {
435 ASN__ENCODE_FAILED;
436 }
437 }
438 }
439 }
440
Lev Walkin6cd0d562017-08-25 11:57:01 -0700441 asn_put_aligned_flush(&preamble);
Lev Walkin890e6032017-07-24 01:48:59 +0400442 computed_size += preamble.flushed_bytes;
443 } /* if(preamble_bits) */
444
445 /*
446 * Put root components and extensions root.
447 */
448 for(edx = 0; edx < td->elements_count; edx++) {
449 asn_TYPE_member_t *elm = &td->elements[edx];
450 asn_enc_rval_t er;
451 void *memb_ptr;
452
453 if(IN_EXTENSION_GROUP(specs, edx)) break;
454
455 memb_ptr = element_ptr(sptr, elm);
456 if(!memb_ptr) {
457 if(elm->optional) continue;
458 /* Mandatory element is missing */
459 ASN__ENCODE_FAILED;
460 }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800461 if(!elm->type->op->oer_encoder) {
Lev Walkin890e6032017-07-24 01:48:59 +0400462 ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
463 ASN__ENCODE_FAILED;
464 }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800465 er = elm->type->op->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
Lev Walkin890e6032017-07-24 01:48:59 +0400466 cb, app_key);
467 if(er.encoded == -1) {
468 ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
469 elm->name);
470 return er;
471 }
472 computed_size += er.encoded;
473 }
474
475 /*
476 * Before encode extensions, encode extensions additions presense bitmap
477 # X.696 (08/2015) #16.4.
478 */
479 if(has_extensions) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700480 asn_bit_outp_t extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400481
482 /* Special case allowing us to use exactly one byte for #8.6 */
483 size_t aoms_length_bits = specs->aoms_count;
484 size_t aoms_length_bytes = (7 + specs->aoms_count) >> 3;
485 uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
486
487 assert(1 + aoms_length_bytes <= 127);
488
489 memset(&extadds, 0, sizeof(extadds));
Lev Walkin6cd0d562017-08-25 11:57:01 -0700490 extadds.output = cb;
Lev Walkin890e6032017-07-24 01:48:59 +0400491 extadds.op_key = app_key;
492
493 /* #8.6 length determinant */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700494 ret = asn_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
Lev Walkin890e6032017-07-24 01:48:59 +0400495 if(ret < 0) ASN__ENCODE_FAILED;
496
497 /* Number of unused bytes, #16.4.2 */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700498 ret = asn_put_few_bits(&extadds, unused_bits, 8);
Lev Walkin890e6032017-07-24 01:48:59 +0400499 if(ret < 0) ASN__ENCODE_FAILED;
500
501 /* Encode presence bitmap #16.4.3 */
Lev Walkin494fb702017-08-07 20:07:00 -0700502 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
503 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400504 asn_TYPE_member_t *elm = &td->elements[edx];
505 void *memb_ptr = element_ptr(sptr, elm);
Lev Walkin6cd0d562017-08-25 11:57:01 -0700506 ret |= asn_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400507 }
508 if(ret < 0) ASN__ENCODE_FAILED;
509
Lev Walkin6cd0d562017-08-25 11:57:01 -0700510 asn_put_aligned_flush(&extadds);
Lev Walkin890e6032017-07-24 01:48:59 +0400511 computed_size += extadds.flushed_bytes;
512
513 /* Now, encode extensions */
Lev Walkin494fb702017-08-07 20:07:00 -0700514 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
515 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400516 asn_TYPE_member_t *elm = &td->elements[edx];
517 void *memb_ptr = element_ptr(sptr, elm);
518
519 if(memb_ptr) {
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800520 asn_enc_rval_t er = elm->type->op->oer_encoder(
Lev Walkin890e6032017-07-24 01:48:59 +0400521 elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
522 if(er.encoded == -1) {
523 return er;
524 }
525 computed_size += er.encoded;
526 } else if(!elm->optional) {
527 ASN__ENCODE_FAILED;
528 }
529 }
530 } /* if(has_extensions) */
531
532
533 {
534 asn_enc_rval_t er = {0, 0, 0};
535 er.encoded = computed_size;
536 ASN__ENCODED_OK(er);
537 }
Lev Walkind88bea92017-07-20 11:21:30 +0300538}
539
540#endif /* ASN_DISABLE_OER_SUPPORT */