SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / uper_opentype.c
1 /*
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 <uper_encoder.h>
7 #include <uper_support.h>
8 #include <uper_opentype.h>
9
10 typedef 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
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
20 /*
21  * Encode an "open type field".
22  * #10.1, #10.2
23  */
24 int
25 uper_open_type_put(const asn_TYPE_descriptor_t *td,
26                    const asn_per_constraints_t *constraints, const void *sptr,
27                    asn_per_outp_t *po) {
28     void *buf;
29     void *bptr;
30     ssize_t size;
31
32     ASN_DEBUG("Open type put %s ...", td->name);
33
34     size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
35     if(size <= 0) return -1;
36
37     ASN_DEBUG("Open type put %s of length %" ASN_PRI_SSIZE " + overhead (1byte?)", td->name,
38               size);
39
40     bptr = buf;
41     do {
42         int need_eom = 0;
43         ssize_t may_save = uper_put_length(po, size, &need_eom);
44         ASN_DEBUG("Prepending length %" ASN_PRI_SSIZE
45                   " to %s and allowing to save %" ASN_PRI_SSIZE,
46                   size, td->name, may_save);
47         if(may_save < 0) break;
48         if(per_put_many_bits(po, bptr, may_save * 8)) break;
49         bptr = (char *)bptr + may_save;
50         size -= may_save;
51         if(need_eom && uper_put_length(po, 0, 0)) {
52             FREEMEM(buf);
53             return -1;
54         }
55     } while(size);
56
57     FREEMEM(buf);
58     if(size) return -1;
59
60     return 0;
61 }
62
63 static asn_dec_rval_t
64 uper_open_type_get_simple(const asn_codec_ctx_t *ctx,
65                           const asn_TYPE_descriptor_t *td,
66                           const asn_per_constraints_t *constraints, void **sptr,
67                           asn_per_data_t *pd) {
68     asn_dec_rval_t rv;
69         ssize_t chunk_bytes;
70         int repeat;
71         uint8_t *buf = 0;
72         size_t bufLen = 0;
73         size_t bufSize = 0;
74         asn_per_data_t spd;
75         size_t padding;
76
77         ASN__STACK_OVERFLOW_CHECK(ctx);
78
79         ASN_DEBUG("Getting open type %s...", td->name);
80
81         do {
82                 chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
83                 if(chunk_bytes < 0) {
84                         FREEMEM(buf);
85                         ASN__DECODE_STARVED;
86                 }
87                 if(bufLen + chunk_bytes > bufSize) {
88                         void *ptr;
89                         bufSize = chunk_bytes + (bufSize << 2);
90                         ptr = REALLOC(buf, bufSize);
91                         if(!ptr) {
92                                 FREEMEM(buf);
93                                 ASN__DECODE_FAILED;
94                         }
95                         buf = ptr;
96                 }
97                 if(per_get_many_bits(pd, (buf == NULL)? NULL : buf + bufLen, 0, chunk_bytes << 3)) {
98                         FREEMEM(buf);
99                         ASN__DECODE_STARVED;
100                 }
101                 bufLen += chunk_bytes;
102         } while(repeat);
103
104         ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
105                 (long)bufLen);
106
107         memset(&spd, 0, sizeof(spd));
108         spd.buffer = buf;
109         spd.nbits = bufLen << 3;
110
111         ASN_DEBUG_INDENT_ADD(+4);
112         rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
113         ASN_DEBUG_INDENT_ADD(-4);
114
115         if(rv.code == RC_OK) {
116                 /* Check padding validity */
117                 padding = spd.nbits - spd.nboff;
118                 if (((padding > 0 && padding < 8) ||
119                 /* X.691#10.1.3 */
120                 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
121                     per_get_few_bits(&spd, padding) == 0) {
122                         /* Everything is cool */
123                         FREEMEM(buf);
124                         return rv;
125                 }
126                 FREEMEM(buf);
127                 if(padding >= 8) {
128                         ASN_DEBUG("Too large padding %d in open type", (int)padding);
129                         ASN__DECODE_FAILED;
130                 } else {
131                         ASN_DEBUG("No padding");
132                 }
133         } else {
134                 FREEMEM(buf);
135                 /* rv.code could be RC_WMORE, nonsense in this context */
136                 rv.code = RC_FAIL; /* No one would give us more */
137         }
138
139         return rv;
140 }
141
142 static asn_dec_rval_t CC_NOTUSED
143 uper_open_type_get_complex(const asn_codec_ctx_t *ctx,
144                            const asn_TYPE_descriptor_t *td,
145                            asn_per_constraints_t *constraints, void **sptr,
146                            asn_per_data_t *pd) {
147     uper_ugot_key arg;
148         asn_dec_rval_t rv;
149         ssize_t padding;
150
151         ASN__STACK_OVERFLOW_CHECK(ctx);
152
153         ASN_DEBUG("Getting open type %s from %s", td->name,
154                 asn_bit_data_string(pd));
155         arg.oldpd = *pd;
156         arg.unclaimed = 0;
157         arg.ot_moved = 0;
158         arg.repeat = 1;
159         pd->refill = uper_ugot_refill;
160         pd->refill_key = &arg;
161         pd->nbits = pd->nboff;  /* 0 good bits at this point, will refill */
162         pd->moved = 0;  /* This now counts the open type size in bits */
163
164         ASN_DEBUG_INDENT_ADD(+4);
165         rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
166         ASN_DEBUG_INDENT_ADD(-4);
167
168 #define UPDRESTOREPD    do {                                            \
169         /* buffer and nboff are valid, preserve them. */                \
170         pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved);       \
171         pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved);       \
172         pd->refill = arg.oldpd.refill;                                  \
173         pd->refill_key = arg.oldpd.refill_key;                          \
174   } while(0)
175
176         if(rv.code != RC_OK) {
177                 UPDRESTOREPD;
178                 return rv;
179         }
180
181         ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
182                 asn_bit_data_string(pd),
183                 asn_bit_data_string(&arg.oldpd),
184                 (int)arg.unclaimed, (int)arg.repeat);
185
186         padding = pd->moved % 8;
187         if(padding) {
188                 int32_t pvalue;
189                 if(padding > 7) {
190                         ASN_DEBUG("Too large padding %d in open type",
191                                 (int)padding);
192                         rv.code = RC_FAIL;
193                         UPDRESTOREPD;
194                         return rv;
195                 }
196                 padding = 8 - padding;
197                 ASN_DEBUG("Getting padding of %d bits", (int)padding);
198                 pvalue = per_get_few_bits(pd, padding);
199                 switch(pvalue) {
200                 case -1:
201                         ASN_DEBUG("Padding skip failed");
202                         UPDRESTOREPD;
203                         ASN__DECODE_STARVED;
204                 case 0: break;
205                 default:
206                         ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
207                                 (int)padding, (int)pvalue);
208                         UPDRESTOREPD;
209                         ASN__DECODE_FAILED;
210                 }
211         }
212         if(pd->nboff != pd->nbits) {
213                 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
214                         asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
215                 if(1) {
216                         UPDRESTOREPD;
217                         ASN__DECODE_FAILED;
218                 } else {
219                         arg.unclaimed += pd->nbits - pd->nboff;
220                 }
221         }
222
223         /* Adjust pd back so it points to original data */
224         UPDRESTOREPD;
225
226         /* Skip data not consumed by the decoder */
227         if(arg.unclaimed) {
228                 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
229                 switch(per_skip_bits(pd, arg.unclaimed)) {
230                 case -1:
231                         ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
232                         ASN__DECODE_STARVED;
233                 case 0:
234                         ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
235                         break;
236                 default:
237                         /* Padding must be blank */
238                         ASN_DEBUG("Non-blank unconsumed padding");
239                         ASN__DECODE_FAILED;
240                 }
241                 arg.unclaimed = 0;
242         }
243
244         if(arg.repeat) {
245                 ASN_DEBUG("Not consumed the whole thing");
246                 rv.code = RC_FAIL;
247                 return rv;
248         }
249
250         return rv;
251 }
252
253
254 asn_dec_rval_t
255 uper_open_type_get(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
256                    const asn_per_constraints_t *constraints, void **sptr,
257                    asn_per_data_t *pd) {
258     return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
259 }
260
261 int
262 uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
263         asn_TYPE_descriptor_t s_td;
264     asn_TYPE_operation_t s_op;
265         asn_dec_rval_t rv;
266
267         s_td.name = "<unknown extension>";
268         s_td.op = &s_op;
269     s_op.uper_decoder = uper_sot_suck;
270
271         rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
272         if(rv.code != RC_OK)
273                 return -1;
274         else
275                 return 0;
276 }
277
278 /*
279  * Internal functions.
280  */
281
282 static int
283 uper_ugot_refill(asn_per_data_t *pd) {
284         uper_ugot_key *arg = pd->refill_key;
285         ssize_t next_chunk_bytes, next_chunk_bits;
286         ssize_t avail;
287
288         asn_per_data_t *oldpd = &arg->oldpd;
289
290         ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
291                 (long)pd->moved, (long)oldpd->moved);
292
293         /* Advance our position to where pd is */
294         oldpd->buffer = pd->buffer;
295         oldpd->nboff  = pd->nboff;
296         oldpd->nbits -= pd->moved - arg->ot_moved;
297         oldpd->moved += pd->moved - arg->ot_moved;
298         arg->ot_moved = pd->moved;
299
300         if(arg->unclaimed) {
301                 /* Refill the container */
302                 if(per_get_few_bits(oldpd, 1))
303                         return -1;
304                 if(oldpd->nboff == 0) {
305                         assert(0);
306                         return -1;
307                 }
308                 pd->buffer = oldpd->buffer;
309                 pd->nboff = oldpd->nboff - 1;
310                 pd->nbits = oldpd->nbits;
311                 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
312                         (long)pd->moved);
313                 return 0;
314         }
315
316         if(!arg->repeat) {
317                 ASN_DEBUG("Want more but refill doesn't have it");
318                 return -1;
319         }
320
321         next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
322         ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
323                 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
324         if(next_chunk_bytes < 0) return -1;
325         if(next_chunk_bytes == 0) {
326                 pd->refill = 0; /* No more refills, naturally */
327                 assert(!arg->repeat);   /* Implementation guarantee */
328         }
329         next_chunk_bits = next_chunk_bytes << 3;
330         avail = oldpd->nbits - oldpd->nboff;
331         if(avail >= next_chunk_bits) {
332                 pd->nbits = oldpd->nboff + next_chunk_bits;
333                 arg->unclaimed = 0;
334                 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
335                         (long)next_chunk_bits, (long)oldpd->moved,
336                         (long)oldpd->nboff, (long)oldpd->nbits,
337                         (long)(oldpd->nbits - oldpd->nboff));
338         } else {
339                 pd->nbits = oldpd->nbits;
340                 arg->unclaimed = next_chunk_bits - avail;
341                 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
342                         (long)avail, (long)next_chunk_bits,
343                         (long)arg->unclaimed);
344         }
345         pd->buffer = oldpd->buffer;
346         pd->nboff = oldpd->nboff;
347         ASN_DEBUG("Refilled pd%s old%s",
348                 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
349         return 0;
350 }
351
352 static int
353 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
354         int hasNonZeroBits = 0;
355         while(skip_nbits > 0) {
356                 int skip;
357
358                 /* per_get_few_bits() is more efficient when nbits <= 24 */
359                 if(skip_nbits < 24)
360                         skip = skip_nbits;
361                 else
362                         skip = 24;
363                 skip_nbits -= skip;
364
365                 switch(per_get_few_bits(pd, skip)) {
366                 case -1: return -1;     /* Starving */
367                 case 0: continue;       /* Skipped empty space */
368                 default: hasNonZeroBits = 1; continue;
369                 }
370         }
371         return hasNonZeroBits;
372 }