blob: 657d356863c0b49400bfc20dfe06cfbcf7f5da1b [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 */
Lev Walkincfc16d32017-08-30 19:15:08 -070057static void **
58element_ptrptr(void *struct_ptr, asn_TYPE_member_t *elm, void **tmp_save_ptr) {
59 if(elm->flags & ATF_POINTER) {
60 /* Member is a pointer to another structure */
61 return (void **)((char *)struct_ptr + elm->memb_offset);
62 } else {
63 assert(tmp_save_ptr);
64 *tmp_save_ptr = (void *)((char *)struct_ptr + elm->memb_offset);
65 return tmp_save_ptr;
66 }
Lev Walkin890e6032017-07-24 01:48:59 +040067}
68
69static void *element_ptr(void *struct_ptr, asn_TYPE_member_t *elm) {
70 if(elm->flags & ATF_POINTER) {
71 /* Member is a pointer to another structure */
72 return *(void **)((char *)struct_ptr + elm->memb_offset);
73 } else {
74 return (void *)((char *)struct_ptr + elm->memb_offset);
75 }
76}
77
Lev Walkind88bea92017-07-20 11:21:30 +030078asn_dec_rval_t
79SEQUENCE_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -070080 const asn_oer_constraints_t *constraints, void **struct_ptr,
81 const void *ptr, size_t size) {
Lev Walkind88bea92017-07-20 11:21:30 +030082 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
83 asn_dec_rval_t rval = {RC_OK, 0};
84 void *st = *struct_ptr; /* Target structure */
85 asn_struct_ctx_t *ctx; /* Decoder context */
86 size_t consumed_myself = 0; /* Consumed bytes from ptr. */
87
88
89 (void)opt_codec_ctx;
Lev Walkin494fb702017-08-07 20:07:00 -070090 (void)constraints;
Lev Walkind88bea92017-07-20 11:21:30 +030091
92 /*
93 * Create the target structure if it is not present already.
94 */
95 if(st == 0) {
96 st = *struct_ptr = CALLOC(1, specs->struct_size);
97 if(st == 0) {
98 RETURN(RC_FAIL);
99 }
100 }
101
102 /*
103 * Restore parsing context.
104 */
105 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
106 if(ctx->ptr == 0) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700107 ctx->ptr = CALLOC(1, sizeof(asn_bit_data_t));
Lev Walkind88bea92017-07-20 11:21:30 +0300108 if(!ctx->ptr) {
109 RETURN(RC_FAIL);
110 }
111 }
112
113 /*
114 * Start to parse where left previously.
115 */
116 switch(ctx->phase) {
117 case 0: {
118 /*
119 * Fetch preamble.
120 */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700121 asn_bit_data_t *preamble = ctx->ptr;
Lev Walkin890e6032017-07-24 01:48:59 +0400122 int has_extensions_bit = (specs->ext_before >= 0);
123 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
124 size_t preamble_bytes = ((7 + preamble_bits) >> 3);
Lev Walkind88bea92017-07-20 11:21:30 +0300125 uint8_t *pbytes;
126
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700127 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
128
Lev Walkin890e6032017-07-24 01:48:59 +0400129 ASN_DEBUG(
130 "Expecting preamble bits %zu for %s (including %d extension bits)",
131 preamble_bits, td->name, has_extensions_bit);
132
Lev Walkind88bea92017-07-20 11:21:30 +0300133 if(size < preamble_bytes) {
134 ASN__DECODE_STARVED;
135 }
136
137 pbytes = MALLOC(preamble_bytes + 1);
138 if(!pbytes) {
139 RETURN(RC_FAIL);
140 }
141 preamble->buffer = (const void *)pbytes;
142 memcpy(pbytes, ptr, preamble_bytes);
143 pbytes[preamble_bytes] = '\0'; /* Just in case */
Lev Walkin890e6032017-07-24 01:48:59 +0400144 preamble->nboff = has_extensions_bit;
Lev Walkind88bea92017-07-20 11:21:30 +0300145 preamble->nbits = preamble_bits;
146 ADVANCE(preamble_bytes);
147 }
148 NEXT_PHASE(ctx);
149 /* FALL THROUGH */
150 case 1: {
151 /* Decode components of the extension root */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700152 asn_bit_data_t *preamble = ctx->ptr;
Lev Walkind88bea92017-07-20 11:21:30 +0300153 size_t edx;
154
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700155 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
156
Lev Walkind88bea92017-07-20 11:21:30 +0300157 for(edx = (ctx->step >> 1); edx < td->elements_count;
158 edx++, ctx->step = (ctx->step & ~1) + 2) {
159 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkind88bea92017-07-20 11:21:30 +0300160
Lev Walkin890e6032017-07-24 01:48:59 +0400161 ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
162
Lev Walkind88bea92017-07-20 11:21:30 +0300163 if(ctx->step & 1) {
164 goto microphase2_decode_continues;
165 }
166
167
168 if(IN_EXTENSION_GROUP(specs, edx)) {
169 /* Ignore non-root components in PHASE 1 */
Lev Walkin890e6032017-07-24 01:48:59 +0400170 break;
Lev Walkind88bea92017-07-20 11:21:30 +0300171 }
172
173 if(elm->optional) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700174 int32_t present = asn_get_few_bits(preamble, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300175 if(present < 0) {
Lev Walkin890e6032017-07-24 01:48:59 +0400176 ASN_DEBUG("Presence map ended prematurely: %d", present);
Lev Walkind88bea92017-07-20 11:21:30 +0300177 RETURN(RC_FAIL);
178 } else if(present == 0) {
179 if(elm->default_value) {
Lev Walkind88bea92017-07-20 11:21:30 +0300180 /* Fill-in DEFAULT */
Lev Walkincfc16d32017-08-30 19:15:08 -0700181 void *tmp;
182 if(elm->default_value(1,
183 element_ptrptr(st, elm, &tmp))) {
Lev Walkind88bea92017-07-20 11:21:30 +0300184 RETURN(RC_FAIL);
185 }
186 }
187 /* The member is not present. */
188 continue;
189 }
190 /* Present OPTIONAL or DEFAULT component. */
191 }
192
193 /*
194 * MICROPHASE 2: Invoke the member-specific decoder.
195 */
196 ctx->step |= 1; /* Confirm entering next microphase */
197 microphase2_decode_continues:
Lev Walkin14fd3e52017-08-27 01:38:45 -0700198 if(elm->flags & ATF_OPEN_TYPE) {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700199 rval = OPEN_TYPE_oer_get(opt_codec_ctx, td, st, elm, ptr, size);
Lev Walkin7c876302017-08-10 06:11:24 -0700200 } else {
Lev Walkin09bec462017-08-31 01:31:43 -0700201 void *save_memb_ptr; /* Temporary reference. */
Lev Walkinf6853ce2017-08-11 00:50:27 -0700202 void **memb_ptr2; /* Pointer to a pointer to a memmber */
203
Lev Walkin09bec462017-08-31 01:31:43 -0700204 memb_ptr2 = element_ptrptr(st, elm, &save_memb_ptr);
Lev Walkinf6853ce2017-08-11 00:50:27 -0700205
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800206 rval = elm->type->op->oer_decoder(opt_codec_ctx, elm->type,
Lev Walkin09bec462017-08-31 01:31:43 -0700207 elm->oer_constraints,
208 memb_ptr2, ptr, size);
Lev Walkin7c876302017-08-10 06:11:24 -0700209 }
Lev Walkind88bea92017-07-20 11:21:30 +0300210 switch(rval.code) {
211 case RC_OK:
212 ADVANCE(rval.consumed);
213 break;
214 case RC_WMORE:
Lev Walkin890e6032017-07-24 01:48:59 +0400215 ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
216 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300217 ADVANCE(rval.consumed);
218 RETURN(RC_WMORE);
219 case RC_FAIL:
Lev Walkin890e6032017-07-24 01:48:59 +0400220 ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
221 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300222 RETURN(RC_FAIL);
223 }
224 } /* for(all root members) */
225
226 }
227 NEXT_PHASE(ctx);
228 /* FALL THROUGH */
229 case 2: {
230 /* Cleanup preamble. */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700231 asn_bit_data_t *preamble = ctx->ptr;
232 asn_bit_data_t *extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400233 int has_extensions_bit = (specs->ext_before >= 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300234 int extensions_present =
Lev Walkin1a503892017-08-31 02:15:11 -0700235 has_extensions_bit
236 && (preamble->buffer == NULL
237 || (((const uint8_t *)preamble->buffer)[0] & 0x80));
Lev Walkind88bea92017-07-20 11:21:30 +0300238 uint8_t unused_bits;
239 size_t len = 0;
240 ssize_t len_len;
241 uint8_t *ebytes;
242
243 union {
244 const uint8_t *cptr;
245 uint8_t *uptr;
246 } unconst;
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700247
248 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
249
Lev Walkind88bea92017-07-20 11:21:30 +0300250 unconst.cptr = preamble->buffer;
251 FREEMEM(unconst.uptr);
Lev Walkin1a503892017-08-31 02:15:11 -0700252 preamble->buffer = 0; /* Will do extensions_present==1 next time. */
Lev Walkind88bea92017-07-20 11:21:30 +0300253
254 if(!extensions_present) {
255 ctx->phase = 10;
256 RETURN(RC_OK);
257 }
258
259 /*
260 * X.696 (08/2015) #16.1 (c), #16.4
261 * Read in the extension addition presence bitmap.
262 */
263
264 len_len = oer_fetch_length(ptr, size, &len);
265 if(len_len > 0) {
266 ADVANCE(len_len);
267 } if(len_len < 0) {
268 RETURN(RC_FAIL);
269 } else {
270 RETURN(RC_WMORE);
271 }
272
273 if(len == 0) {
274 /* 16.4.1-2 */
275 RETURN(RC_FAIL);
276 } else if(len > size) {
277 RETURN(RC_WMORE);
278 }
279
280 /* Account for unused bits */
281 unused_bits = 0x7 & *(const uint8_t *)ptr;
282 ADVANCE(1);
283 len--;
284 if(unused_bits && len == 0) {
285 RETURN(RC_FAIL);
286 }
287
288 /* Get the extensions map */
289 ebytes = MALLOC(len + 1);
290 if(!ebytes) {
291 RETURN(RC_FAIL);
292 }
293 memcpy(ebytes, ptr, len);
294 ebytes[len] = '\0';
295
296 extadds = preamble;
297 memset(extadds, 0, sizeof(*extadds));
298 extadds->buffer = ebytes;
299 extadds->nboff = 0;
300 extadds->nbits = 8 * len - unused_bits;
301
302 ADVANCE(len);
303 }
304 NEXT_PHASE(ctx);
305 ctx->step = (specs->ext_after + 1);
306 /* Fall through */
307 case 3:
Lev Walkin890e6032017-07-24 01:48:59 +0400308 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
309 for(; ctx->step < specs->ext_before - 1; ctx->step++) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700310 asn_bit_data_t *extadds = ctx->ptr;
Lev Walkind88bea92017-07-20 11:21:30 +0300311 size_t edx = ctx->step;
312 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkincfc16d32017-08-30 19:15:08 -0700313 void **memb_ptr2 = element_ptrptr(st, elm, 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300314
Lev Walkin6cd0d562017-08-25 11:57:01 -0700315 switch(asn_get_few_bits(extadds, 1)) {
Lev Walkind88bea92017-07-20 11:21:30 +0300316 case -1:
317 /*
318 * Not every one of our extensions is known to the remote side.
319 * Continue filling in their defaults though.
320 */
321 /* Fall through */
322 case 0:
323 /* Fill-in DEFAULT */
324 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
325 RETURN(RC_FAIL);
326 }
327 continue;
328 case 1: {
329 /* Read OER open type */
330 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
331 elm->oer_constraints,
332 memb_ptr2, ptr, size);
333 if(ot_size > 0) {
334 ADVANCE(ot_size);
335 } else if(ot_size < 0) {
336 RETURN(RC_FAIL);
337 } else {
338 /* Roll back open type parsing */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700339 asn_get_undo(extadds, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300340 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
341 *memb_ptr2 = NULL;
342 RETURN(RC_WMORE);
343 }
344 break;
345 }
346 default:
347 RETURN(RC_FAIL);
348 }
349 }
350
351 NEXT_PHASE(ctx);
352 /* Fall through */
353 case 4:
Lev Walkin890e6032017-07-24 01:48:59 +0400354 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300355 /* Read in the rest of Open Types while ignoring them */
356 for(;;) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700357 asn_bit_data_t *extadds = ctx->ptr;
358 switch(asn_get_few_bits(extadds, 1)) {
Lev Walkind88bea92017-07-20 11:21:30 +0300359 case 0:
360 continue;
361 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300362 ssize_t skipped = oer_open_type_skip(ptr, size);
363 if(skipped > 0) {
364 ADVANCE(skipped);
365 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300366 RETURN(RC_FAIL);
367 } else {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700368 asn_get_undo(extadds, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300369 RETURN(RC_WMORE);
370 }
371 continue;
372 }
373 case -1:
374 /* No more Open Type encoded components */
375 break;
376 default:
377 RETURN(RC_FAIL);
378 }
379 break;
380 }
381 }
382
383 return rval;
384}
385
386/*
387 * Encode as Canonical OER.
388 */
389asn_enc_rval_t
390SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700391 const asn_oer_constraints_t *constraints, void *sptr,
392 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin890e6032017-07-24 01:48:59 +0400393 asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
394 size_t computed_size = 0;
395 int has_extensions_bit = (specs->ext_before >= 0);
396 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
397 uint32_t has_extensions = 0;
398 size_t edx;
399 int ret;
Lev Walkind88bea92017-07-20 11:21:30 +0300400
Lev Walkin494fb702017-08-07 20:07:00 -0700401 (void)constraints;
402
Lev Walkin890e6032017-07-24 01:48:59 +0400403 if(preamble_bits) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700404 asn_bit_outp_t preamble;
Lev Walkind88bea92017-07-20 11:21:30 +0300405
Lev Walkin890e6032017-07-24 01:48:59 +0400406 memset(&preamble, 0, sizeof(preamble));
Lev Walkin6cd0d562017-08-25 11:57:01 -0700407 preamble.output = cb;
Lev Walkin890e6032017-07-24 01:48:59 +0400408 preamble.op_key = app_key;
409
410 if(has_extensions_bit) {
Lev Walkin494fb702017-08-07 20:07:00 -0700411 for(edx = specs->ext_after + 1;
412 (ssize_t)edx < specs->ext_before - 1; edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400413 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin09bec462017-08-31 01:31:43 -0700414 void *memb_ptr = element_ptr(sptr, elm);
415 if(memb_ptr) {
416 if(elm->default_value
417 && elm->default_value(0, &memb_ptr) == 1) {
418 /* Do not encode default values in extensions */
419 } else {
420 has_extensions = 1;
421 break;
422 }
Lev Walkin890e6032017-07-24 01:48:59 +0400423 }
424 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700425 ret = asn_put_few_bits(&preamble, has_extensions, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400426 assert(ret == 0);
427 if(ret < 0) {
428 ASN__ENCODE_FAILED;
429 }
430 }
431
432 /*
433 * Encode optional components bitmap.
434 */
435 if(specs->roms_count) {
436 for(edx = 0; edx < td->elements_count; edx++) {
437 asn_TYPE_member_t *elm = &td->elements[edx];
438
439 if(IN_EXTENSION_GROUP(specs, edx)) break;
440
441 if(elm->optional) {
Lev Walkin09bec462017-08-31 01:31:43 -0700442 void *memb_ptr = element_ptr(sptr, elm);
443 uint32_t has_component = memb_ptr != NULL;
444 if(has_component && elm->default_value
445 && elm->default_value(0, &memb_ptr) == 1) {
446 has_component = 0;
447 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700448 ret = asn_put_few_bits(&preamble, has_component, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400449 if(ret < 0) {
450 ASN__ENCODE_FAILED;
451 }
452 }
453 }
454 }
455
Lev Walkin6cd0d562017-08-25 11:57:01 -0700456 asn_put_aligned_flush(&preamble);
Lev Walkin890e6032017-07-24 01:48:59 +0400457 computed_size += preamble.flushed_bytes;
458 } /* if(preamble_bits) */
459
460 /*
461 * Put root components and extensions root.
462 */
463 for(edx = 0; edx < td->elements_count; edx++) {
464 asn_TYPE_member_t *elm = &td->elements[edx];
465 asn_enc_rval_t er;
466 void *memb_ptr;
467
468 if(IN_EXTENSION_GROUP(specs, edx)) break;
469
470 memb_ptr = element_ptr(sptr, elm);
Lev Walkin09bec462017-08-31 01:31:43 -0700471 if(memb_ptr) {
472 if(elm->default_value && elm->default_value(0, &memb_ptr) == 1) {
473 /* Skip default values in encoding */
474 continue;
475 }
476 } else {
Lev Walkin890e6032017-07-24 01:48:59 +0400477 if(elm->optional) continue;
478 /* Mandatory element is missing */
479 ASN__ENCODE_FAILED;
480 }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800481 if(!elm->type->op->oer_encoder) {
Lev Walkin890e6032017-07-24 01:48:59 +0400482 ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
483 ASN__ENCODE_FAILED;
484 }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800485 er = elm->type->op->oer_encoder(elm->type, elm->oer_constraints, memb_ptr,
Lev Walkin890e6032017-07-24 01:48:59 +0400486 cb, app_key);
487 if(er.encoded == -1) {
488 ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
489 elm->name);
490 return er;
491 }
492 computed_size += er.encoded;
493 }
494
495 /*
496 * Before encode extensions, encode extensions additions presense bitmap
497 # X.696 (08/2015) #16.4.
498 */
499 if(has_extensions) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700500 asn_bit_outp_t extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400501
502 /* Special case allowing us to use exactly one byte for #8.6 */
503 size_t aoms_length_bits = specs->aoms_count;
Lev Walkin09bec462017-08-31 01:31:43 -0700504 size_t aoms_length_bytes = (7 + aoms_length_bits) >> 3;
Lev Walkin890e6032017-07-24 01:48:59 +0400505 uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
506
507 assert(1 + aoms_length_bytes <= 127);
508
509 memset(&extadds, 0, sizeof(extadds));
Lev Walkin6cd0d562017-08-25 11:57:01 -0700510 extadds.output = cb;
Lev Walkin890e6032017-07-24 01:48:59 +0400511 extadds.op_key = app_key;
512
513 /* #8.6 length determinant */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700514 ret = asn_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
Lev Walkin890e6032017-07-24 01:48:59 +0400515 if(ret < 0) ASN__ENCODE_FAILED;
516
517 /* Number of unused bytes, #16.4.2 */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700518 ret = asn_put_few_bits(&extadds, unused_bits, 8);
Lev Walkin890e6032017-07-24 01:48:59 +0400519 if(ret < 0) ASN__ENCODE_FAILED;
520
521 /* Encode presence bitmap #16.4.3 */
Lev Walkin494fb702017-08-07 20:07:00 -0700522 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
523 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400524 asn_TYPE_member_t *elm = &td->elements[edx];
525 void *memb_ptr = element_ptr(sptr, elm);
Lev Walkin09bec462017-08-31 01:31:43 -0700526 if(memb_ptr && elm->default_value
527 && elm->default_value(0, &memb_ptr) == 1) {
528 memb_ptr = 0; /* Do not encode default value. */
529 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700530 ret |= asn_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400531 }
532 if(ret < 0) ASN__ENCODE_FAILED;
533
Lev Walkin6cd0d562017-08-25 11:57:01 -0700534 asn_put_aligned_flush(&extadds);
Lev Walkin890e6032017-07-24 01:48:59 +0400535 computed_size += extadds.flushed_bytes;
536
537 /* Now, encode extensions */
Lev Walkin494fb702017-08-07 20:07:00 -0700538 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
539 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400540 asn_TYPE_member_t *elm = &td->elements[edx];
541 void *memb_ptr = element_ptr(sptr, elm);
542
543 if(memb_ptr) {
Lev Walkin09bec462017-08-31 01:31:43 -0700544 if(elm->default_value
545 && elm->default_value(0, &memb_ptr) == 1) {
546 /* Do not encode default value. */
547 } else {
548 asn_enc_rval_t er = elm->type->op->oer_encoder(
549 elm->type, elm->oer_constraints, memb_ptr, cb, app_key);
550 if(er.encoded == -1) {
551 return er;
552 }
553 computed_size += er.encoded;
Lev Walkin890e6032017-07-24 01:48:59 +0400554 }
Lev Walkin890e6032017-07-24 01:48:59 +0400555 } else if(!elm->optional) {
556 ASN__ENCODE_FAILED;
557 }
558 }
559 } /* if(has_extensions) */
560
561
562 {
563 asn_enc_rval_t er = {0, 0, 0};
564 er.encoded = computed_size;
565 ASN__ENCODED_OK(er);
566 }
Lev Walkind88bea92017-07-20 11:21:30 +0300567}
568
569#endif /* ASN_DISABLE_OER_SUPPORT */