2 * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
5 #include <asn_internal.h>
6 #include <per_support.h>
7 #include <constr_TYPE.h>
8 #include <per_opentype.h>
10 typedef struct uper_ugot_key {
11 asn_per_data_t oldpd; /* Old per data source */
13 size_t ot_moved; /* Number of bits moved by OT processing */
17 static int uper_ugot_refill(asn_per_data_t *pd);
18 static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
19 static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *,
20 const asn_TYPE_descriptor_t *td,
21 const asn_per_constraints_t *constraints,
22 void **sptr, asn_per_data_t *pd);
25 * Encode an "open type field".
29 uper_open_type_put(const asn_TYPE_descriptor_t *td,
30 const asn_per_constraints_t *constraints, const void *sptr,
36 ASN_DEBUG("Open type put %s ...", td->name);
38 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
39 if(size <= 0) return -1;
41 ASN_DEBUG("Open type put %s of length %" ASN_PRI_SSIZE " + overhead (1byte?)", td->name,
47 ssize_t may_save = uper_put_length(po, size, &need_eom);
48 ASN_DEBUG("Prepending length %" ASN_PRI_SSIZE
49 " to %s and allowing to save %" ASN_PRI_SSIZE,
50 size, td->name, may_save);
51 if(may_save < 0) break;
52 if(per_put_many_bits(po, bptr, may_save * 8)) break;
53 bptr = (char *)bptr + may_save;
55 if(need_eom && uper_put_length(po, 0, 0)) {
68 uper_open_type_get_simple(const asn_codec_ctx_t *ctx,
69 const asn_TYPE_descriptor_t *td,
70 const asn_per_constraints_t *constraints, void **sptr,
81 ASN__STACK_OVERFLOW_CHECK(ctx);
83 ASN_DEBUG("Getting open type %s...", td->name);
86 chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
91 if(bufLen + chunk_bytes > bufSize) {
93 bufSize = chunk_bytes + (bufSize << 2);
94 ptr = REALLOC(buf, bufSize);
101 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
105 bufLen += chunk_bytes;
108 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
111 memset(&spd, 0, sizeof(spd));
113 spd.nbits = bufLen << 3;
115 ASN_DEBUG_INDENT_ADD(+4);
116 rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
117 ASN_DEBUG_INDENT_ADD(-4);
119 if(rv.code == RC_OK) {
120 /* Check padding validity */
121 padding = spd.nbits - spd.nboff;
122 if (((padding > 0 && padding < 8) ||
124 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
125 per_get_few_bits(&spd, padding) == 0) {
126 /* Everything is cool */
132 ASN_DEBUG("Too large padding %d in open type", (int)padding);
135 ASN_DEBUG("No padding");
139 /* rv.code could be RC_WMORE, nonsense in this context */
140 rv.code = RC_FAIL; /* Noone would give us more */
146 static asn_dec_rval_t CC_NOTUSED
147 uper_open_type_get_complex(const asn_codec_ctx_t *ctx,
148 const asn_TYPE_descriptor_t *td,
149 asn_per_constraints_t *constraints, void **sptr,
150 asn_per_data_t *pd) {
155 ASN__STACK_OVERFLOW_CHECK(ctx);
157 ASN_DEBUG("Getting open type %s from %s", td->name,
158 asn_bit_data_string(pd));
163 pd->refill = uper_ugot_refill;
164 pd->refill_key = &arg;
165 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
166 pd->moved = 0; /* This now counts the open type size in bits */
168 ASN_DEBUG_INDENT_ADD(+4);
169 rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
170 ASN_DEBUG_INDENT_ADD(-4);
172 #define UPDRESTOREPD do { \
173 /* buffer and nboff are valid, preserve them. */ \
174 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
175 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
176 pd->refill = arg.oldpd.refill; \
177 pd->refill_key = arg.oldpd.refill_key; \
180 if(rv.code != RC_OK) {
185 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
186 asn_bit_data_string(pd),
187 asn_bit_data_string(&arg.oldpd),
188 (int)arg.unclaimed, (int)arg.repeat);
190 padding = pd->moved % 8;
194 ASN_DEBUG("Too large padding %d in open type",
200 padding = 8 - padding;
201 ASN_DEBUG("Getting padding of %d bits", (int)padding);
202 pvalue = per_get_few_bits(pd, padding);
205 ASN_DEBUG("Padding skip failed");
210 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
211 (int)padding, (int)pvalue);
216 if(pd->nboff != pd->nbits) {
217 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
218 asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
223 arg.unclaimed += pd->nbits - pd->nboff;
227 /* Adjust pd back so it points to original data */
230 /* Skip data not consumed by the decoder */
232 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
233 switch(per_skip_bits(pd, arg.unclaimed)) {
235 ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
238 ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
241 /* Padding must be blank */
242 ASN_DEBUG("Non-blank unconsumed padding");
249 ASN_DEBUG("Not consumed the whole thing");
259 uper_open_type_get(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
260 const asn_per_constraints_t *constraints, void **sptr,
261 asn_per_data_t *pd) {
262 return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
266 uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
267 asn_TYPE_descriptor_t s_td;
268 asn_TYPE_operation_t s_op;
271 s_td.name = "<unknown extension>";
273 s_op.uper_decoder = uper_sot_suck;
275 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
283 * Internal functions.
286 static asn_dec_rval_t
287 uper_sot_suck(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
288 const asn_per_constraints_t *constraints, void **sptr,
289 asn_per_data_t *pd) {
297 while(per_get_few_bits(pd, 1) >= 0);
300 rv.consumed = pd->moved;
306 uper_ugot_refill(asn_per_data_t *pd) {
307 uper_ugot_key *arg = pd->refill_key;
308 ssize_t next_chunk_bytes, next_chunk_bits;
311 asn_per_data_t *oldpd = &arg->oldpd;
313 ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
314 (long)pd->moved, (long)oldpd->moved);
316 /* Advance our position to where pd is */
317 oldpd->buffer = pd->buffer;
318 oldpd->nboff = pd->nboff;
319 oldpd->nbits -= pd->moved - arg->ot_moved;
320 oldpd->moved += pd->moved - arg->ot_moved;
321 arg->ot_moved = pd->moved;
324 /* Refill the container */
325 if(per_get_few_bits(oldpd, 1))
327 if(oldpd->nboff == 0) {
331 pd->buffer = oldpd->buffer;
332 pd->nboff = oldpd->nboff - 1;
333 pd->nbits = oldpd->nbits;
334 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
340 ASN_DEBUG("Want more but refill doesn't have it");
344 next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
345 ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
346 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
347 if(next_chunk_bytes < 0) return -1;
348 if(next_chunk_bytes == 0) {
349 pd->refill = 0; /* No more refills, naturally */
350 assert(!arg->repeat); /* Implementation guarantee */
352 next_chunk_bits = next_chunk_bytes << 3;
353 avail = oldpd->nbits - oldpd->nboff;
354 if(avail >= next_chunk_bits) {
355 pd->nbits = oldpd->nboff + next_chunk_bits;
357 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
358 (long)next_chunk_bits, (long)oldpd->moved,
359 (long)oldpd->nboff, (long)oldpd->nbits,
360 (long)(oldpd->nbits - oldpd->nboff));
362 pd->nbits = oldpd->nbits;
363 arg->unclaimed = next_chunk_bits - avail;
364 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
365 (long)avail, (long)next_chunk_bits,
366 (long)arg->unclaimed);
368 pd->buffer = oldpd->buffer;
369 pd->nboff = oldpd->nboff;
370 ASN_DEBUG("Refilled pd%s old%s",
371 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
376 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
377 int hasNonZeroBits = 0;
378 while(skip_nbits > 0) {
381 /* per_get_few_bits() is more efficient when nbits <= 24 */
388 switch(per_get_few_bits(pd, skip)) {
389 case -1: return -1; /* Starving */
390 case 0: continue; /* Skipped empty space */
391 default: hasNonZeroBits = 1; continue;
394 return hasNonZeroBits;
397 static asn_dec_rval_t
398 aper_open_type_get_simple(const asn_codec_ctx_t *ctx,
399 const asn_TYPE_descriptor_t *td,
400 const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
410 ASN__STACK_OVERFLOW_CHECK(ctx);
412 ASN_DEBUG("Getting open type %s...", td->name);
415 chunk_bytes = aper_get_length(pd, -1, -1, &repeat);
416 if(chunk_bytes < 0) {
420 if(bufLen + chunk_bytes > bufSize) {
422 bufSize = chunk_bytes + (bufSize << 2);
423 ptr = REALLOC(buf, bufSize);
430 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
434 bufLen += chunk_bytes;
437 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
440 memset(&spd, 0, sizeof(spd));
442 spd.nbits = bufLen << 3;
444 ASN_DEBUG_INDENT_ADD(+4);
445 rv = td->op->aper_decoder(ctx, td, constraints, sptr, &spd);
446 ASN_DEBUG_INDENT_ADD(-4);
448 if(rv.code == RC_OK) {
449 /* Check padding validity */
450 padding = spd.nbits - spd.nboff;
451 if (((padding > 0 && padding < 8) ||
453 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
454 per_get_few_bits(&spd, padding) == 0) {
455 /* Everything is cool */
461 ASN_DEBUG("Too large padding %d in open type", (int)padding);
464 ASN_DEBUG("No padding");
468 /* rv.code could be RC_WMORE, nonsense in this context */
469 rv.code = RC_FAIL; /* Noone would give us more */
476 aper_open_type_put(const asn_TYPE_descriptor_t *td,
477 const asn_per_constraints_t *constraints,
478 const void *sptr, asn_per_outp_t *po) {
484 ASN_DEBUG("Open type put %s ...", td->name);
486 size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
487 if(size <= 0) return -1;
489 for(bptr = buf, toGo = size; toGo;) {
490 ssize_t maySave = aper_put_length(po, -1, toGo);
491 if(maySave < 0) break;
492 if(per_put_many_bits(po, bptr, maySave * 8)) break;
493 bptr = (char *)bptr + maySave;
500 ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
507 aper_open_type_get(const asn_codec_ctx_t *ctx,
508 const asn_TYPE_descriptor_t *td,
509 const asn_per_constraints_t *constraints,
510 void **sptr, asn_per_data_t *pd) {
512 return aper_open_type_get_simple(ctx, td, constraints, sptr, pd);
516 aper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
517 asn_TYPE_descriptor_t s_td;
519 asn_TYPE_operation_t op_t;
521 memset(&op_t, 0, sizeof(op_t));
522 s_td.name = "<unknown extension>";
524 s_td.op->aper_decoder = uper_sot_suck;
526 rv = aper_open_type_get(ctx, &s_td, 0, 0, pd);