blob: 25c6d711eda52d63f381a024215f3bee944848a1 [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);
vlm39422fb2007-06-29 11:25:49 +0000124 }
125
vlmb08408b2007-06-29 02:28:50 +0000126 return rv;
127}
128
129static asn_dec_rval_t GCC_NOTUSED
130uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
vlm5d3db2f2007-06-27 04:09:37 +0000131 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
132 uper_ugot_key arg;
133 asn_dec_rval_t rv;
134 ssize_t padding;
135
vlmb08408b2007-06-29 02:28:50 +0000136 _ASN_STACK_OVERFLOW_CHECK(ctx);
vlm5d3db2f2007-06-27 04:09:37 +0000137
vlmb08408b2007-06-29 02:28:50 +0000138 ASN_DEBUG("Getting open type %s from %s", td->name,
139 per_data_string(pd));
vlm5d3db2f2007-06-27 04:09:37 +0000140 arg.oldpd = *pd;
141 arg.unclaimed = 0;
142 arg.ot_moved = 0;
143 arg.repeat = 1;
144 pd->refill = uper_ugot_refill;
145 pd->refill_key = &arg;
146 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
147 pd->moved = 0; /* This now counts the open type size in bits */
148
vlm39422fb2007-06-29 11:25:49 +0000149 asn_debug_indent += 4;
vlmb08408b2007-06-29 02:28:50 +0000150 rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
vlm39422fb2007-06-29 11:25:49 +0000151 asn_debug_indent -= 4;
vlm5d3db2f2007-06-27 04:09:37 +0000152
vlmb08408b2007-06-29 02:28:50 +0000153#define UPDRESTOREPD do { \
154 /* buffer and nboff are valid, preserve them. */ \
155 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
156 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
157 pd->refill = arg.oldpd.refill; \
158 pd->refill_key = arg.oldpd.refill_key; \
159 } while(0)
160
161 if(rv.code != RC_OK) {
162 UPDRESTOREPD;
163 return rv;
164 }
165
166 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d"
167 , td->name,
168 per_data_string(pd),
169 per_data_string(&arg.oldpd),
vlm5d3db2f2007-06-27 04:09:37 +0000170 arg.unclaimed, arg.repeat);
171
vlm5d3db2f2007-06-27 04:09:37 +0000172 padding = pd->moved % 8;
173 if(padding) {
174 int32_t pvalue;
175 if(padding > 7) {
176 ASN_DEBUG("Too large padding %d in open type",
177 padding);
178 rv.code = RC_FAIL;
vlmb08408b2007-06-29 02:28:50 +0000179 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000180 return rv;
181 }
182 padding = 8 - padding;
183 ASN_DEBUG("Getting padding of %d bits", padding);
184 pvalue = per_get_few_bits(pd, padding);
185 switch(pvalue) {
186 case -1:
187 ASN_DEBUG("Padding skip failed");
vlmb08408b2007-06-29 02:28:50 +0000188 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000189 _ASN_DECODE_STARVED;
190 case 0: break;
191 default:
192 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
vlm3dc56b92007-06-29 16:01:51 +0000193 padding, (int)pvalue);
vlmb08408b2007-06-29 02:28:50 +0000194 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000195 _ASN_DECODE_FAILED;
196 }
197 }
vlmb08408b2007-06-29 02:28:50 +0000198 if(pd->nboff != pd->nbits) {
199 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
200 per_data_string(pd), per_data_string(&arg.oldpd));
201 if(1) {
202 UPDRESTOREPD;
203 _ASN_DECODE_FAILED;
204 } else {
205 arg.unclaimed += pd->nbits - pd->nboff;
206 }
vlm5d3db2f2007-06-27 04:09:37 +0000207 }
208
209 /* Adjust pd back so it points to original data */
vlmb08408b2007-06-29 02:28:50 +0000210 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000211
212 /* Skip data not consumed by the decoder */
213 if(arg.unclaimed) ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
vlmb08408b2007-06-29 02:28:50 +0000214 if(arg.unclaimed) {
215 switch(per_skip_bits(pd, arg.unclaimed)) {
vlm5d3db2f2007-06-27 04:09:37 +0000216 case -1:
vlmb08408b2007-06-29 02:28:50 +0000217 ASN_DEBUG("Claim of %d failed", arg.unclaimed);
vlm5d3db2f2007-06-27 04:09:37 +0000218 _ASN_DECODE_STARVED;
219 case 0:
vlmb08408b2007-06-29 02:28:50 +0000220 ASN_DEBUG("Got claim of %d", arg.unclaimed);
221 break;
vlm5d3db2f2007-06-27 04:09:37 +0000222 default:
223 /* Padding must be blank */
224 ASN_DEBUG("Non-blank unconsumed padding");
225 _ASN_DECODE_FAILED;
226 }
vlmb08408b2007-06-29 02:28:50 +0000227 arg.unclaimed = 0;
vlm5d3db2f2007-06-27 04:09:37 +0000228 }
229
vlm5d3db2f2007-06-27 04:09:37 +0000230 if(arg.repeat) {
231 ASN_DEBUG("Not consumed the whole thing");
232 rv.code = RC_FAIL;
233 return rv;
234 }
235
236 return rv;
237}
238
vlmb08408b2007-06-29 02:28:50 +0000239
240asn_dec_rval_t
241uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
242 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
243
244 return uper_open_type_get_simple(ctx, td, constraints,
245 sptr, pd);
246
247}
248
vlm5d3db2f2007-06-27 04:09:37 +0000249int
vlmb08408b2007-06-29 02:28:50 +0000250uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
vlm5d3db2f2007-06-27 04:09:37 +0000251 asn_TYPE_descriptor_t s_td;
252 asn_dec_rval_t rv;
253
254 s_td.name = "<unknown extension>";
255 s_td.uper_decoder = uper_sot_suck;
256
vlmb08408b2007-06-29 02:28:50 +0000257 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
vlm5d3db2f2007-06-27 04:09:37 +0000258 if(rv.code != RC_OK)
259 return -1;
260 else
261 return 0;
262}
263
264/*
265 * Internal functions.
266 */
267
268static asn_dec_rval_t
vlmb08408b2007-06-29 02:28:50 +0000269uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
vlm5d3db2f2007-06-27 04:09:37 +0000270 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
271 asn_dec_rval_t rv;
272
vlmb08408b2007-06-29 02:28:50 +0000273 (void)ctx;
vlm5d3db2f2007-06-27 04:09:37 +0000274 (void)td;
275 (void)constraints;
276 (void)sptr;
277
278 while(per_get_few_bits(pd, 24) >= 0);
279
280 rv.code = RC_OK;
281 rv.consumed = pd->moved;
282
283 return rv;
284}
285
286static int
287uper_ugot_refill(asn_per_data_t *pd) {
288 uper_ugot_key *arg = pd->refill_key;
289 ssize_t next_chunk_bytes, next_chunk_bits;
290 ssize_t avail;
291
292 asn_per_data_t *oldpd = &arg->oldpd;
293
vlmb08408b2007-06-29 02:28:50 +0000294 ASN_DEBUG("REFILLING pd->moved=%d, oldpd->moved=%d",
295 pd->moved, oldpd->moved);
vlm5d3db2f2007-06-27 04:09:37 +0000296
297 /* Advance our position to where pd is */
298 oldpd->buffer = pd->buffer;
299 oldpd->nboff = pd->nboff;
300 oldpd->nbits -= pd->moved - arg->ot_moved;
301 oldpd->moved += pd->moved - arg->ot_moved;
302 arg->ot_moved = pd->moved;
303
304 if(arg->unclaimed) {
305 /* Refill the container */
306 if(per_get_few_bits(oldpd, 1))
307 return -1;
308 if(oldpd->nboff == 0) {
309 assert(0);
310 return -1;
311 }
312 pd->buffer = oldpd->buffer;
313 pd->nboff = oldpd->nboff - 1;
314 pd->nbits = oldpd->nbits;
vlmb08408b2007-06-29 02:28:50 +0000315 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%d)", pd->moved);
vlm5d3db2f2007-06-27 04:09:37 +0000316 return 0;
317 }
318
319 if(!arg->repeat) {
320 ASN_DEBUG("Want more but refill doesn't have it");
321 return -1;
322 }
323
324 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
325 ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
326 next_chunk_bytes, oldpd->moved, arg->repeat);
327 if(next_chunk_bytes < 0) return -1;
328 if(next_chunk_bytes == 0) {
329 pd->refill = 0; /* No more refills, naturally */
330 assert(!arg->repeat); /* Implementation guarantee */
331 }
332 next_chunk_bits = next_chunk_bytes << 3;
333 avail = oldpd->nbits - oldpd->nboff;
334 if(avail >= next_chunk_bits) {
335 pd->nbits = oldpd->nboff + next_chunk_bits;
336 arg->unclaimed = 0;
vlmb08408b2007-06-29 02:28:50 +0000337 ASN_DEBUG("!+Parent frame %d bits, alloting %d [%d..%d] (%d)",
338 next_chunk_bits, oldpd->moved,
339 oldpd->nboff, oldpd->nbits,
340 oldpd->nbits - oldpd->nboff);
vlm5d3db2f2007-06-27 04:09:37 +0000341 } else {
342 pd->nbits = oldpd->nbits;
343 arg->unclaimed = next_chunk_bits - avail;
vlmb08408b2007-06-29 02:28:50 +0000344 ASN_DEBUG("!-Parent frame %d, require %d, will claim %d", avail, next_chunk_bits, arg->unclaimed);
vlm5d3db2f2007-06-27 04:09:37 +0000345 }
346 pd->buffer = oldpd->buffer;
347 pd->nboff = oldpd->nboff;
vlmb08408b2007-06-29 02:28:50 +0000348 ASN_DEBUG("Refilled pd%s old%s",
349 per_data_string(pd), per_data_string(oldpd));
vlm5d3db2f2007-06-27 04:09:37 +0000350 return 0;
351}
vlmb08408b2007-06-29 02:28:50 +0000352
353static int
354per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
355 int hasNonZeroBits = 0;
356 while(skip_nbits > 0) {
357 int skip;
358 if(skip_nbits < skip)
359 skip = skip_nbits;
360 else
361 skip = 24;
362 skip_nbits -= skip;
363
364 switch(per_get_few_bits(pd, skip)) {
365 case -1: return -1; /* Starving */
366 case 0: continue; /* Skipped empty space */
367 default: hasNonZeroBits = 1; continue;
368 }
369 }
370 return hasNonZeroBits;
371}