1 /*****************************************************************************
3 # Copyright 2019 AT&T Intellectual Property *
5 # Licensed under the Apache License, Version 2.0 (the "License"); *
6 # you may not use this file except in compliance with the License. *
7 # You may obtain a copy of the License at *
9 # http://www.apache.org/licenses/LICENSE-2.0 *
11 # Unless required by applicable law or agreed to in writing, software *
12 # distributed under the License is distributed on an "AS IS" BASIS, *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 # See the License for the specific language governing permissions and *
15 # limitations under the License. *
17 ******************************************************************************/
20 * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
21 * Redistribution and modifications are permitted subject to BSD license.
23 #include <asn_internal.h>
24 #include <per_support.h>
25 #include <constr_TYPE.h>
26 #include <per_opentype.h>
28 typedef struct uper_ugot_key {
29 asn_per_data_t oldpd; /* Old per data source */
31 size_t ot_moved; /* Number of bits moved by OT processing */
35 static int uper_ugot_refill(asn_per_data_t *pd);
36 static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
37 static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *,
38 const asn_TYPE_descriptor_t *td,
39 const asn_per_constraints_t *constraints,
40 void **sptr, asn_per_data_t *pd);
43 * Encode an "open type field".
47 uper_open_type_put(const asn_TYPE_descriptor_t *td,
48 const asn_per_constraints_t *constraints, const void *sptr,
54 ASN_DEBUG("Open type put %s ...", td->name);
56 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
57 if(size <= 0) return -1;
59 ASN_DEBUG("Open type put %s of length %" ASN_PRI_SSIZE " + overhead (1byte?)", td->name,
65 ssize_t may_save = uper_put_length(po, size, &need_eom);
66 ASN_DEBUG("Prepending length %" ASN_PRI_SSIZE
67 " to %s and allowing to save %" ASN_PRI_SSIZE,
68 size, td->name, may_save);
69 if(may_save < 0) break;
70 if(per_put_many_bits(po, bptr, may_save * 8)) break;
71 bptr = (char *)bptr + may_save;
73 if(need_eom && uper_put_length(po, 0, 0)) {
86 uper_open_type_get_simple(const asn_codec_ctx_t *ctx,
87 const asn_TYPE_descriptor_t *td,
88 const asn_per_constraints_t *constraints, void **sptr,
99 ASN__STACK_OVERFLOW_CHECK(ctx);
101 ASN_DEBUG("Getting open type %s...", td->name);
104 chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
105 if(chunk_bytes < 0) {
109 if(bufLen + chunk_bytes > bufSize) {
111 bufSize = chunk_bytes + (bufSize << 2);
112 ptr = REALLOC(buf, bufSize);
119 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
123 bufLen += chunk_bytes;
126 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
129 memset(&spd, 0, sizeof(spd));
131 spd.nbits = bufLen << 3;
133 ASN_DEBUG_INDENT_ADD(+4);
134 rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
135 ASN_DEBUG_INDENT_ADD(-4);
137 if(rv.code == RC_OK) {
138 /* Check padding validity */
139 padding = spd.nbits - spd.nboff;
140 if (((padding > 0 && padding < 8) ||
142 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
143 per_get_few_bits(&spd, padding) == 0) {
144 /* Everything is cool */
150 ASN_DEBUG("Too large padding %d in open type", (int)padding);
153 ASN_DEBUG("No padding");
157 /* rv.code could be RC_WMORE, nonsense in this context */
158 rv.code = RC_FAIL; /* Noone would give us more */
164 static asn_dec_rval_t CC_NOTUSED
165 uper_open_type_get_complex(const asn_codec_ctx_t *ctx,
166 const asn_TYPE_descriptor_t *td,
167 asn_per_constraints_t *constraints, void **sptr,
168 asn_per_data_t *pd) {
173 ASN__STACK_OVERFLOW_CHECK(ctx);
175 ASN_DEBUG("Getting open type %s from %s", td->name,
176 asn_bit_data_string(pd));
181 pd->refill = uper_ugot_refill;
182 pd->refill_key = &arg;
183 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
184 pd->moved = 0; /* This now counts the open type size in bits */
186 ASN_DEBUG_INDENT_ADD(+4);
187 rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
188 ASN_DEBUG_INDENT_ADD(-4);
190 #define UPDRESTOREPD do { \
191 /* buffer and nboff are valid, preserve them. */ \
192 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
193 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
194 pd->refill = arg.oldpd.refill; \
195 pd->refill_key = arg.oldpd.refill_key; \
198 if(rv.code != RC_OK) {
203 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
204 asn_bit_data_string(pd),
205 asn_bit_data_string(&arg.oldpd),
206 (int)arg.unclaimed, (int)arg.repeat);
208 padding = pd->moved % 8;
212 ASN_DEBUG("Too large padding %d in open type",
218 padding = 8 - padding;
219 ASN_DEBUG("Getting padding of %d bits", (int)padding);
220 pvalue = per_get_few_bits(pd, padding);
223 ASN_DEBUG("Padding skip failed");
228 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
229 (int)padding, (int)pvalue);
234 if(pd->nboff != pd->nbits) {
235 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
236 asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
241 arg.unclaimed += pd->nbits - pd->nboff;
245 /* Adjust pd back so it points to original data */
248 /* Skip data not consumed by the decoder */
250 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
251 switch(per_skip_bits(pd, arg.unclaimed)) {
253 ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
256 ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
259 /* Padding must be blank */
260 ASN_DEBUG("Non-blank unconsumed padding");
267 ASN_DEBUG("Not consumed the whole thing");
277 uper_open_type_get(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
278 const asn_per_constraints_t *constraints, void **sptr,
279 asn_per_data_t *pd) {
280 return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
284 uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
285 asn_TYPE_descriptor_t s_td;
286 asn_TYPE_operation_t s_op;
289 s_td.name = "<unknown extension>";
291 s_op.uper_decoder = uper_sot_suck;
293 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
301 * Internal functions.
304 static asn_dec_rval_t
305 uper_sot_suck(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
306 const asn_per_constraints_t *constraints, void **sptr,
307 asn_per_data_t *pd) {
315 while(per_get_few_bits(pd, 1) >= 0);
318 rv.consumed = pd->moved;
324 uper_ugot_refill(asn_per_data_t *pd) {
325 uper_ugot_key *arg = pd->refill_key;
326 ssize_t next_chunk_bytes, next_chunk_bits;
329 asn_per_data_t *oldpd = &arg->oldpd;
331 ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
332 (long)pd->moved, (long)oldpd->moved);
334 /* Advance our position to where pd is */
335 oldpd->buffer = pd->buffer;
336 oldpd->nboff = pd->nboff;
337 oldpd->nbits -= pd->moved - arg->ot_moved;
338 oldpd->moved += pd->moved - arg->ot_moved;
339 arg->ot_moved = pd->moved;
342 /* Refill the container */
343 if(per_get_few_bits(oldpd, 1))
345 if(oldpd->nboff == 0) {
349 pd->buffer = oldpd->buffer;
350 pd->nboff = oldpd->nboff - 1;
351 pd->nbits = oldpd->nbits;
352 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
358 ASN_DEBUG("Want more but refill doesn't have it");
362 next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
363 ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
364 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
365 if(next_chunk_bytes < 0) return -1;
366 if(next_chunk_bytes == 0) {
367 pd->refill = 0; /* No more refills, naturally */
368 assert(!arg->repeat); /* Implementation guarantee */
370 next_chunk_bits = next_chunk_bytes << 3;
371 avail = oldpd->nbits - oldpd->nboff;
372 if(avail >= next_chunk_bits) {
373 pd->nbits = oldpd->nboff + next_chunk_bits;
375 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
376 (long)next_chunk_bits, (long)oldpd->moved,
377 (long)oldpd->nboff, (long)oldpd->nbits,
378 (long)(oldpd->nbits - oldpd->nboff));
380 pd->nbits = oldpd->nbits;
381 arg->unclaimed = next_chunk_bits - avail;
382 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
383 (long)avail, (long)next_chunk_bits,
384 (long)arg->unclaimed);
386 pd->buffer = oldpd->buffer;
387 pd->nboff = oldpd->nboff;
388 ASN_DEBUG("Refilled pd%s old%s",
389 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
394 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
395 int hasNonZeroBits = 0;
396 while(skip_nbits > 0) {
399 /* per_get_few_bits() is more efficient when nbits <= 24 */
406 switch(per_get_few_bits(pd, skip)) {
407 case -1: return -1; /* Starving */
408 case 0: continue; /* Skipped empty space */
409 default: hasNonZeroBits = 1; continue;
412 return hasNonZeroBits;
415 static asn_dec_rval_t
416 aper_open_type_get_simple(const asn_codec_ctx_t *ctx,
417 const asn_TYPE_descriptor_t *td,
418 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
428 ASN__STACK_OVERFLOW_CHECK(ctx);
430 ASN_DEBUG("Getting open type %s...", td->name);
433 chunk_bytes = aper_get_length(pd, -1, -1, &repeat);
434 if(chunk_bytes < 0) {
438 if(bufLen + chunk_bytes > bufSize) {
440 bufSize = chunk_bytes + (bufSize << 2);
441 ptr = REALLOC(buf, bufSize);
448 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
452 bufLen += chunk_bytes;
455 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
458 memset(&spd, 0, sizeof(spd));
460 spd.nbits = bufLen << 3;
462 ASN_DEBUG_INDENT_ADD(+4);
463 rv = td->op->aper_decoder(ctx, td, constraints, sptr, &spd);
464 ASN_DEBUG_INDENT_ADD(-4);
466 if(rv.code == RC_OK) {
467 /* Check padding validity */
468 padding = spd.nbits - spd.nboff;
469 if (((padding > 0 && padding < 8) ||
471 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
472 per_get_few_bits(&spd, padding) == 0) {
473 /* Everything is cool */
479 ASN_DEBUG("Too large padding %d in open type", (int)padding);
482 ASN_DEBUG("No padding");
486 /* rv.code could be RC_WMORE, nonsense in this context */
487 rv.code = RC_FAIL; /* Noone would give us more */
494 aper_open_type_put(const asn_TYPE_descriptor_t *td,
495 const asn_per_constraints_t *constraints,
496 const void *sptr, asn_per_outp_t *po) {
502 ASN_DEBUG("Open type put %s ...", td->name);
504 size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
505 if(size <= 0) return -1;
507 for(bptr = buf, toGo = size; toGo;) {
508 ssize_t maySave = aper_put_length(po, -1, toGo);
509 if(maySave < 0) break;
510 if(per_put_many_bits(po, bptr, maySave * 8)) break;
511 bptr = (char *)bptr + maySave;
518 ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
525 aper_open_type_get(const asn_codec_ctx_t *ctx,
526 const asn_TYPE_descriptor_t *td,
527 const asn_per_constraints_t *constraints,
528 void **sptr, asn_per_data_t *pd) {
530 return aper_open_type_get_simple(ctx, td, constraints, sptr, pd);
534 aper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
535 asn_TYPE_descriptor_t s_td;
537 asn_TYPE_operation_t op_t;
539 memset(&op_t, 0, sizeof(op_t));
540 s_td.name = "<unknown extension>";
542 s_td.op->aper_decoder = uper_sot_suck;
544 rv = aper_open_type_get(ctx, &s_td, 0, 0, pd);