blob: 4e71596640b39dca4ecee725b5793bcce45d8feb [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
Lev Walkinafbf2a92017-09-12 23:30:27 -070079SEQUENCE_decode_oer(const 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 Walkind84f6032017-10-03 16:33:59 -070082 const asn_SEQUENCE_specifics_t *specs =
83 (const asn_SEQUENCE_specifics_t *)td->specifics;
Lev Walkind88bea92017-07-20 11:21:30 +030084 asn_dec_rval_t rval = {RC_OK, 0};
85 void *st = *struct_ptr; /* Target structure */
86 asn_struct_ctx_t *ctx; /* Decoder context */
87 size_t consumed_myself = 0; /* Consumed bytes from ptr. */
88
89
90 (void)opt_codec_ctx;
Lev Walkin494fb702017-08-07 20:07:00 -070091 (void)constraints;
Lev Walkind88bea92017-07-20 11:21:30 +030092
93 /*
94 * Create the target structure if it is not present already.
95 */
96 if(st == 0) {
97 st = *struct_ptr = CALLOC(1, specs->struct_size);
98 if(st == 0) {
99 RETURN(RC_FAIL);
100 }
101 }
102
103 /*
104 * Restore parsing context.
105 */
106 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
107 if(ctx->ptr == 0) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700108 ctx->ptr = CALLOC(1, sizeof(asn_bit_data_t));
Lev Walkind88bea92017-07-20 11:21:30 +0300109 if(!ctx->ptr) {
110 RETURN(RC_FAIL);
111 }
112 }
113
114 /*
115 * Start to parse where left previously.
116 */
117 switch(ctx->phase) {
118 case 0: {
119 /*
120 * Fetch preamble.
121 */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700122 asn_bit_data_t *preamble = ctx->ptr;
Lev Walkin890e6032017-07-24 01:48:59 +0400123 int has_extensions_bit = (specs->ext_before >= 0);
124 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
125 size_t preamble_bytes = ((7 + preamble_bits) >> 3);
Lev Walkind88bea92017-07-20 11:21:30 +0300126 uint8_t *pbytes;
127
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700128 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 0", td->name);
129
Lev Walkin890e6032017-07-24 01:48:59 +0400130 ASN_DEBUG(
131 "Expecting preamble bits %zu for %s (including %d extension bits)",
132 preamble_bits, td->name, has_extensions_bit);
133
Lev Walkind88bea92017-07-20 11:21:30 +0300134 if(size < preamble_bytes) {
135 ASN__DECODE_STARVED;
136 }
137
138 pbytes = MALLOC(preamble_bytes + 1);
139 if(!pbytes) {
140 RETURN(RC_FAIL);
141 }
142 preamble->buffer = (const void *)pbytes;
143 memcpy(pbytes, ptr, preamble_bytes);
144 pbytes[preamble_bytes] = '\0'; /* Just in case */
Lev Walkin890e6032017-07-24 01:48:59 +0400145 preamble->nboff = has_extensions_bit;
Lev Walkind88bea92017-07-20 11:21:30 +0300146 preamble->nbits = preamble_bits;
147 ADVANCE(preamble_bytes);
148 }
149 NEXT_PHASE(ctx);
150 /* FALL THROUGH */
151 case 1: {
152 /* Decode components of the extension root */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700153 asn_bit_data_t *preamble = ctx->ptr;
Lev Walkind88bea92017-07-20 11:21:30 +0300154 size_t edx;
155
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700156 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 1", td->name);
157
Lev Walkind88bea92017-07-20 11:21:30 +0300158 for(edx = (ctx->step >> 1); edx < td->elements_count;
159 edx++, ctx->step = (ctx->step & ~1) + 2) {
160 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkind88bea92017-07-20 11:21:30 +0300161
Lev Walkin890e6032017-07-24 01:48:59 +0400162 ASN_DEBUG("Decoding %s->%s", td->name, elm->name);
163
Lev Walkind88bea92017-07-20 11:21:30 +0300164 if(ctx->step & 1) {
165 goto microphase2_decode_continues;
166 }
167
168
169 if(IN_EXTENSION_GROUP(specs, edx)) {
170 /* Ignore non-root components in PHASE 1 */
Lev Walkin890e6032017-07-24 01:48:59 +0400171 break;
Lev Walkind88bea92017-07-20 11:21:30 +0300172 }
173
174 if(elm->optional) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700175 int32_t present = asn_get_few_bits(preamble, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300176 if(present < 0) {
Lev Walkin890e6032017-07-24 01:48:59 +0400177 ASN_DEBUG("Presence map ended prematurely: %d", present);
Lev Walkind88bea92017-07-20 11:21:30 +0300178 RETURN(RC_FAIL);
179 } else if(present == 0) {
180 if(elm->default_value) {
Lev Walkind88bea92017-07-20 11:21:30 +0300181 /* Fill-in DEFAULT */
Lev Walkincfc16d32017-08-30 19:15:08 -0700182 void *tmp;
183 if(elm->default_value(1,
184 element_ptrptr(st, elm, &tmp))) {
Lev Walkind88bea92017-07-20 11:21:30 +0300185 RETURN(RC_FAIL);
186 }
187 }
188 /* The member is not present. */
189 continue;
190 }
191 /* Present OPTIONAL or DEFAULT component. */
192 }
193
194 /*
195 * MICROPHASE 2: Invoke the member-specific decoder.
196 */
197 ctx->step |= 1; /* Confirm entering next microphase */
198 microphase2_decode_continues:
Lev Walkin14fd3e52017-08-27 01:38:45 -0700199 if(elm->flags & ATF_OPEN_TYPE) {
Lev Walkinf6853ce2017-08-11 00:50:27 -0700200 rval = OPEN_TYPE_oer_get(opt_codec_ctx, td, st, elm, ptr, size);
Lev Walkin7c876302017-08-10 06:11:24 -0700201 } else {
Lev Walkin09bec462017-08-31 01:31:43 -0700202 void *save_memb_ptr; /* Temporary reference. */
Lev Walkinf6853ce2017-08-11 00:50:27 -0700203 void **memb_ptr2; /* Pointer to a pointer to a memmber */
204
Lev Walkin09bec462017-08-31 01:31:43 -0700205 memb_ptr2 = element_ptrptr(st, elm, &save_memb_ptr);
Lev Walkinf6853ce2017-08-11 00:50:27 -0700206
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800207 rval = elm->type->op->oer_decoder(opt_codec_ctx, elm->type,
Lev Walkina5972be2017-09-29 23:15:58 -0700208 elm->encoding_constraints.oer_constraints,
Lev Walkin09bec462017-08-31 01:31:43 -0700209 memb_ptr2, ptr, size);
Lev Walkin7c876302017-08-10 06:11:24 -0700210 }
Lev Walkind88bea92017-07-20 11:21:30 +0300211 switch(rval.code) {
212 case RC_OK:
213 ADVANCE(rval.consumed);
214 break;
215 case RC_WMORE:
Lev Walkin890e6032017-07-24 01:48:59 +0400216 ASN_DEBUG("More bytes needed at element %s \"%s\"", td->name,
217 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300218 ADVANCE(rval.consumed);
219 RETURN(RC_WMORE);
220 case RC_FAIL:
Lev Walkin890e6032017-07-24 01:48:59 +0400221 ASN_DEBUG("Decoding failed at element %s \"%s\"", td->name,
222 elm->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300223 RETURN(RC_FAIL);
224 }
225 } /* for(all root members) */
226
227 }
228 NEXT_PHASE(ctx);
229 /* FALL THROUGH */
230 case 2: {
231 /* Cleanup preamble. */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700232 asn_bit_data_t *preamble = ctx->ptr;
233 asn_bit_data_t *extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400234 int has_extensions_bit = (specs->ext_before >= 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300235 int extensions_present =
Lev Walkin1a503892017-08-31 02:15:11 -0700236 has_extensions_bit
237 && (preamble->buffer == NULL
238 || (((const uint8_t *)preamble->buffer)[0] & 0x80));
Lev Walkind88bea92017-07-20 11:21:30 +0300239 uint8_t unused_bits;
240 size_t len = 0;
241 ssize_t len_len;
242 uint8_t *ebytes;
243
244 union {
245 const uint8_t *cptr;
246 uint8_t *uptr;
247 } unconst;
Lev Walkinbc0b0c52017-08-02 14:02:48 -0700248
249 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 2", td->name);
250
Lev Walkind88bea92017-07-20 11:21:30 +0300251 unconst.cptr = preamble->buffer;
252 FREEMEM(unconst.uptr);
Lev Walkin1a503892017-08-31 02:15:11 -0700253 preamble->buffer = 0; /* Will do extensions_present==1 next time. */
Lev Walkind88bea92017-07-20 11:21:30 +0300254
255 if(!extensions_present) {
256 ctx->phase = 10;
257 RETURN(RC_OK);
258 }
259
260 /*
261 * X.696 (08/2015) #16.1 (c), #16.4
262 * Read in the extension addition presence bitmap.
263 */
264
265 len_len = oer_fetch_length(ptr, size, &len);
266 if(len_len > 0) {
267 ADVANCE(len_len);
268 } if(len_len < 0) {
269 RETURN(RC_FAIL);
270 } else {
271 RETURN(RC_WMORE);
272 }
273
274 if(len == 0) {
275 /* 16.4.1-2 */
276 RETURN(RC_FAIL);
277 } else if(len > size) {
278 RETURN(RC_WMORE);
279 }
280
281 /* Account for unused bits */
282 unused_bits = 0x7 & *(const uint8_t *)ptr;
283 ADVANCE(1);
284 len--;
285 if(unused_bits && len == 0) {
286 RETURN(RC_FAIL);
287 }
288
289 /* Get the extensions map */
290 ebytes = MALLOC(len + 1);
291 if(!ebytes) {
292 RETURN(RC_FAIL);
293 }
294 memcpy(ebytes, ptr, len);
295 ebytes[len] = '\0';
296
297 extadds = preamble;
298 memset(extadds, 0, sizeof(*extadds));
299 extadds->buffer = ebytes;
300 extadds->nboff = 0;
301 extadds->nbits = 8 * len - unused_bits;
302
303 ADVANCE(len);
304 }
305 NEXT_PHASE(ctx);
306 ctx->step = (specs->ext_after + 1);
307 /* Fall through */
308 case 3:
Lev Walkin890e6032017-07-24 01:48:59 +0400309 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 3", td->name);
310 for(; ctx->step < specs->ext_before - 1; ctx->step++) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700311 asn_bit_data_t *extadds = ctx->ptr;
Lev Walkind88bea92017-07-20 11:21:30 +0300312 size_t edx = ctx->step;
313 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkincfc16d32017-08-30 19:15:08 -0700314 void **memb_ptr2 = element_ptrptr(st, elm, 0);
Lev Walkind88bea92017-07-20 11:21:30 +0300315
Lev Walkin6cd0d562017-08-25 11:57:01 -0700316 switch(asn_get_few_bits(extadds, 1)) {
Lev Walkind88bea92017-07-20 11:21:30 +0300317 case -1:
318 /*
319 * Not every one of our extensions is known to the remote side.
320 * Continue filling in their defaults though.
321 */
322 /* Fall through */
323 case 0:
324 /* Fill-in DEFAULT */
325 if(elm->default_value && elm->default_value(1, memb_ptr2)) {
326 RETURN(RC_FAIL);
327 }
328 continue;
329 case 1: {
330 /* Read OER open type */
331 ssize_t ot_size = oer_open_type_get(opt_codec_ctx, elm->type,
Lev Walkina5972be2017-09-29 23:15:58 -0700332 elm->encoding_constraints.oer_constraints,
Lev Walkind88bea92017-07-20 11:21:30 +0300333 memb_ptr2, ptr, size);
334 if(ot_size > 0) {
335 ADVANCE(ot_size);
336 } else if(ot_size < 0) {
337 RETURN(RC_FAIL);
338 } else {
339 /* Roll back open type parsing */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700340 asn_get_undo(extadds, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300341 ASN_STRUCT_FREE(*elm->type, *memb_ptr2);
342 *memb_ptr2 = NULL;
343 RETURN(RC_WMORE);
344 }
345 break;
346 }
347 default:
348 RETURN(RC_FAIL);
349 }
350 }
351
352 NEXT_PHASE(ctx);
353 /* Fall through */
354 case 4:
Lev Walkin890e6032017-07-24 01:48:59 +0400355 ASN_DEBUG("OER SEQUENCE %s Decoding PHASE 4", td->name);
Lev Walkind88bea92017-07-20 11:21:30 +0300356 /* Read in the rest of Open Types while ignoring them */
357 for(;;) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700358 asn_bit_data_t *extadds = ctx->ptr;
359 switch(asn_get_few_bits(extadds, 1)) {
Lev Walkind88bea92017-07-20 11:21:30 +0300360 case 0:
361 continue;
362 case 1: {
Lev Walkin51a1f3f2017-07-20 14:52:25 +0300363 ssize_t skipped = oer_open_type_skip(ptr, size);
364 if(skipped > 0) {
365 ADVANCE(skipped);
366 } else if(skipped < 0) {
Lev Walkind88bea92017-07-20 11:21:30 +0300367 RETURN(RC_FAIL);
368 } else {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700369 asn_get_undo(extadds, 1);
Lev Walkind88bea92017-07-20 11:21:30 +0300370 RETURN(RC_WMORE);
371 }
372 continue;
373 }
374 case -1:
375 /* No more Open Type encoded components */
376 break;
377 default:
378 RETURN(RC_FAIL);
379 }
380 break;
381 }
382 }
383
384 return rval;
385}
386
387/*
388 * Encode as Canonical OER.
389 */
390asn_enc_rval_t
391SEQUENCE_encode_oer(asn_TYPE_descriptor_t *td,
Lev Walkin494fb702017-08-07 20:07:00 -0700392 const asn_oer_constraints_t *constraints, void *sptr,
393 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkind84f6032017-10-03 16:33:59 -0700394 const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;
Lev Walkin890e6032017-07-24 01:48:59 +0400395 size_t computed_size = 0;
396 int has_extensions_bit = (specs->ext_before >= 0);
397 size_t preamble_bits = (has_extensions_bit + specs->roms_count);
398 uint32_t has_extensions = 0;
399 size_t edx;
400 int ret;
Lev Walkind88bea92017-07-20 11:21:30 +0300401
Lev Walkin494fb702017-08-07 20:07:00 -0700402 (void)constraints;
403
Lev Walkin890e6032017-07-24 01:48:59 +0400404 if(preamble_bits) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700405 asn_bit_outp_t preamble;
Lev Walkind88bea92017-07-20 11:21:30 +0300406
Lev Walkin890e6032017-07-24 01:48:59 +0400407 memset(&preamble, 0, sizeof(preamble));
Lev Walkin6cd0d562017-08-25 11:57:01 -0700408 preamble.output = cb;
Lev Walkin890e6032017-07-24 01:48:59 +0400409 preamble.op_key = app_key;
410
411 if(has_extensions_bit) {
Lev Walkin494fb702017-08-07 20:07:00 -0700412 for(edx = specs->ext_after + 1;
413 (ssize_t)edx < specs->ext_before - 1; edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400414 asn_TYPE_member_t *elm = &td->elements[edx];
Lev Walkin09bec462017-08-31 01:31:43 -0700415 void *memb_ptr = element_ptr(sptr, elm);
416 if(memb_ptr) {
417 if(elm->default_value
418 && elm->default_value(0, &memb_ptr) == 1) {
419 /* Do not encode default values in extensions */
420 } else {
421 has_extensions = 1;
422 break;
423 }
Lev Walkin890e6032017-07-24 01:48:59 +0400424 }
425 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700426 ret = asn_put_few_bits(&preamble, has_extensions, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400427 assert(ret == 0);
428 if(ret < 0) {
429 ASN__ENCODE_FAILED;
430 }
431 }
432
433 /*
434 * Encode optional components bitmap.
435 */
436 if(specs->roms_count) {
437 for(edx = 0; edx < td->elements_count; edx++) {
438 asn_TYPE_member_t *elm = &td->elements[edx];
439
440 if(IN_EXTENSION_GROUP(specs, edx)) break;
441
442 if(elm->optional) {
Lev Walkin09bec462017-08-31 01:31:43 -0700443 void *memb_ptr = element_ptr(sptr, elm);
444 uint32_t has_component = memb_ptr != NULL;
445 if(has_component && elm->default_value
446 && elm->default_value(0, &memb_ptr) == 1) {
447 has_component = 0;
448 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700449 ret = asn_put_few_bits(&preamble, has_component, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400450 if(ret < 0) {
451 ASN__ENCODE_FAILED;
452 }
453 }
454 }
455 }
456
Lev Walkin6cd0d562017-08-25 11:57:01 -0700457 asn_put_aligned_flush(&preamble);
Lev Walkin890e6032017-07-24 01:48:59 +0400458 computed_size += preamble.flushed_bytes;
459 } /* if(preamble_bits) */
460
461 /*
462 * Put root components and extensions root.
463 */
464 for(edx = 0; edx < td->elements_count; edx++) {
465 asn_TYPE_member_t *elm = &td->elements[edx];
466 asn_enc_rval_t er;
467 void *memb_ptr;
468
469 if(IN_EXTENSION_GROUP(specs, edx)) break;
470
471 memb_ptr = element_ptr(sptr, elm);
Lev Walkin09bec462017-08-31 01:31:43 -0700472 if(memb_ptr) {
473 if(elm->default_value && elm->default_value(0, &memb_ptr) == 1) {
474 /* Skip default values in encoding */
475 continue;
476 }
477 } else {
Lev Walkin890e6032017-07-24 01:48:59 +0400478 if(elm->optional) continue;
479 /* Mandatory element is missing */
480 ASN__ENCODE_FAILED;
481 }
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +0800482 if(!elm->type->op->oer_encoder) {
Lev Walkin890e6032017-07-24 01:48:59 +0400483 ASN_DEBUG("OER encoder is not defined for type %s", elm->type->name);
484 ASN__ENCODE_FAILED;
485 }
Lev Walkina5972be2017-09-29 23:15:58 -0700486 er = elm->type->op->oer_encoder(
487 elm->type, elm->encoding_constraints.oer_constraints, memb_ptr, cb,
488 app_key);
Lev Walkin890e6032017-07-24 01:48:59 +0400489 if(er.encoded == -1) {
490 ASN_DEBUG("... while encoding %s member \"%s\"\n", td->name,
491 elm->name);
492 return er;
493 }
494 computed_size += er.encoded;
495 }
496
497 /*
498 * Before encode extensions, encode extensions additions presense bitmap
499 # X.696 (08/2015) #16.4.
500 */
501 if(has_extensions) {
Lev Walkin6cd0d562017-08-25 11:57:01 -0700502 asn_bit_outp_t extadds;
Lev Walkin890e6032017-07-24 01:48:59 +0400503
504 /* Special case allowing us to use exactly one byte for #8.6 */
505 size_t aoms_length_bits = specs->aoms_count;
Lev Walkin09bec462017-08-31 01:31:43 -0700506 size_t aoms_length_bytes = (7 + aoms_length_bits) >> 3;
Lev Walkin890e6032017-07-24 01:48:59 +0400507 uint8_t unused_bits = 0x07 & (8 - (aoms_length_bits & 0x07));
508
509 assert(1 + aoms_length_bytes <= 127);
510
511 memset(&extadds, 0, sizeof(extadds));
Lev Walkin6cd0d562017-08-25 11:57:01 -0700512 extadds.output = cb;
Lev Walkin890e6032017-07-24 01:48:59 +0400513 extadds.op_key = app_key;
514
515 /* #8.6 length determinant */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700516 ret = asn_put_few_bits(&extadds, (1 + aoms_length_bytes), 8);
Lev Walkin890e6032017-07-24 01:48:59 +0400517 if(ret < 0) ASN__ENCODE_FAILED;
518
519 /* Number of unused bytes, #16.4.2 */
Lev Walkin6cd0d562017-08-25 11:57:01 -0700520 ret = asn_put_few_bits(&extadds, unused_bits, 8);
Lev Walkin890e6032017-07-24 01:48:59 +0400521 if(ret < 0) ASN__ENCODE_FAILED;
522
523 /* Encode presence bitmap #16.4.3 */
Lev Walkin494fb702017-08-07 20:07:00 -0700524 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
525 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400526 asn_TYPE_member_t *elm = &td->elements[edx];
527 void *memb_ptr = element_ptr(sptr, elm);
Lev Walkin09bec462017-08-31 01:31:43 -0700528 if(memb_ptr && elm->default_value
529 && elm->default_value(0, &memb_ptr) == 1) {
530 memb_ptr = 0; /* Do not encode default value. */
531 }
Lev Walkin6cd0d562017-08-25 11:57:01 -0700532 ret |= asn_put_few_bits(&extadds, memb_ptr ? 1 : 0, 1);
Lev Walkin890e6032017-07-24 01:48:59 +0400533 }
534 if(ret < 0) ASN__ENCODE_FAILED;
535
Lev Walkin6cd0d562017-08-25 11:57:01 -0700536 asn_put_aligned_flush(&extadds);
Lev Walkin890e6032017-07-24 01:48:59 +0400537 computed_size += extadds.flushed_bytes;
538
539 /* Now, encode extensions */
Lev Walkin494fb702017-08-07 20:07:00 -0700540 for(edx = specs->ext_after + 1; (ssize_t)edx < specs->ext_before - 1;
541 edx++) {
Lev Walkin890e6032017-07-24 01:48:59 +0400542 asn_TYPE_member_t *elm = &td->elements[edx];
543 void *memb_ptr = element_ptr(sptr, elm);
544
545 if(memb_ptr) {
Lev Walkin09bec462017-08-31 01:31:43 -0700546 if(elm->default_value
547 && elm->default_value(0, &memb_ptr) == 1) {
548 /* Do not encode default value. */
549 } else {
550 asn_enc_rval_t er = elm->type->op->oer_encoder(
Lev Walkina5972be2017-09-29 23:15:58 -0700551 elm->type, elm->encoding_constraints.oer_constraints,
552 memb_ptr, cb, app_key);
Lev Walkin09bec462017-08-31 01:31:43 -0700553 if(er.encoded == -1) {
554 return er;
555 }
556 computed_size += er.encoded;
Lev Walkin890e6032017-07-24 01:48:59 +0400557 }
Lev Walkin890e6032017-07-24 01:48:59 +0400558 } else if(!elm->optional) {
559 ASN__ENCODE_FAILED;
560 }
561 }
562 } /* if(has_extensions) */
563
564
565 {
566 asn_enc_rval_t er = {0, 0, 0};
567 er.encoded = computed_size;
568 ASN__ENCODED_OK(er);
569 }
Lev Walkind88bea92017-07-20 11:21:30 +0300570}
571
572#endif /* ASN_DISABLE_OER_SUPPORT */