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) {
363 if(skip_nbits
< skip
)
369 switch(per_get_few_bits(pd
, skip
)) {
370 case -1: return -1; /* Starving */
371 case 0: continue; /* Skipped empty space */
372 default: hasNonZeroBits
= 1; continue;
375 return hasNonZeroBits
;