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