blob: 1c3a49a773b8505922e6c2eda6ca29e8897ccfda [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
21/*
vlmb08408b2007-06-29 02:28:50 +000022 * Encode an "open type field".
vlm5d3db2f2007-06-27 04:09:37 +000023 * #10.1, #10.2
24 */
25int
26uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
27 void *buf;
vlmb08408b2007-06-29 02:28:50 +000028 void *bptr;
vlm5d3db2f2007-06-27 04:09:37 +000029 ssize_t size;
vlmb08408b2007-06-29 02:28:50 +000030 size_t toGo;
vlm5d3db2f2007-06-27 04:09:37 +000031
vlmb08408b2007-06-29 02:28:50 +000032 ASN_DEBUG("Open type put %s ...", td->name);
33
vlm5d3db2f2007-06-27 04:09:37 +000034 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
35 if(size <= 0) return -1;
36
vlmb08408b2007-06-29 02:28:50 +000037 for(bptr = buf, toGo = size; toGo;) {
38 ssize_t maySave = uper_put_length(po, toGo);
vlm5d3db2f2007-06-27 04:09:37 +000039 if(maySave < 0) break;
vlmb08408b2007-06-29 02:28:50 +000040 if(per_put_many_bits(po, bptr, maySave * 8)) break;
41 bptr = (char *)bptr + maySave;
42 toGo -= maySave;
vlm5d3db2f2007-06-27 04:09:37 +000043 }
44
vlmb08408b2007-06-29 02:28:50 +000045 FREEMEM(buf);
46 if(toGo) return -1;
47
48 ASN_DEBUG("Open type put %s of length %d + overhead (1byte?)",
49 td->name, size);
vlm5d3db2f2007-06-27 04:09:37 +000050
51 return 0;
52}
53
vlmb08408b2007-06-29 02:28:50 +000054static asn_dec_rval_t
55uper_open_type_get_simple(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
56 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
57 asn_dec_rval_t rv;
58 ssize_t chunk_bytes;
59 int repeat;
60 uint8_t *buf = 0;
61 size_t bufLen = 0;
62 size_t bufSize = 0;
63 asn_per_data_t spd;
64
65 _ASN_STACK_OVERFLOW_CHECK(ctx);
66
67 ASN_DEBUG("Getting open type %s from %s", td->name,
68 per_data_string(pd));
69
70 do {
71 chunk_bytes = uper_get_length(pd, -1, &repeat);
72 if(chunk_bytes < 0) {
73 FREEMEM(buf);
74 _ASN_DECODE_STARVED;
75 }
76 if(bufLen + chunk_bytes > bufSize) {
77 void *ptr;
78 bufSize = chunk_bytes + (bufSize << 2);
79 ptr = REALLOC(buf, bufSize);
80 if(!ptr) {
81 FREEMEM(buf);
82 _ASN_DECODE_FAILED;
83 }
84 buf = ptr;
85 }
86 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
87 FREEMEM(buf);
88 _ASN_DECODE_STARVED;
89 }
90 bufLen += chunk_bytes;
91 } while(repeat);
92
93 memset(&spd, 0, sizeof(spd));
94 spd.buffer = buf;
95 spd.nbits = bufLen << 3;
96
97 rv = td->uper_decoder(ctx, td, constraints, sptr, &spd);
98
99 FREEMEM(buf);
100
101 return rv;
102}
103
104static asn_dec_rval_t GCC_NOTUSED
105uper_open_type_get_complex(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
vlm5d3db2f2007-06-27 04:09:37 +0000106 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
107 uper_ugot_key arg;
108 asn_dec_rval_t rv;
109 ssize_t padding;
110
vlmb08408b2007-06-29 02:28:50 +0000111 _ASN_STACK_OVERFLOW_CHECK(ctx);
vlm5d3db2f2007-06-27 04:09:37 +0000112
vlmb08408b2007-06-29 02:28:50 +0000113 ASN_DEBUG("Getting open type %s from %s", td->name,
114 per_data_string(pd));
vlm5d3db2f2007-06-27 04:09:37 +0000115 arg.oldpd = *pd;
116 arg.unclaimed = 0;
117 arg.ot_moved = 0;
118 arg.repeat = 1;
119 pd->refill = uper_ugot_refill;
120 pd->refill_key = &arg;
121 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
122 pd->moved = 0; /* This now counts the open type size in bits */
123
vlmb08408b2007-06-29 02:28:50 +0000124 /*asn_debug_indent += 4;*/
125 rv = td->uper_decoder(ctx, td, constraints, sptr, pd);
126 /*asn_debug_indent -= 4;*/
vlm5d3db2f2007-06-27 04:09:37 +0000127
vlmb08408b2007-06-29 02:28:50 +0000128#define UPDRESTOREPD do { \
129 /* buffer and nboff are valid, preserve them. */ \
130 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved); \
131 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved); \
132 pd->refill = arg.oldpd.refill; \
133 pd->refill_key = arg.oldpd.refill_key; \
134 } while(0)
135
136 if(rv.code != RC_OK) {
137 UPDRESTOREPD;
138 return rv;
139 }
140
141 ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d"
142 , td->name,
143 per_data_string(pd),
144 per_data_string(&arg.oldpd),
vlm5d3db2f2007-06-27 04:09:37 +0000145 arg.unclaimed, arg.repeat);
146
vlm5d3db2f2007-06-27 04:09:37 +0000147 padding = pd->moved % 8;
148 if(padding) {
149 int32_t pvalue;
150 if(padding > 7) {
151 ASN_DEBUG("Too large padding %d in open type",
152 padding);
153 rv.code = RC_FAIL;
vlmb08408b2007-06-29 02:28:50 +0000154 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000155 return rv;
156 }
157 padding = 8 - padding;
158 ASN_DEBUG("Getting padding of %d bits", padding);
159 pvalue = per_get_few_bits(pd, padding);
160 switch(pvalue) {
161 case -1:
162 ASN_DEBUG("Padding skip failed");
vlmb08408b2007-06-29 02:28:50 +0000163 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000164 _ASN_DECODE_STARVED;
165 case 0: break;
166 default:
167 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
168 padding, pvalue);
vlmb08408b2007-06-29 02:28:50 +0000169 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000170 _ASN_DECODE_FAILED;
171 }
172 }
vlmb08408b2007-06-29 02:28:50 +0000173 if(pd->nboff != pd->nbits) {
174 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
175 per_data_string(pd), per_data_string(&arg.oldpd));
176 if(1) {
177 UPDRESTOREPD;
178 _ASN_DECODE_FAILED;
179 } else {
180 arg.unclaimed += pd->nbits - pd->nboff;
181 }
vlm5d3db2f2007-06-27 04:09:37 +0000182 }
183
184 /* Adjust pd back so it points to original data */
vlmb08408b2007-06-29 02:28:50 +0000185 UPDRESTOREPD;
vlm5d3db2f2007-06-27 04:09:37 +0000186
187 /* Skip data not consumed by the decoder */
188 if(arg.unclaimed) ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
vlmb08408b2007-06-29 02:28:50 +0000189 if(arg.unclaimed) {
190 switch(per_skip_bits(pd, arg.unclaimed)) {
vlm5d3db2f2007-06-27 04:09:37 +0000191 case -1:
vlmb08408b2007-06-29 02:28:50 +0000192 ASN_DEBUG("Claim of %d failed", arg.unclaimed);
vlm5d3db2f2007-06-27 04:09:37 +0000193 _ASN_DECODE_STARVED;
194 case 0:
vlmb08408b2007-06-29 02:28:50 +0000195 ASN_DEBUG("Got claim of %d", arg.unclaimed);
196 break;
vlm5d3db2f2007-06-27 04:09:37 +0000197 default:
198 /* Padding must be blank */
199 ASN_DEBUG("Non-blank unconsumed padding");
200 _ASN_DECODE_FAILED;
201 }
vlmb08408b2007-06-29 02:28:50 +0000202 arg.unclaimed = 0;
vlm5d3db2f2007-06-27 04:09:37 +0000203 }
204
vlm5d3db2f2007-06-27 04:09:37 +0000205 if(arg.repeat) {
206 ASN_DEBUG("Not consumed the whole thing");
207 rv.code = RC_FAIL;
208 return rv;
209 }
210
211 return rv;
212}
213
vlmb08408b2007-06-29 02:28:50 +0000214
215asn_dec_rval_t
216uper_open_type_get(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
217 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
218
219 return uper_open_type_get_simple(ctx, td, constraints,
220 sptr, pd);
221
222}
223
vlm5d3db2f2007-06-27 04:09:37 +0000224int
vlmb08408b2007-06-29 02:28:50 +0000225uper_open_type_skip(asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
vlm5d3db2f2007-06-27 04:09:37 +0000226 asn_TYPE_descriptor_t s_td;
227 asn_dec_rval_t rv;
228
229 s_td.name = "<unknown extension>";
230 s_td.uper_decoder = uper_sot_suck;
231
vlmb08408b2007-06-29 02:28:50 +0000232 rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
vlm5d3db2f2007-06-27 04:09:37 +0000233 if(rv.code != RC_OK)
234 return -1;
235 else
236 return 0;
237}
238
239/*
240 * Internal functions.
241 */
242
243static asn_dec_rval_t
vlmb08408b2007-06-29 02:28:50 +0000244uper_sot_suck(asn_codec_ctx_t *ctx, asn_TYPE_descriptor_t *td,
vlm5d3db2f2007-06-27 04:09:37 +0000245 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
246 asn_dec_rval_t rv;
247
vlmb08408b2007-06-29 02:28:50 +0000248 (void)ctx;
vlm5d3db2f2007-06-27 04:09:37 +0000249 (void)td;
250 (void)constraints;
251 (void)sptr;
252
253 while(per_get_few_bits(pd, 24) >= 0);
254
255 rv.code = RC_OK;
256 rv.consumed = pd->moved;
257
258 return rv;
259}
260
261static int
262uper_ugot_refill(asn_per_data_t *pd) {
263 uper_ugot_key *arg = pd->refill_key;
264 ssize_t next_chunk_bytes, next_chunk_bits;
265 ssize_t avail;
266
267 asn_per_data_t *oldpd = &arg->oldpd;
268
vlmb08408b2007-06-29 02:28:50 +0000269 ASN_DEBUG("REFILLING pd->moved=%d, oldpd->moved=%d",
270 pd->moved, oldpd->moved);
vlm5d3db2f2007-06-27 04:09:37 +0000271
272 /* Advance our position to where pd is */
273 oldpd->buffer = pd->buffer;
274 oldpd->nboff = pd->nboff;
275 oldpd->nbits -= pd->moved - arg->ot_moved;
276 oldpd->moved += pd->moved - arg->ot_moved;
277 arg->ot_moved = pd->moved;
278
279 if(arg->unclaimed) {
280 /* Refill the container */
281 if(per_get_few_bits(oldpd, 1))
282 return -1;
283 if(oldpd->nboff == 0) {
284 assert(0);
285 return -1;
286 }
287 pd->buffer = oldpd->buffer;
288 pd->nboff = oldpd->nboff - 1;
289 pd->nbits = oldpd->nbits;
vlmb08408b2007-06-29 02:28:50 +0000290 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%d)", pd->moved);
vlm5d3db2f2007-06-27 04:09:37 +0000291 return 0;
292 }
293
294 if(!arg->repeat) {
295 ASN_DEBUG("Want more but refill doesn't have it");
296 return -1;
297 }
298
299 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
300 ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
301 next_chunk_bytes, oldpd->moved, arg->repeat);
302 if(next_chunk_bytes < 0) return -1;
303 if(next_chunk_bytes == 0) {
304 pd->refill = 0; /* No more refills, naturally */
305 assert(!arg->repeat); /* Implementation guarantee */
306 }
307 next_chunk_bits = next_chunk_bytes << 3;
308 avail = oldpd->nbits - oldpd->nboff;
309 if(avail >= next_chunk_bits) {
310 pd->nbits = oldpd->nboff + next_chunk_bits;
311 arg->unclaimed = 0;
vlmb08408b2007-06-29 02:28:50 +0000312 ASN_DEBUG("!+Parent frame %d bits, alloting %d [%d..%d] (%d)",
313 next_chunk_bits, oldpd->moved,
314 oldpd->nboff, oldpd->nbits,
315 oldpd->nbits - oldpd->nboff);
vlm5d3db2f2007-06-27 04:09:37 +0000316 } else {
317 pd->nbits = oldpd->nbits;
318 arg->unclaimed = next_chunk_bits - avail;
vlmb08408b2007-06-29 02:28:50 +0000319 ASN_DEBUG("!-Parent frame %d, require %d, will claim %d", avail, next_chunk_bits, arg->unclaimed);
vlm5d3db2f2007-06-27 04:09:37 +0000320 }
321 pd->buffer = oldpd->buffer;
322 pd->nboff = oldpd->nboff;
vlmb08408b2007-06-29 02:28:50 +0000323 ASN_DEBUG("Refilled pd%s old%s",
324 per_data_string(pd), per_data_string(oldpd));
vlm5d3db2f2007-06-27 04:09:37 +0000325 return 0;
326}
vlmb08408b2007-06-29 02:28:50 +0000327
328static int
329per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
330 int hasNonZeroBits = 0;
331 while(skip_nbits > 0) {
332 int skip;
333 if(skip_nbits < skip)
334 skip = skip_nbits;
335 else
336 skip = 24;
337 skip_nbits -= skip;
338
339 switch(per_get_few_bits(pd, skip)) {
340 case -1: return -1; /* Starving */
341 case 0: continue; /* Skipped empty space */
342 default: hasNonZeroBits = 1; continue;
343 }
344 }
345 return hasNonZeroBits;
346}