blob: 4d624f04307c6ca334b03b9e39f44f31eb6a7829 [file] [log] [blame]
Lev Walkin9218bc12007-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);
18static asn_dec_rval_t uper_sot_suck(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd);
19
20/*
21 * #10.1, #10.2
22 */
23int
24uper_open_type_put(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
25 void *buf;
26 ssize_t size;
27
28 ASN_DEBUG("Encoding as open type %s", td->name);
29 size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
30 if(size <= 0) return -1;
31
32 ASN_DEBUG("Putting %s of length %d", td->name, size);
33 while(size) {
34 ssize_t maySave = uper_put_length(po, size);
35 if(maySave < 0) break;
36 if(per_put_many_bits(po, buf, maySave * 8)) break;
37 buf = (char *)buf + maySave;
38 size -= maySave;
39 }
40
41 if(size) {
42 FREEMEM(buf);
43 return -1;
44 }
45
46 return 0;
47}
48
49asn_dec_rval_t
50uper_open_type_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
51 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
52 uper_ugot_key arg;
53 asn_dec_rval_t rv;
54 ssize_t padding;
55
56 _ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx);
57
58 ASN_DEBUG("Getting open type off %d (%d+%d), %p", pd->moved, pd->nboff, pd->nbits, pd->buffer);
59 arg.oldpd = *pd;
60 arg.unclaimed = 0;
61 arg.ot_moved = 0;
62 arg.repeat = 1;
63 pd->refill = uper_ugot_refill;
64 pd->refill_key = &arg;
65 pd->nbits = pd->nboff; /* 0 good bits at this point, will refill */
66 pd->moved = 0; /* This now counts the open type size in bits */
67
68 rv = td->uper_decoder(opt_codec_ctx, td, constraints, sptr, pd);
69
70 ASN_DEBUG("Open type %s consumed %d off of %d unclaimed=%d, repeat=%d",
71 td->name, pd->moved, arg.oldpd.moved,
72 arg.unclaimed, arg.repeat);
73
74 ASN_DEBUG("OT1 moved %d, estimated %d uncl=%d",
75 arg.oldpd.moved,
76 arg.oldpd.nboff + ((((int)arg.oldpd.buffer) & 0x7) << 3),
77 arg.unclaimed
78 );
79
80 padding = pd->moved % 8;
81 if(padding) {
82 int32_t pvalue;
83 if(padding > 7) {
84 ASN_DEBUG("Too large padding %d in open type",
85 padding);
86 rv.code = RC_FAIL;
87 return rv;
88 }
89 padding = 8 - padding;
90 ASN_DEBUG("Getting padding of %d bits", padding);
91 pvalue = per_get_few_bits(pd, padding);
92 switch(pvalue) {
93 case -1:
94 ASN_DEBUG("Padding skip failed");
95 _ASN_DECODE_STARVED;
96 case 0: break;
97 default:
98 ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
99 padding, pvalue);
100 _ASN_DECODE_FAILED;
101 }
102 }
103 if(pd->nbits != pd->nboff) {
104 ASN_DEBUG("Open type container overhead of %d bits!", pd->nbits - pd->nboff);
105 if(1) _ASN_DECODE_FAILED;
106 arg.unclaimed += pd->nbits - pd->nboff;
107 }
108
109 /* Adjust pd back so it points to original data */
110 pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved);
111 pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved);
112 pd->refill = arg.oldpd.refill;
113 pd->refill_key = arg.oldpd.refill_key;
114
115 /* Skip data not consumed by the decoder */
116 if(arg.unclaimed) ASN_DEBUG("Getting unclaimed %d", arg.unclaimed);
117 while(arg.unclaimed) {
118 size_t toget = 24;
119 if(arg.unclaimed < toget)
120 toget = arg.unclaimed;
121 arg.unclaimed -= toget;
122 switch(per_get_few_bits(pd, toget)) {
123 case -1:
124 ASN_DEBUG("Claim of %d failed", toget);
125 _ASN_DECODE_STARVED;
126 case 0:
127 ASN_DEBUG("Got claim of %d", toget);
128 continue;
129 default:
130 /* Padding must be blank */
131 ASN_DEBUG("Non-blank unconsumed padding");
132 _ASN_DECODE_FAILED;
133 }
134 }
135
Lev Walkin3877dca2007-06-27 04:17:51 +0000136 if(0) /* Special debugging assert */
Lev Walkin9218bc12007-06-27 04:09:37 +0000137 assert(pd->moved == pd->nboff + ((((int)pd->buffer) & 0x7) << 3));
138
139 if(arg.repeat) {
140 ASN_DEBUG("Not consumed the whole thing");
141 rv.code = RC_FAIL;
142 return rv;
143 }
144
145 return rv;
146}
147
148int
149uper_open_type_skip(asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd) {
150 asn_TYPE_descriptor_t s_td;
151 asn_dec_rval_t rv;
152
153 s_td.name = "<unknown extension>";
154 s_td.uper_decoder = uper_sot_suck;
155
156 rv = uper_open_type_get(opt_codec_ctx, &s_td, 0, 0, pd);
157 if(rv.code != RC_OK)
158 return -1;
159 else
160 return 0;
161}
162
163/*
164 * Internal functions.
165 */
166
167static asn_dec_rval_t
168uper_sot_suck(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
169 asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
170 asn_dec_rval_t rv;
171
172 (void)opt_codec_ctx;
173 (void)td;
174 (void)constraints;
175 (void)sptr;
176
177 while(per_get_few_bits(pd, 24) >= 0);
178
179 rv.code = RC_OK;
180 rv.consumed = pd->moved;
181
182 return rv;
183}
184
185static int
186uper_ugot_refill(asn_per_data_t *pd) {
187 uper_ugot_key *arg = pd->refill_key;
188 ssize_t next_chunk_bytes, next_chunk_bits;
189 ssize_t avail;
190
191 asn_per_data_t *oldpd = &arg->oldpd;
192
193 ASN_DEBUG("REFILLING (%+db) [from %d (%d->%d)_%d] now [%d (%d->%d)_%d] uncl %d",
194 pd->buffer - oldpd->buffer,
195 oldpd->nbits - oldpd->nboff, oldpd->nboff, oldpd->nbits, oldpd->moved,
196 pd->nbits - pd->nboff, pd->nboff, pd->nbits, pd->moved, arg->unclaimed);
197
198 /* Advance our position to where pd is */
199 oldpd->buffer = pd->buffer;
200 oldpd->nboff = pd->nboff;
201 oldpd->nbits -= pd->moved - arg->ot_moved;
202 oldpd->moved += pd->moved - arg->ot_moved;
203 arg->ot_moved = pd->moved;
204
205 if(arg->unclaimed) {
206 /* Refill the container */
207 if(per_get_few_bits(oldpd, 1))
208 return -1;
209 if(oldpd->nboff == 0) {
210 assert(0);
211 return -1;
212 }
213 pd->buffer = oldpd->buffer;
214 pd->nboff = oldpd->nboff - 1;
215 pd->nbits = oldpd->nbits;
216 ASN_DEBUG("Return from UNCLAIMED");
217 return 0;
218 }
219
220 if(!arg->repeat) {
221 ASN_DEBUG("Want more but refill doesn't have it");
222 return -1;
223 }
224
225 next_chunk_bytes = uper_get_length(oldpd, -1, &arg->repeat);
226 ASN_DEBUG("Open type LENGTH %d bytes at off %d, repeat %d",
227 next_chunk_bytes, oldpd->moved, arg->repeat);
228 if(next_chunk_bytes < 0) return -1;
229 if(next_chunk_bytes == 0) {
230 pd->refill = 0; /* No more refills, naturally */
231 assert(!arg->repeat); /* Implementation guarantee */
232 }
233 next_chunk_bits = next_chunk_bytes << 3;
234 avail = oldpd->nbits - oldpd->nboff;
235 if(avail >= next_chunk_bits) {
236 pd->nbits = oldpd->nboff + next_chunk_bits;
237 arg->unclaimed = 0;
238 } else {
239 pd->nbits = oldpd->nbits;
240 arg->unclaimed = next_chunk_bits - avail;
241 ASN_DEBUG("Parent has %d, require %d, will claim %d", avail, next_chunk_bits, arg->unclaimed);
242 }
243 pd->buffer = oldpd->buffer;
244 pd->nboff = oldpd->nboff;
245 return 0;
246}