Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / ASN1c / per_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 <per_support.h>
7 #include <constr_TYPE.h>
8 #include <per_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 static asn_dec_rval_t uper_sot_suck(const asn_codec_ctx_t *,
20                                     const asn_TYPE_descriptor_t *td,
21                                     const asn_per_constraints_t *constraints,
22                                     void **sptr, asn_per_data_t *pd);
23
24 /*
25  * Encode an "open type field".
26  * #10.1, #10.2
27  */
28 int
29 uper_open_type_put(const asn_TYPE_descriptor_t *td,
30                    const asn_per_constraints_t *constraints, const void *sptr,
31                    asn_per_outp_t *po) {
32     void *buf;
33     void *bptr;
34     ssize_t size;
35
36     ASN_DEBUG("Open type put %s ...", td->name);
37
38     size = uper_encode_to_new_buffer(td, constraints, sptr, &buf);
39     if(size <= 0) return -1;
40
41     ASN_DEBUG("Open type put %s of length %" ASN_PRI_SSIZE " + overhead (1byte?)", td->name,
42               size);
43
44     bptr = buf;
45     do {
46         int need_eom = 0;
47         ssize_t may_save = uper_put_length(po, size, &need_eom);
48         ASN_DEBUG("Prepending length %" ASN_PRI_SSIZE
49                   " to %s and allowing to save %" ASN_PRI_SSIZE,
50                   size, td->name, may_save);
51         if(may_save < 0) break;
52         if(per_put_many_bits(po, bptr, may_save * 8)) break;
53         bptr = (char *)bptr + may_save;
54         size -= may_save;
55         if(need_eom && uper_put_length(po, 0, 0)) {
56             FREEMEM(buf);
57             return -1;
58         }
59     } while(size);
60
61     FREEMEM(buf);
62     if(size) return -1;
63
64     return 0;
65 }
66
67 static asn_dec_rval_t
68 uper_open_type_get_simple(const asn_codec_ctx_t *ctx,
69                           const asn_TYPE_descriptor_t *td,
70                           const asn_per_constraints_t *constraints, void **sptr,
71                           asn_per_data_t *pd) {
72     asn_dec_rval_t rv;
73         ssize_t chunk_bytes;
74         int repeat;
75         uint8_t *buf = 0;
76         size_t bufLen = 0;
77         size_t bufSize = 0;
78         asn_per_data_t spd;
79         size_t padding;
80
81         ASN__STACK_OVERFLOW_CHECK(ctx);
82
83         ASN_DEBUG("Getting open type %s...", td->name);
84
85         do {
86                 chunk_bytes = uper_get_length(pd, -1, 0, &repeat);
87                 if(chunk_bytes < 0) {
88                         FREEMEM(buf);
89                         ASN__DECODE_STARVED;
90                 }
91                 if(bufLen + chunk_bytes > bufSize) {
92                         void *ptr;
93                         bufSize = chunk_bytes + (bufSize << 2);
94                         ptr = REALLOC(buf, bufSize);
95                         if(!ptr) {
96                                 FREEMEM(buf);
97                                 ASN__DECODE_FAILED;
98                         }
99                         buf = ptr;
100                 }
101                 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
102                         FREEMEM(buf);
103                         ASN__DECODE_STARVED;
104                 }
105                 bufLen += chunk_bytes;
106         } while(repeat);
107
108         ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
109                 (long)bufLen);
110
111         memset(&spd, 0, sizeof(spd));
112         spd.buffer = buf;
113         spd.nbits = bufLen << 3;
114
115         ASN_DEBUG_INDENT_ADD(+4);
116         rv = td->op->uper_decoder(ctx, td, constraints, sptr, &spd);
117         ASN_DEBUG_INDENT_ADD(-4);
118
119         if(rv.code == RC_OK) {
120                 /* Check padding validity */
121                 padding = spd.nbits - spd.nboff;
122                 if (((padding > 0 && padding < 8) ||
123                 /* X.691#10.1.3 */
124                 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
125                     per_get_few_bits(&spd, padding) == 0) {
126                         /* Everything is cool */
127                         FREEMEM(buf);
128                         return rv;
129                 }
130                 FREEMEM(buf);
131                 if(padding >= 8) {
132                         ASN_DEBUG("Too large padding %d in open type", (int)padding);
133                         ASN__DECODE_FAILED;
134                 } else {
135                         ASN_DEBUG("No padding");
136                 }
137         } else {
138                 FREEMEM(buf);
139                 /* rv.code could be RC_WMORE, nonsense in this context */
140                 rv.code = RC_FAIL; /* Noone would give us more */
141         }
142
143         return rv;
144 }
145
146 static asn_dec_rval_t CC_NOTUSED
147 uper_open_type_get_complex(const asn_codec_ctx_t *ctx,
148                            const asn_TYPE_descriptor_t *td,
149                            asn_per_constraints_t *constraints, void **sptr,
150                            asn_per_data_t *pd) {
151     uper_ugot_key arg;
152         asn_dec_rval_t rv;
153         ssize_t padding;
154
155         ASN__STACK_OVERFLOW_CHECK(ctx);
156
157         ASN_DEBUG("Getting open type %s from %s", td->name,
158                 asn_bit_data_string(pd));
159         arg.oldpd = *pd;
160         arg.unclaimed = 0;
161         arg.ot_moved = 0;
162         arg.repeat = 1;
163         pd->refill = uper_ugot_refill;
164         pd->refill_key = &arg;
165         pd->nbits = pd->nboff;  /* 0 good bits at this point, will refill */
166         pd->moved = 0;  /* This now counts the open type size in bits */
167
168         ASN_DEBUG_INDENT_ADD(+4);
169         rv = td->op->uper_decoder(ctx, td, constraints, sptr, pd);
170         ASN_DEBUG_INDENT_ADD(-4);
171
172 #define UPDRESTOREPD    do {                                            \
173         /* buffer and nboff are valid, preserve them. */                \
174         pd->nbits = arg.oldpd.nbits - (pd->moved - arg.ot_moved);       \
175         pd->moved = arg.oldpd.moved + (pd->moved - arg.ot_moved);       \
176         pd->refill = arg.oldpd.refill;                                  \
177         pd->refill_key = arg.oldpd.refill_key;                          \
178   } while(0)
179
180         if(rv.code != RC_OK) {
181                 UPDRESTOREPD;
182                 return rv;
183         }
184
185         ASN_DEBUG("OpenType %s pd%s old%s unclaimed=%d, repeat=%d", td->name,
186                 asn_bit_data_string(pd),
187                 asn_bit_data_string(&arg.oldpd),
188                 (int)arg.unclaimed, (int)arg.repeat);
189
190         padding = pd->moved % 8;
191         if(padding) {
192                 int32_t pvalue;
193                 if(padding > 7) {
194                         ASN_DEBUG("Too large padding %d in open type",
195                                 (int)padding);
196                         rv.code = RC_FAIL;
197                         UPDRESTOREPD;
198                         return rv;
199                 }
200                 padding = 8 - padding;
201                 ASN_DEBUG("Getting padding of %d bits", (int)padding);
202                 pvalue = per_get_few_bits(pd, padding);
203                 switch(pvalue) {
204                 case -1:
205                         ASN_DEBUG("Padding skip failed");
206                         UPDRESTOREPD;
207                         ASN__DECODE_STARVED;
208                 case 0: break;
209                 default:
210                         ASN_DEBUG("Non-blank padding (%d bits 0x%02x)",
211                                 (int)padding, (int)pvalue);
212                         UPDRESTOREPD;
213                         ASN__DECODE_FAILED;
214                 }
215         }
216         if(pd->nboff != pd->nbits) {
217                 ASN_DEBUG("Open type %s overhead pd%s old%s", td->name,
218                         asn_bit_data_string(pd), asn_bit_data_string(&arg.oldpd));
219                 if(1) {
220                         UPDRESTOREPD;
221                         ASN__DECODE_FAILED;
222                 } else {
223                         arg.unclaimed += pd->nbits - pd->nboff;
224                 }
225         }
226
227         /* Adjust pd back so it points to original data */
228         UPDRESTOREPD;
229
230         /* Skip data not consumed by the decoder */
231         if(arg.unclaimed) {
232                 ASN_DEBUG("Getting unclaimed %d", (int)arg.unclaimed);
233                 switch(per_skip_bits(pd, arg.unclaimed)) {
234                 case -1:
235                         ASN_DEBUG("Claim of %d failed", (int)arg.unclaimed);
236                         ASN__DECODE_STARVED;
237                 case 0:
238                         ASN_DEBUG("Got claim of %d", (int)arg.unclaimed);
239                         break;
240                 default:
241                         /* Padding must be blank */
242                         ASN_DEBUG("Non-blank unconsumed padding");
243                         ASN__DECODE_FAILED;
244                 }
245                 arg.unclaimed = 0;
246         }
247
248         if(arg.repeat) {
249                 ASN_DEBUG("Not consumed the whole thing");
250                 rv.code = RC_FAIL;
251                 return rv;
252         }
253
254         return rv;
255 }
256
257
258 asn_dec_rval_t
259 uper_open_type_get(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
260                    const asn_per_constraints_t *constraints, void **sptr,
261                    asn_per_data_t *pd) {
262     return uper_open_type_get_simple(ctx, td, constraints, sptr, pd);
263 }
264
265 int
266 uper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
267         asn_TYPE_descriptor_t s_td;
268     asn_TYPE_operation_t s_op;
269         asn_dec_rval_t rv;
270
271         s_td.name = "<unknown extension>";
272         s_td.op = &s_op;
273     s_op.uper_decoder = uper_sot_suck;
274
275         rv = uper_open_type_get(ctx, &s_td, 0, 0, pd);
276         if(rv.code != RC_OK)
277                 return -1;
278         else
279                 return 0;
280 }
281
282 /*
283  * Internal functions.
284  */
285
286 static asn_dec_rval_t
287 uper_sot_suck(const asn_codec_ctx_t *ctx, const asn_TYPE_descriptor_t *td,
288               const asn_per_constraints_t *constraints, void **sptr,
289               asn_per_data_t *pd) {
290     asn_dec_rval_t rv;
291
292         (void)ctx;
293         (void)td;
294         (void)constraints;
295         (void)sptr;
296
297         while(per_get_few_bits(pd, 1) >= 0);
298
299         rv.code = RC_OK;
300         rv.consumed = pd->moved;
301
302         return rv;
303 }
304
305 static int
306 uper_ugot_refill(asn_per_data_t *pd) {
307         uper_ugot_key *arg = pd->refill_key;
308         ssize_t next_chunk_bytes, next_chunk_bits;
309         ssize_t avail;
310
311         asn_per_data_t *oldpd = &arg->oldpd;
312
313         ASN_DEBUG("REFILLING pd->moved=%ld, oldpd->moved=%ld",
314                 (long)pd->moved, (long)oldpd->moved);
315
316         /* Advance our position to where pd is */
317         oldpd->buffer = pd->buffer;
318         oldpd->nboff  = pd->nboff;
319         oldpd->nbits -= pd->moved - arg->ot_moved;
320         oldpd->moved += pd->moved - arg->ot_moved;
321         arg->ot_moved = pd->moved;
322
323         if(arg->unclaimed) {
324                 /* Refill the container */
325                 if(per_get_few_bits(oldpd, 1))
326                         return -1;
327                 if(oldpd->nboff == 0) {
328                         assert(0);
329                         return -1;
330                 }
331                 pd->buffer = oldpd->buffer;
332                 pd->nboff = oldpd->nboff - 1;
333                 pd->nbits = oldpd->nbits;
334                 ASN_DEBUG("UNCLAIMED <- return from (pd->moved=%ld)",
335                         (long)pd->moved);
336                 return 0;
337         }
338
339         if(!arg->repeat) {
340                 ASN_DEBUG("Want more but refill doesn't have it");
341                 return -1;
342         }
343
344         next_chunk_bytes = uper_get_length(oldpd, -1, 0, &arg->repeat);
345         ASN_DEBUG("Open type LENGTH %ld bytes at off %ld, repeat %ld",
346                 (long)next_chunk_bytes, (long)oldpd->moved, (long)arg->repeat);
347         if(next_chunk_bytes < 0) return -1;
348         if(next_chunk_bytes == 0) {
349                 pd->refill = 0; /* No more refills, naturally */
350                 assert(!arg->repeat);   /* Implementation guarantee */
351         }
352         next_chunk_bits = next_chunk_bytes << 3;
353         avail = oldpd->nbits - oldpd->nboff;
354         if(avail >= next_chunk_bits) {
355                 pd->nbits = oldpd->nboff + next_chunk_bits;
356                 arg->unclaimed = 0;
357                 ASN_DEBUG("!+Parent frame %ld bits, alloting %ld [%ld..%ld] (%ld)",
358                         (long)next_chunk_bits, (long)oldpd->moved,
359                         (long)oldpd->nboff, (long)oldpd->nbits,
360                         (long)(oldpd->nbits - oldpd->nboff));
361         } else {
362                 pd->nbits = oldpd->nbits;
363                 arg->unclaimed = next_chunk_bits - avail;
364                 ASN_DEBUG("!-Parent frame %ld, require %ld, will claim %ld",
365                         (long)avail, (long)next_chunk_bits,
366                         (long)arg->unclaimed);
367         }
368         pd->buffer = oldpd->buffer;
369         pd->nboff = oldpd->nboff;
370         ASN_DEBUG("Refilled pd%s old%s",
371                 asn_bit_data_string(pd), asn_bit_data_string(oldpd));
372         return 0;
373 }
374
375 static int
376 per_skip_bits(asn_per_data_t *pd, int skip_nbits) {
377         int hasNonZeroBits = 0;
378         while(skip_nbits > 0) {
379                 int skip;
380
381                 /* per_get_few_bits() is more efficient when nbits <= 24 */
382                 if(skip_nbits < 24)
383                         skip = skip_nbits;
384                 else
385                         skip = 24;
386                 skip_nbits -= skip;
387
388                 switch(per_get_few_bits(pd, skip)) {
389                 case -1: return -1;     /* Starving */
390                 case 0: continue;       /* Skipped empty space */
391                 default: hasNonZeroBits = 1; continue;
392                 }
393         }
394         return hasNonZeroBits;
395 }
396
397 static asn_dec_rval_t
398 aper_open_type_get_simple(const asn_codec_ctx_t *ctx,
399                           const asn_TYPE_descriptor_t *td,
400                           const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
401         asn_dec_rval_t rv;
402         ssize_t chunk_bytes;
403         int repeat;
404         uint8_t *buf = 0;
405         size_t bufLen = 0;
406         size_t bufSize = 0;
407         asn_per_data_t spd;
408         size_t padding;
409
410         ASN__STACK_OVERFLOW_CHECK(ctx);
411
412         ASN_DEBUG("Getting open type %s...", td->name);
413
414         do {
415                 chunk_bytes = aper_get_length(pd, -1, -1, &repeat);
416                 if(chunk_bytes < 0) {
417                         FREEMEM(buf);
418                         ASN__DECODE_STARVED;
419                 }
420                 if(bufLen + chunk_bytes > bufSize) {
421                         void *ptr;
422                         bufSize = chunk_bytes + (bufSize << 2);
423                         ptr = REALLOC(buf, bufSize);
424                         if(!ptr) {
425                                 FREEMEM(buf);
426                                 ASN__DECODE_FAILED;
427                         }
428                         buf = ptr;
429                 }
430                 if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
431                         FREEMEM(buf);
432                         ASN__DECODE_STARVED;
433                 }
434                 bufLen += chunk_bytes;
435         } while(repeat);
436
437         ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
438                 (long)bufLen);
439
440         memset(&spd, 0, sizeof(spd));
441         spd.buffer = buf;
442         spd.nbits = bufLen << 3;
443
444         ASN_DEBUG_INDENT_ADD(+4);
445         rv = td->op->aper_decoder(ctx, td, constraints, sptr, &spd);
446         ASN_DEBUG_INDENT_ADD(-4);
447
448         if(rv.code == RC_OK) {
449                 /* Check padding validity */
450                 padding = spd.nbits - spd.nboff;
451                 if (((padding > 0 && padding < 8) ||
452                 /* X.691#10.1.3 */
453                 (spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
454                     per_get_few_bits(&spd, padding) == 0) {
455                         /* Everything is cool */
456                         FREEMEM(buf);
457                         return rv;
458                 }
459                 FREEMEM(buf);
460                 if(padding >= 8) {
461                         ASN_DEBUG("Too large padding %d in open type", (int)padding);
462                         ASN__DECODE_FAILED;
463                 } else {
464                         ASN_DEBUG("No padding");
465                 }
466         } else {
467                 FREEMEM(buf);
468                 /* rv.code could be RC_WMORE, nonsense in this context */
469                 rv.code = RC_FAIL; /* Noone would give us more */
470         }
471
472         return rv;
473 }
474
475 int
476 aper_open_type_put(const asn_TYPE_descriptor_t *td,
477                    const asn_per_constraints_t *constraints,
478                    const void *sptr, asn_per_outp_t *po) {
479         void *buf;
480         void *bptr;
481         ssize_t size;
482         size_t toGo;
483
484         ASN_DEBUG("Open type put %s ...", td->name);
485
486         size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
487         if(size <= 0) return -1;
488
489         for(bptr = buf, toGo = size; toGo;) {
490                 ssize_t maySave = aper_put_length(po, -1, toGo);
491                 if(maySave < 0) break;
492                 if(per_put_many_bits(po, bptr, maySave * 8)) break;
493                 bptr = (char *)bptr + maySave;
494                 toGo -= maySave;
495         }
496
497         FREEMEM(buf);
498         if(toGo) return -1;
499
500         ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
501                           td->name, size);
502
503         return 0;
504 }
505
506 asn_dec_rval_t
507 aper_open_type_get(const asn_codec_ctx_t *ctx,
508                    const asn_TYPE_descriptor_t *td,
509                    const asn_per_constraints_t *constraints,
510                    void **sptr, asn_per_data_t *pd) {
511
512         return aper_open_type_get_simple(ctx, td, constraints, sptr, pd);
513 }
514
515 int
516 aper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
517         asn_TYPE_descriptor_t s_td;
518         asn_dec_rval_t rv;
519         asn_TYPE_operation_t op_t;
520
521         memset(&op_t, 0, sizeof(op_t));
522         s_td.name = "<unknown extension>";
523         s_td.op = &op_t;
524         s_td.op->aper_decoder = uper_sot_suck;
525
526         rv = aper_open_type_get(ctx, &s_td, 0, 0, pd);
527         if(rv.code != RC_OK)
528                 return -1;
529         else
530                 return 0;
531 }
532
533