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