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(asn_codec_ctx_t *, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
22 * Encode an "open type field".
26 uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
32 ASN_DEBUG("Open type put %s ...", td->name);
34 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
35 if(size <= 0) return -1;
37 for(bptr = buf, toGo = size; toGo;) {
38 ssize_t maySave = uper_put_length(po, toGo);
39 ASN_DEBUG("Prepending length %d to %s and allowing to save %d",
40 (int)size, td->name, (int)maySave);
41 if(maySave < 0) break;
42 if(per_put_many_bits(po, bptr, maySave * 8)) break;
43 bptr = (char *)bptr + maySave;
50 ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
51 td->name, (long)size);
57 uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
58 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
68 ASN__STACK_OVERFLOW_CHECK(ctx);
70 ASN_DEBUG("Getting open type %s...", td->name);
73 chunk_bytes = uper_get_length(pd, -1, &repeat);
78 if(bufLen + chunk_bytes > bufSize) {
80 bufSize = chunk_bytes + (bufSize << 2);
81 ptr = REALLOC(buf, bufSize);
88 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
92 bufLen += chunk_bytes;
95 ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
98 memset(&spd, 0, sizeof(spd));
100 spd.nbits = bufLen << 3;
102 ASN_DEBUG_INDENT_ADD(+4);
103 rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
104 ASN_DEBUG_INDENT_ADD(-4);
106 if(rv.code == RC_OK) {
107 /* Check padding validity */
108 padding = spd.nbits - spd.nboff;
111 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
112 per_get_few_bits(&spd, padding) == 0) {
113 /* Everything is cool */
119 ASN_DEBUG("Too large padding %d in open type", (int)padding);
122 ASN_DEBUG("Non-zero padding");
127 /* rv.code could be RC_WMORE, nonsense in this context */
128 rv.code = RC_FAIL; /* Noone would give us more */
134 static asn_dec_rval_t GCC_NOTUSED
135 uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
136 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
141 ASN__STACK_OVERFLOW_CHECK(ctx);
143 ASN_DEBUG("Getting open type %s from %s", td->name,
144 per_data_string(pd));
149 pd->refill = uper_ugot_refill;
150 pd->refill_key = &arg;
151 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
152 pd->moved = 0; /* This now counts the open type size in bits */
154 ASN_DEBUG_INDENT_ADD(+4);
155 rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
156 ASN_DEBUG_INDENT_ADD(-4);
158 #define UPDRESTOREPD do { \
159 /* buffer and nboff are valid, preserve them. */ \
160 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
161 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
162 pd->refill = arg.oldpd.refill; \
163 pd->refill_key = arg.oldpd.refill_key; \
166 if(rv.code != RC_OK) {
171 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
173 per_data_string(&arg.oldpd),
174 (int)arg.unclaimed, (int)arg.repeat);
176 padding = pd->moved % 8;
180 ASN_DEBUG("Too large padding %d in open type",
186 padding = 8 - padding;
187 ASN_DEBUG("Getting padding of %d bits", (int)padding);
188 pvalue = per_get_few_bits(pd, padding);
191 ASN_DEBUG("Padding skip failed");
196 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
197 (int)padding, (int)pvalue);
202 if(pd->nboff != pd->nbits) {
203 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
204 per_data_string(pd), per_data_string(&arg.oldpd));
209 arg.unclaimed += pd->nbits - pd->nboff;
213 /* Adjust pd back so it points to original data */
216 /* Skip data not consumed by the decoder */
218 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
219 switch(per_skip_bits(pd, arg.unclaimed)) {
221 ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
224 ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
227 /* Padding must be blank */
228 ASN_DEBUG("Non-blank unconsumed padding");
235 ASN_DEBUG("Not consumed the whole thing");
245 uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
246 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
248 return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
252 uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
253 asn_TYPE_descriptor_t s_td;
256 s_td.name = "<unknown extension>";
257 s_td.uper_decoder = uper_sot_suck;
259 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
267 * Internal functions.
270 static asn_dec_rval_t
271 uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
272 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
280 while(per_get_few_bits(pd, 24) >= 0);
283 rv.consumed = pd->moved;
289 uper_ugot_refill(asn_per_data_t *pd) {
290 uper_ugot_key *arg = pd->refill_key;
291 ssize_t next_chunk_bytes, next_chunk_bits;
294 asn_per_data_t *oldpd = &arg->oldpd;
296 ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
297 (long)pd->moved, (long)oldpd->moved);
299 /* Advance our position to where pd is */
300 oldpd->buffer = pd->buffer;
301 oldpd->nboff = pd->nboff;
302 oldpd->nbits -= pd->moved - arg->ot_moved;
303 oldpd->moved += pd->moved - arg->ot_moved;
304 arg->ot_moved = pd->moved;
307 /* Refill the container */
308 if(per_get_few_bits(oldpd, 1))
310 if(oldpd->nboff == 0) {
314 pd->buffer = oldpd->buffer;
315 pd->nboff = oldpd->nboff - 1;
316 pd->nbits = oldpd->nbits;
317 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
323 ASN_DEBUG("Want more but refill doesn't have it");
327 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
328 ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
329 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
330 if(next_chunk_bytes < 0) return -1;
331 if(next_chunk_bytes == 0) {
332 pd->refill = 0; /* No more refills, naturally */
333 assert(!arg->repeat); /* Implementation guarantee */
335 next_chunk_bits = next_chunk_bytes << 3;
336 avail = oldpd->nbits - oldpd->nboff;
337 if(avail >= next_chunk_bits) {
338 pd->nbits = oldpd->nboff + next_chunk_bits;
340 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
341 (long)next_chunk_bits, (long)oldpd->moved,
342 (long)oldpd->nboff, (long)oldpd->nbits,
343 (long)(oldpd->nbits - oldpd->nboff));
345 pd->nbits = oldpd->nbits;
346 arg->unclaimed = next_chunk_bits - avail;
347 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
348 (long)avail, (long)next_chunk_bits,
349 (long)arg->unclaimed);
351 pd->buffer = oldpd->buffer;
352 pd->nboff = oldpd->nboff;
353 ASN_DEBUG("Refilled pd%s old%s",
354 per_data_string(pd), per_data_string(oldpd));
359 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
360 int hasNonZeroBits = 0;
361 while(skip_nbits > 0) {
364 /* per_get_few_bits() is more efficient when nbits <= 24 */
371 switch(per_get_few_bits(pd, skip)) {
372 case -1: return -1; /* Starving */
373 case 0: continue; /* Skipped empty space */
374 default: hasNonZeroBits = 1; continue;
377 return hasNonZeroBits;