blob: c749c8c6c85a50db3bbeadc213c5887295d1c42c [file] [log] [blame]
vlm5d3db2f2007-06-27 04:09:37 +00001/*
2 * Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <asn_internal.h>
6#include <per_support.h>
7#include <constr_TYPE.h>
8#include <per_opentype.h>
9
10typedef struct uper_ugot_key {
11 asn_per_data_t oldpd; /* Old per data source */
12 size_t unclaimed;
13 size_t ot_moved; /* Number of bits moved by OT processing */
14 int repeat;
15} uper_ugot_key;
16
17static int uper_ugot_refill(asn_per_data_t *pd);
vlmb08408b2007-06-29 02:28:50 +000018static int per_skip_bits(asn_per_data_t *pd, int skip_nbits);
19static 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);
vlm5d3db2f2007-06-27 04:09:37 +000020
vlm39422fb2007-06-29 11:25:49 +000021int asn_debug_indent;
22
vlm5d3db2f2007-06-27 04:09:37 +000023/*
vlmb08408b2007-06-29 02:28:50 +000024 * Encode an "open type field".
vlm5d3db2f2007-06-27 04:09:37 +000025 * #10.1, #10.2
26 */
27int
28uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
29 void *buf;
vlmb08408b2007-06-29 02:28:50 +000030 void *bptr;
vlm5d3db2f2007-06-27 04:09:37 +000031 ssize_t size;
vlmb08408b2007-06-29 02:28:50 +000032 size_t toGo;
vlm5d3db2f2007-06-27 04:09:37 +000033
vlmb08408b2007-06-29 02:28:50 +000034 ASN_DEBUG("Open type put %s ...", td->name);
35
vlm5d3db2f2007-06-27 04:09:37 +000036 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
37 if(size <= 0) return -1;
38
vlmb08408b2007-06-29 02:28:50 +000039 for(bptr = buf, toGo = size; toGo;) {
40 ssize_t maySave = uper_put_length(po, toGo);
vlm5d3db2f2007-06-27 04:09:37 +000041 if(maySave < 0) break;
vlmb08408b2007-06-29 02:28:50 +000042 if(per_put_many_bits(po, bptr, maySave * 8)) break;
43 bptr = (char *)bptr + maySave;
44 toGo -= maySave;
vlm5d3db2f2007-06-27 04:09:37 +000045 }
46
vlmb08408b2007-06-29 02:28:50 +000047 FREEMEM(buf);
48 if(toGo) return -1;
49
50 ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)",
51 td->name, size);
vlm5d3db2f2007-06-27 04:09:37 +000052
53 return 0;
54}
55
vlmb08408b2007-06-29 02:28:50 +000056static asn_dec_rval_t
57uper_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) {
59 asn_dec_rval_t rv;
60 ssize_t chunk_bytes;
61 int repeat;
62 uint8_t *buf = 0;
63 size_t bufLen = 0;
64 size_t bufSize = 0;
65 asn_per_data_t spd;
vlm39422fb2007-06-29 11:25:49 +000066 size_t padding;
vlmb08408b2007-06-29 02:28:50 +000067
68 _ASN_STACK_OVERFLOW_CHECK(ctx);
69
vlm36fc7022007-06-29 11:32:25 +000070 ASN_DEBUG("Getting open type %s...", td->name);
vlmb08408b2007-06-29 02:28:50 +000071
72 do {
73 chunk_bytes = uper_get_length(pd, -1, &repeat);
74 if(chunk_bytes < 0) {
75 FREEMEM(buf);
76 _ASN_DECODE_STARVED;
77 }
78 if(bufLen + chunk_bytes > bufSize) {
79 void *ptr;
80 bufSize = chunk_bytes + (bufSize << 2);
81 ptr = REALLOC(buf, bufSize);
82 if(!ptr) {
83 FREEMEM(buf);
84 _ASN_DECODE_FAILED;
85 }
86 buf = ptr;
87 }
88 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
89 FREEMEM(buf);
90 _ASN_DECODE_STARVED;
91 }
92 bufLen += chunk_bytes;
93 } while(repeat);
94
vlm39422fb2007-06-29 11:25:49 +000095 ASN_DEBUG("Getting open type %s encoded in %d bytes", td->name,
96 bufLen);
97
vlmb08408b2007-06-29 02:28:50 +000098 memset(&spd, 0, sizeof(spd));
99 spd.buffer = buf;
100 spd.nbits = bufLen << 3;
101
vlm39422fb2007-06-29 11:25:49 +0000102 asn_debug_indent += 4;
vlmb08408b2007-06-29 02:28:50 +0000103 rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
vlm39422fb2007-06-29 11:25:49 +0000104 asn_debug_indent -= 4;
vlmb08408b2007-06-29 02:28:50 +0000105
vlma0a8e7c2007-06-29 17:33:04 +0000106 if(rv.code == RC_OK) {
107 /* Check padding validity */
108 padding = spd.nbits - spd.nboff;
109 if(padding < 8 && per_get_few_bits(&spd, padding) == 0) {
110 /* Everything is cool */
111 FREEMEM(buf);
112 return rv;
113 }
114 FREEMEM(buf);
115 if(padding >= 8) {
116 ASN_DEBUG("Too large padding %d in open type", padding);
117 _ASN_DECODE_FAILED;
118 } else {
119 ASN_DEBUG("Non-zero padding");
120 _ASN_DECODE_FAILED;
121 }
122 } else {
123 FREEMEM(buf);
vlmce82ea52007-06-29 23:23:05 +0000124 /* rv.code could be RC_WMORE, nonsense in this context */
125 rv.code = RC_FAIL; /* Noone would give us more */
vlm39422fb2007-06-29 11:25:49 +0000126 }
127
vlmb08408b2007-06-29 02:28:50 +0000128 return rv;
129}
130
131static asn_dec_rval_t GCC_NOTUSED
132uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
vlm5d3db2f2007-06-27 04:09:37 +0000133 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
134 uper_ugot_key arg;
135 asn_dec_rval_t rv;
136 ssize_t padding;
137
vlmb08408b2007-06-29 02:28:50 +0000138 _ASN_STACK_OVERFLOW_CHECK(ctx);
vlm5d3db2f2007-06-27 04:09:37 +0000139
vlmb08408b2007-06-29 02:28:50 +0000140 ASN_DEBUG("Getting open type %s from %s", td->name,
141 per_data_string(pd));
vlm5d3db2f2007-06-27 04:09:37 +0000142 arg.oldpd = *pd;
143 arg.unclaimed = 0;
144 arg.ot_moved = 0;
145 arg.repeat = 1;
146 pd->refill = uper_ugot_refill;
147 pd->refill_key = &arg;
148 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
149 pd->moved = 0; /* This now counts the open type size in bits */
150
vlm39422fb2007-06-29 11:25:49 +0000151 asn_debug_indent += 4;
vlmb08408b2007-06-29 02:28:50 +0000152 rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
vlm39422fb2007-06-29 11:25:49 +0000153 asn_debug_indent -= 4;
vlm5d3db2f2007-06-27 04:09:37 +0000154
vlmb08408b2007-06-29 02:28:50 +0000155#define UPDRESTOREPD do { \
156 /* buffer and nboff are valid, preserve them. */ \
157 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
158 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
159 pd->refill = arg.oldpd.refill; \
160 pd->refill_key = arg.oldpd.refill_key; \
161 } while(0)
162
163 if(rv.code != RC_OK) {
164 UPDRESTOREPD;
165 return rv;
166 }
167
168 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d"
169 , td->name,
170 per_data_string(pd),
171 per_data_string(&arg.oldpd),
vlm5d3db2f2007-06-27 04:09:37 +0000172 arg.unclaimed, arg.repeat);
173
vlm5d3db2f2007-06-27 04:09:37 +0000174 padding = pd->moved % 8;
175 if(padding) {
176 int32_t pvalue;
177 if(padding > 7) {
178 ASN_DEBUG("Too large padding %d in open type",
179 padding);
180 rv.code = RC_FAIL;
vlmb08408b2007-06-29 02:28:50 +0000181 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000182 return rv;
183 }
184 padding = 8 - padding;
185 ASN_DEBUG("Getting padding of %d bits", padding);
186 pvalue = per_get_few_bits(pd, padding);
187 switch(pvalue) {
188 case -1:
189 ASN_DEBUG("Padding skip failed");
vlmb08408b2007-06-29 02:28:50 +0000190 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000191 _ASN_DECODE_STARVED;
192 case 0: break;
193 default:
194 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
vlm3dc56b92007-06-29 16:01:51 +0000195 padding, (int)pvalue);
vlmb08408b2007-06-29 02:28:50 +0000196 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000197 _ASN_DECODE_FAILED;
198 }
199 }
vlmb08408b2007-06-29 02:28:50 +0000200 if(pd->nboff != pd->nbits) {
201 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
202 per_data_string(pd), per_data_string(&arg.oldpd));
203 if(1) {
204 UPDRESTOREPD;
205 _ASN_DECODE_FAILED;
206 } else {
207 arg.unclaimed += pd->nbits - pd->nboff;
208 }
vlm5d3db2f2007-06-27 04:09:37 +0000209 }
210
211 /* Adjust pd back so it points to original data */
vlmb08408b2007-06-29 02:28:50 +0000212 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000213
214 /* Skip data not consumed by the decoder */
215 if(arg.unclaimed) ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
vlmb08408b2007-06-29 02:28:50 +0000216 if(arg.unclaimed) {
217 switch(per_skip_bits(pd, arg.unclaimed)) {
vlm5d3db2f2007-06-27 04:09:37 +0000218 case -1:
vlmb08408b2007-06-29 02:28:50 +0000219 ASN_DEBUG("Claim of %d failed", arg.unclaimed);
vlm5d3db2f2007-06-27 04:09:37 +0000220 _ASN_DECODE_STARVED;
221 case 0:
vlmb08408b2007-06-29 02:28:50 +0000222 ASN_DEBUG("Got claim of %d", arg.unclaimed);
223 break;
vlm5d3db2f2007-06-27 04:09:37 +0000224 default:
225 /* Padding must be blank */
226 ASN_DEBUG("Non-blank unconsumed padding");
227 _ASN_DECODE_FAILED;
228 }
vlmb08408b2007-06-29 02:28:50 +0000229 arg.unclaimed = 0;
vlm5d3db2f2007-06-27 04:09:37 +0000230 }
231
vlm5d3db2f2007-06-27 04:09:37 +0000232 if(arg.repeat) {
233 ASN_DEBUG("Not consumed the whole thing");
234 rv.code = RC_FAIL;
235 return rv;
236 }
237
238 return rv;
239}
240
vlmb08408b2007-06-29 02:28:50 +0000241
242asn_dec_rval_t
243uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
244 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
245
246 return uper_open_type_get_simple(ctx, td, constraints,
247 sptr, pd);
248
249}
250
vlm5d3db2f2007-06-27 04:09:37 +0000251int
vlmb08408b2007-06-29 02:28:50 +0000252uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
vlm5d3db2f2007-06-27 04:09:37 +0000253 asn_TYPE_descriptor_t s_td;
254 asn_dec_rval_t rv;
255
256 s_td.name = "<unknown extension>";
257 s_td.uper_decoder = uper_sot_suck;
258
vlmb08408b2007-06-29 02:28:50 +0000259 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
vlm5d3db2f2007-06-27 04:09:37 +0000260 if(rv.code != RC_OK)
261 return -1;
262 else
263 return 0;
264}
265
266/*
267 * Internal functions.
268 */
269
270static asn_dec_rval_t
vlmb08408b2007-06-29 02:28:50 +0000271uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
vlm5d3db2f2007-06-27 04:09:37 +0000272 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
273 asn_dec_rval_t rv;
274
vlmb08408b2007-06-29 02:28:50 +0000275 (void)ctx;
vlm5d3db2f2007-06-27 04:09:37 +0000276 (void)td;
277 (void)constraints;
278 (void)sptr;
279
280 while(per_get_few_bits(pd, 24) >= 0);
281
282 rv.code = RC_OK;
283 rv.consumed = pd->moved;
284
285 return rv;
286}
287
288static int
289uper_ugot_refill(asn_per_data_t *pd) {
290 uper_ugot_key *arg = pd->refill_key;
291 ssize_t next_chunk_bytes, next_chunk_bits;
292 ssize_t avail;
293
294 asn_per_data_t *oldpd = &arg->oldpd;
295
vlmb08408b2007-06-29 02:28:50 +0000296 ASN_DEBUG("REFILLING pd->moved=%d, oldpd->moved=%d",
297 pd->moved, oldpd->moved);
vlm5d3db2f2007-06-27 04:09:37 +0000298
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;
305
306 if(arg->unclaimed) {
307 /* Refill the container */
308 if(per_get_few_bits(oldpd, 1))
309 return -1;
310 if(oldpd->nboff == 0) {
311 assert(0);
312 return -1;
313 }
314 pd->buffer = oldpd->buffer;
315 pd->nboff = oldpd->nboff - 1;
316 pd->nbits = oldpd->nbits;
vlmb08408b2007-06-29 02:28:50 +0000317 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%d)", pd->moved);
vlm5d3db2f2007-06-27 04:09:37 +0000318 return 0;
319 }
320
321 if(!arg->repeat) {
322 ASN_DEBUG("Want more but refill doesn't have it");
323 return -1;
324 }
325
326 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
327 ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
328 next_chunk_bytes, oldpd->moved, arg->repeat);
329 if(next_chunk_bytes < 0) return -1;
330 if(next_chunk_bytes == 0) {
331 pd->refill = 0; /* No more refills, naturally */
332 assert(!arg->repeat); /* Implementation guarantee */
333 }
334 next_chunk_bits = next_chunk_bytes << 3;
335 avail = oldpd->nbits - oldpd->nboff;
336 if(avail >= next_chunk_bits) {
337 pd->nbits = oldpd->nboff + next_chunk_bits;
338 arg->unclaimed = 0;
vlmb08408b2007-06-29 02:28:50 +0000339 ASN_DEBUG("!+Parent frame %d bits, alloting %d [%d..%d] (%d)",
340 next_chunk_bits, oldpd->moved,
341 oldpd->nboff, oldpd->nbits,
342 oldpd->nbits - oldpd->nboff);
vlm5d3db2f2007-06-27 04:09:37 +0000343 } else {
344 pd->nbits = oldpd->nbits;
345 arg->unclaimed = next_chunk_bits - avail;
vlmb08408b2007-06-29 02:28:50 +0000346 ASN_DEBUG("!-Parent frame %d, require %d, will claim %d", avail, next_chunk_bits, arg->unclaimed);
vlm5d3db2f2007-06-27 04:09:37 +0000347 }
348 pd->buffer = oldpd->buffer;
349 pd->nboff = oldpd->nboff;
vlmb08408b2007-06-29 02:28:50 +0000350 ASN_DEBUG("Refilled pd%s old%s",
351 per_data_string(pd), per_data_string(oldpd));
vlm5d3db2f2007-06-27 04:09:37 +0000352 return 0;
353}
vlmb08408b2007-06-29 02:28:50 +0000354
355static int
356per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
357 int hasNonZeroBits = 0;
358 while(skip_nbits > 0) {
359 int skip;
360 if(skip_nbits < skip)
361 skip = skip_nbits;
362 else
363 skip = 24;
364 skip_nbits -= skip;
365
366 switch(per_get_few_bits(pd, skip)) {
367 case -1: return -1; /* Starving */
368 case 0: continue; /* Skipped empty space */
369 default: hasNonZeroBits = 1; continue;
370 }
371 }
372 return hasNonZeroBits;
373}