26137b02bde3275c362ff12af0ffdda8566bc93d
[ric-app/kpimon.git] / asn1c_defs / all-defs / constr_SEQUENCE.c
1 /*\r
2  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.\r
3  * All rights reserved.\r
4  * Redistribution and modifications are permitted subject to BSD license.\r
5  */\r
6 #include <asn_internal.h>\r
7 #include <constr_SEQUENCE.h>\r
8 #include <OPEN_TYPE.h>\r
9 #include <per_opentype.h>\r
10 \r
11 /*\r
12  * Number of bytes left for this structure.\r
13  * (ctx->left) indicates the number of bytes _transferred_ for the structure.\r
14  * (size) contains the number of bytes in the buffer passed.\r
15  */\r
16 #define LEFT    ((size<(size_t)ctx->left)?size:(size_t)ctx->left)\r
17 \r
18 /*\r
19  * If the subprocessor function returns with an indication that it wants\r
20  * more data, it may well be a fatal decoding problem, because the\r
21  * size is constrained by the <TLV>'s L, even if the buffer size allows\r
22  * reading more data.\r
23  * For example, consider the buffer containing the following TLVs:\r
24  * <T:5><L:1><V> <T:6>...\r
25  * The TLV length clearly indicates that one byte is expected in V, but\r
26  * if the V processor returns with "want more data" even if the buffer\r
27  * contains way more data than the V processor have seen.\r
28  */\r
29 #define SIZE_VIOLATION  (ctx->left >= 0 && (size_t)ctx->left <= size)\r
30 \r
31 /*\r
32  * This macro "eats" the part of the buffer which is definitely "consumed",\r
33  * i.e. was correctly converted into local representation or rightfully skipped.\r
34  */\r
35 #undef  ADVANCE\r
36 #define ADVANCE(num_bytes)      do {            \\r
37                 size_t num = num_bytes;         \\r
38                 ptr = ((const char *)ptr) + num; \\r
39                 size -= num;                    \\r
40                 if(ctx->left >= 0)              \\r
41                         ctx->left -= num;       \\r
42                 consumed_myself += num;         \\r
43         } while(0)\r
44 \r
45 /*\r
46  * Switch to the next phase of parsing.\r
47  */\r
48 #undef  NEXT_PHASE\r
49 #undef  PHASE_OUT\r
50 #define NEXT_PHASE(ctx) do {                    \\r
51                 ctx->phase++;                   \\r
52                 ctx->step = 0;                  \\r
53         } while(0)\r
54 #define PHASE_OUT(ctx)  do { ctx->phase = 10; } while(0)\r
55 \r
56 /*\r
57  * Return a standardized complex structure.\r
58  */\r
59 #undef  RETURN\r
60 #define RETURN(_code)   do {                    \\r
61                 rval.code = _code;              \\r
62                 rval.consumed = consumed_myself;\\r
63                 return rval;                    \\r
64         } while(0)\r
65 \r
66 /*\r
67  * Check whether we are inside the extensions group.\r
68  */\r
69 #define IN_EXTENSION_GROUP(specs, memb_idx) \\r
70     ((specs)->first_extension >= 0          \\r
71      && (unsigned)(specs)->first_extension <= (memb_idx))\r
72 \r
73 /*\r
74  * Tags are canonically sorted in the tag2element map.\r
75  */\r
76 static int\r
77 _t2e_cmp(const void *ap, const void *bp) {\r
78         const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;\r
79         const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;\r
80 \r
81         int a_class = BER_TAG_CLASS(a->el_tag);\r
82         int b_class = BER_TAG_CLASS(b->el_tag);\r
83 \r
84         if(a_class == b_class) {\r
85                 ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);\r
86                 ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);\r
87 \r
88                 if(a_value == b_value) {\r
89                         if(a->el_no > b->el_no)\r
90                                 return 1;\r
91                         /*\r
92                          * Important: we do not check\r
93                          * for a->el_no <= b->el_no!\r
94                          */\r
95                         return 0;\r
96                 } else if(a_value < b_value)\r
97                         return -1;\r
98                 else\r
99                         return 1;\r
100         } else if(a_class < b_class) {\r
101                 return -1;\r
102         } else {\r
103                 return 1;\r
104         }\r
105 }\r
106 \r
107 \r
108 /*\r
109  * The decoder of the SEQUENCE type.\r
110  */\r
111 asn_dec_rval_t\r
112 SEQUENCE_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,\r
113                     const asn_TYPE_descriptor_t *td, void **struct_ptr,\r
114                     const void *ptr, size_t size, int tag_mode) {\r
115     /*\r
116          * Bring closer parts of structure description.\r
117          */\r
118         const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
119     const asn_TYPE_member_t *elements = td->elements;\r
120 \r
121     /*\r
122          * Parts of the structure being constructed.\r
123          */\r
124         void *st = *struct_ptr; /* Target structure. */\r
125         asn_struct_ctx_t *ctx;  /* Decoder context */\r
126 \r
127         ber_tlv_tag_t tlv_tag;  /* T from TLV */\r
128         asn_dec_rval_t rval;    /* Return code from subparsers */\r
129 \r
130         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */\r
131         size_t edx;                     /* SEQUENCE element's index */\r
132 \r
133         ASN_DEBUG("Decoding %s as SEQUENCE", td->name);\r
134         \r
135         /*\r
136          * Create the target structure if it is not present already.\r
137          */\r
138         if(st == 0) {\r
139                 st = *struct_ptr = CALLOC(1, specs->struct_size);\r
140                 if(st == 0) {\r
141                         RETURN(RC_FAIL);\r
142                 }\r
143         }\r
144 \r
145         /*\r
146          * Restore parsing context.\r
147          */\r
148         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);\r
149         \r
150         /*\r
151          * Start to parse where left previously\r
152          */\r
153         switch(ctx->phase) {\r
154         case 0:\r
155                 /*\r
156                  * PHASE 0.\r
157                  * Check that the set of tags associated with given structure\r
158                  * perfectly fits our expectations.\r
159                  */\r
160 \r
161                 rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,\r
162                         tag_mode, 1, &ctx->left, 0);\r
163                 if(rval.code != RC_OK) {\r
164                         ASN_DEBUG("%s tagging check failed: %d",\r
165                                 td->name, rval.code);\r
166                         return rval;\r
167                 }\r
168 \r
169                 if(ctx->left >= 0)\r
170                         ctx->left += rval.consumed; /* ?Substracted below! */\r
171                 ADVANCE(rval.consumed);\r
172 \r
173                 NEXT_PHASE(ctx);\r
174 \r
175                 ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",\r
176                         (long)ctx->left, (long)size);\r
177 \r
178                 /* Fall through */\r
179         case 1:\r
180                 /*\r
181                  * PHASE 1.\r
182                  * From the place where we've left it previously,\r
183                  * try to decode the next member from the list of\r
184                  * this structure's elements.\r
185                  * (ctx->step) stores the member being processed\r
186                  * between invocations and the microphase {0,1} of parsing\r
187                  * that member:\r
188                  *      step = (<member_number> * 2 + <microphase>).\r
189                  */\r
190           for(edx = ((size_t)ctx->step >> 1); edx < td->elements_count;\r
191                         edx++, ctx->step = (ctx->step & ~1) + 2) {\r
192                 void *memb_ptr;         /* Pointer to the member */\r
193                 void **memb_ptr2;       /* Pointer to that pointer */\r
194                 ssize_t tag_len;        /* Length of TLV's T */\r
195                 size_t opt_edx_end;     /* Next non-optional element */\r
196                 size_t n;\r
197                 int use_bsearch;\r
198 \r
199                 if(ctx->step & 1)\r
200                         goto microphase2;\r
201 \r
202                 /*\r
203                  * MICROPHASE 1: Synchronize decoding.\r
204                  */\r
205                 ASN_DEBUG("In %s SEQUENCE left %d, edx=%" ASN_PRI_SIZE " flags=%d"\r
206                                 " opt=%d ec=%d",\r
207                         td->name, (int)ctx->left, edx,\r
208                         elements[edx].flags, elements[edx].optional,\r
209                         td->elements_count);\r
210 \r
211         if(ctx->left == 0 /* No more stuff is expected */\r
212            && (\r
213                   /* Explicit OPTIONAL specification reaches the end */\r
214                   (edx + elements[edx].optional == td->elements_count) ||\r
215                   /* All extensions are optional */\r
216                   IN_EXTENSION_GROUP(specs, edx))) {\r
217             ASN_DEBUG("End of SEQUENCE %s", td->name);\r
218             /*\r
219              * Found the legitimate end of the structure.\r
220              */\r
221             PHASE_OUT(ctx);\r
222             RETURN(RC_OK);\r
223         }\r
224 \r
225                 /*\r
226                  * Fetch the T from TLV.\r
227                  */\r
228                 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);\r
229                 ASN_DEBUG("Current tag in %s SEQUENCE for element %" ASN_PRI_SIZE " "\r
230                         "(%s) is %s encoded in %d bytes, of frame %ld",\r
231                         td->name, edx, elements[edx].name,\r
232                         ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);\r
233                 switch(tag_len) {\r
234                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);\r
235                         /* Fall through */\r
236                 case -1: RETURN(RC_FAIL);\r
237                 }\r
238 \r
239         if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {\r
240             if(LEFT < 2) {\r
241                 if(SIZE_VIOLATION) {\r
242                     RETURN(RC_FAIL);\r
243                 } else {\r
244                     RETURN(RC_WMORE);\r
245                 }\r
246             } else if(((const uint8_t *)ptr)[1] == 0) {\r
247                 ASN_DEBUG("edx = %" ASN_PRI_SIZE ", opt = %d, ec=%d", edx,\r
248                           elements[edx].optional, td->elements_count);\r
249                 if((edx + elements[edx].optional == td->elements_count)\r
250                    || IN_EXTENSION_GROUP(specs, edx)) {\r
251                     /*\r
252                      * Yeah, baby! Found the terminator\r
253                      * of the indefinite length structure.\r
254                      */\r
255                     /*\r
256                      * Proceed to the canonical\r
257                      * finalization function.\r
258                      * No advancing is necessary.\r
259                      */\r
260                     goto phase3;\r
261                 }\r
262             }\r
263         }\r
264 \r
265                 /*\r
266                  * Find the next available type with this tag.\r
267                  */\r
268                 use_bsearch = 0;\r
269                 opt_edx_end = edx + elements[edx].optional + 1;\r
270                 if(opt_edx_end > td->elements_count)\r
271                         opt_edx_end = td->elements_count;       /* Cap */\r
272                 else if(opt_edx_end - edx > 8) {\r
273                         /* Limit the scope of linear search... */\r
274                         opt_edx_end = edx + 8;\r
275                         use_bsearch = 1;\r
276                         /* ... and resort to bsearch() */\r
277                 }\r
278                 for(n = edx; n < opt_edx_end; n++) {\r
279                         if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {\r
280                                 /*\r
281                                  * Found element corresponding to the tag\r
282                                  * being looked at.\r
283                                  * Reposition over the right element.\r
284                                  */\r
285                                 edx = n;\r
286                                 ctx->step = 1 + 2 * edx;        /* Remember! */\r
287                                 goto microphase2;\r
288                         } else if(elements[n].flags & ATF_ANY_TYPE) {\r
289                                 /*\r
290                                  * This is the ANY type, which may bear\r
291                                  * any flag whatsoever.\r
292                                  */\r
293                                 edx = n;\r
294                                 ctx->step = 1 + 2 * edx;        /* Remember! */\r
295                                 goto microphase2;\r
296                         } else if(elements[n].tag == (ber_tlv_tag_t)-1) {\r
297                                 use_bsearch = 1;\r
298                                 break;\r
299                         }\r
300                 }\r
301                 if(use_bsearch) {\r
302                         /*\r
303                          * Resort to a binary search over\r
304                          * sorted array of tags.\r
305                          */\r
306                         const asn_TYPE_tag2member_t *t2m;\r
307                         asn_TYPE_tag2member_t key = {0, 0, 0, 0};\r
308                         key.el_tag = tlv_tag;\r
309                         key.el_no = edx;\r
310                         t2m = (const asn_TYPE_tag2member_t *)bsearch(&key,\r
311                                 specs->tag2el, specs->tag2el_count,\r
312                                 sizeof(specs->tag2el[0]), _t2e_cmp);\r
313                         if(t2m) {\r
314                                 const asn_TYPE_tag2member_t *best = 0;\r
315                                 const asn_TYPE_tag2member_t *t2m_f, *t2m_l;\r
316                                 size_t edx_max = edx + elements[edx].optional;\r
317                                 /*\r
318                                  * Rewind to the first element with that tag,\r
319                                  * `cause bsearch() does not guarantee order.\r
320                                  */\r
321                                 t2m_f = t2m + t2m->toff_first;\r
322                                 t2m_l = t2m + t2m->toff_last;\r
323                                 for(t2m = t2m_f; t2m <= t2m_l; t2m++) {\r
324                                         if(t2m->el_no > edx_max) break;\r
325                                         if(t2m->el_no < edx) continue;\r
326                                         best = t2m;\r
327                                 }\r
328                                 if(best) {\r
329                                         edx = best->el_no;\r
330                                         ctx->step = 1 + 2 * edx;\r
331                                         goto microphase2;\r
332                                 }\r
333                         }\r
334                         n = opt_edx_end;\r
335                 }\r
336                 if(n == opt_edx_end) {\r
337                         /*\r
338                          * If tag is unknown, it may be either\r
339                          * an unknown (thus, incorrect) tag,\r
340                          * or an extension (...),\r
341                          * or an end of the indefinite-length structure.\r
342                          */\r
343                         if(!IN_EXTENSION_GROUP(specs,\r
344                                 edx + elements[edx].optional)) {\r
345                                 ASN_DEBUG("Unexpected tag %s (at %" ASN_PRI_SIZE ")",\r
346                                         ber_tlv_tag_string(tlv_tag), edx);\r
347                                 ASN_DEBUG("Expected tag %s (%s)%s",\r
348                                         ber_tlv_tag_string(elements[edx].tag),\r
349                                         elements[edx].name,\r
350                                         elements[edx].optional\r
351                                                 ?" or alternatives":"");\r
352                                 RETURN(RC_FAIL);\r
353                         } else {\r
354                                 /* Skip this tag */\r
355                                 ssize_t skip;\r
356                                 edx += elements[edx].optional;\r
357 \r
358                                 ASN_DEBUG("Skipping unexpected %s (at %" ASN_PRI_SIZE ")",\r
359                                         ber_tlv_tag_string(tlv_tag), edx);\r
360                                 skip = ber_skip_length(opt_codec_ctx,\r
361                                         BER_TLV_CONSTRUCTED(ptr),\r
362                                         (const char *)ptr + tag_len,\r
363                                         LEFT - tag_len);\r
364                                 ASN_DEBUG("Skip length %d in %s",\r
365                                         (int)skip, td->name);\r
366                                 switch(skip) {\r
367                                 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);\r
368                                         /* Fall through */\r
369                                 case -1: RETURN(RC_FAIL);\r
370                                 }\r
371 \r
372                                 ADVANCE(skip + tag_len);\r
373                                 ctx->step -= 2;\r
374                                 edx--;\r
375                                 continue;  /* Try again with the next tag */\r
376                         }\r
377                 }\r
378 \r
379                 /*\r
380                  * MICROPHASE 2: Invoke the member-specific decoder.\r
381                  */\r
382                 ctx->step |= 1;         /* Confirm entering next microphase */\r
383         microphase2:\r
384                 ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);\r
385                 \r
386                 /*\r
387                  * Compute the position of the member inside a structure,\r
388                  * and also a type of containment (it may be contained\r
389                  * as pointer or using inline inclusion).\r
390                  */\r
391                 if(elements[edx].flags & ATF_POINTER) {\r
392                         /* Member is a pointer to another structure */\r
393                         memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);\r
394                 } else {\r
395                         /*\r
396                          * A pointer to a pointer\r
397                          * holding the start of the structure\r
398                          */\r
399                         memb_ptr = (char *)st + elements[edx].memb_offset;\r
400                         memb_ptr2 = &memb_ptr;\r
401                 }\r
402                 /*\r
403                  * Invoke the member fetch routine according to member's type\r
404                  */\r
405                 if(elements[edx].flags & ATF_OPEN_TYPE) {\r
406                         rval = OPEN_TYPE_ber_get(opt_codec_ctx, td, st, &elements[edx], ptr, LEFT);\r
407         } else {\r
408                         rval = elements[edx].type->op->ber_decoder(opt_codec_ctx,\r
409                                         elements[edx].type,\r
410                                         memb_ptr2, ptr, LEFT,\r
411                                         elements[edx].tag_mode);\r
412                 }\r
413                 ASN_DEBUG("In %s SEQUENCE decoded %" ASN_PRI_SIZE " %s of %d "\r
414                         "in %d bytes rval.code %d, size=%d",\r
415                         td->name, edx, elements[edx].type->name,\r
416                         (int)LEFT, (int)rval.consumed, rval.code, (int)size);\r
417                 switch(rval.code) {\r
418                 case RC_OK:\r
419                         break;\r
420                 case RC_WMORE: /* More data expected */\r
421                         if(!SIZE_VIOLATION) {\r
422                                 ADVANCE(rval.consumed);\r
423                                 RETURN(RC_WMORE);\r
424                         }\r
425                         ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",\r
426                                 (long)ctx->left, (long)size);\r
427                         /* Fall through */\r
428                 case RC_FAIL: /* Fatal error */\r
429                         RETURN(RC_FAIL);\r
430                 } /* switch(rval) */\r
431                 \r
432                 ADVANCE(rval.consumed);\r
433           }     /* for(all structure members) */\r
434 \r
435         phase3:\r
436                 ctx->phase = 3;\r
437         /* Fall through */\r
438         case 3: /* 00 and other tags expected */\r
439         case 4: /* only 00's expected */\r
440 \r
441                 ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",\r
442                         td->name, (long)ctx->left, (long)size);\r
443 \r
444                 /*\r
445                  * Skip everything until the end of the SEQUENCE.\r
446                  */\r
447                 while(ctx->left) {\r
448                         ssize_t tl, ll;\r
449 \r
450                         tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);\r
451                         switch(tl) {\r
452                         case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);\r
453                                 /* Fall through */\r
454                         case -1: RETURN(RC_FAIL);\r
455                         }\r
456 \r
457                         /*\r
458                          * If expected <0><0>...\r
459                          */\r
460                         if(ctx->left < 0\r
461                                 && ((const uint8_t *)ptr)[0] == 0) {\r
462                                 if(LEFT < 2) {\r
463                                         if(SIZE_VIOLATION)\r
464                                                 RETURN(RC_FAIL);\r
465                                         else\r
466                                                 RETURN(RC_WMORE);\r
467                                 } else if(((const uint8_t *)ptr)[1] == 0) {\r
468                                         /*\r
469                                          * Correctly finished with <0><0>.\r
470                                          */\r
471                                         ADVANCE(2);\r
472                                         ctx->left++;\r
473                                         ctx->phase = 4;\r
474                                         continue;\r
475                                 }\r
476                         }\r
477 \r
478                         if(!IN_EXTENSION_GROUP(specs, td->elements_count)\r
479                         || ctx->phase == 4) {\r
480                                 ASN_DEBUG("Unexpected continuation "\r
481                                         "of a non-extensible type "\r
482                                         "%s (SEQUENCE): %s",\r
483                                         td->name,\r
484                                         ber_tlv_tag_string(tlv_tag));\r
485                                 RETURN(RC_FAIL);\r
486                         }\r
487 \r
488                         ll = ber_skip_length(opt_codec_ctx,\r
489                                 BER_TLV_CONSTRUCTED(ptr),\r
490                                 (const char *)ptr + tl, LEFT - tl);\r
491                         switch(ll) {\r
492                         case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);\r
493                                 /* Fall through */\r
494                         case -1: RETURN(RC_FAIL);\r
495                         }\r
496 \r
497                         ADVANCE(tl + ll);\r
498                 }\r
499 \r
500                 PHASE_OUT(ctx);\r
501         }\r
502         \r
503         RETURN(RC_OK);\r
504 }\r
505 \r
506 \r
507 /*\r
508  * The DER encoder of the SEQUENCE type.\r
509  */\r
510 asn_enc_rval_t\r
511 SEQUENCE_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,\r
512                     int tag_mode, ber_tlv_tag_t tag,\r
513                     asn_app_consume_bytes_f *cb, void *app_key) {\r
514     size_t computed_size = 0;\r
515         asn_enc_rval_t erval = {0,0,0};\r
516         ssize_t ret;\r
517         size_t edx;\r
518 \r
519         ASN_DEBUG("%s %s as SEQUENCE",\r
520                 cb?"Encoding":"Estimating", td->name);\r
521 \r
522         /*\r
523          * Gather the length of the underlying members sequence.\r
524          */\r
525         for(edx = 0; edx < td->elements_count; edx++) {\r
526                 asn_TYPE_member_t *elm = &td->elements[edx];\r
527 \r
528                 const void *memb_ptr;           /* Pointer to the member */\r
529         const void *const *memb_ptr2; /* Pointer to that pointer */\r
530 \r
531         if(elm->flags & ATF_POINTER) {\r
532             memb_ptr2 =\r
533                 (const void *const *)((const char *)sptr + elm->memb_offset);\r
534             if(!*memb_ptr2) {\r
535                                 ASN_DEBUG("Element %s %" ASN_PRI_SIZE " not present",\r
536                                         elm->name, edx);\r
537                                 if(elm->optional)\r
538                                         continue;\r
539                                 /* Mandatory element is missing */\r
540                                 ASN__ENCODE_FAILED;\r
541                         }\r
542                 } else {\r
543             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
544             memb_ptr2 = &memb_ptr;\r
545                 }\r
546 \r
547                 /* Eliminate default values */\r
548                 if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)\r
549                         continue;\r
550 \r
551                 erval = elm->type->op->der_encoder(elm->type, *memb_ptr2,\r
552                         elm->tag_mode, elm->tag,\r
553                         0, 0);\r
554                 if(erval.encoded == -1)\r
555                         return erval;\r
556                 computed_size += erval.encoded;\r
557                 ASN_DEBUG("Member %" ASN_PRI_SIZE " %s estimated %ld bytes",\r
558                         edx, elm->name, (long)erval.encoded);\r
559         }\r
560 \r
561         /*\r
562          * Encode the TLV for the sequence itself.\r
563          */\r
564         ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);\r
565         ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);\r
566         if(ret == -1)\r
567                 ASN__ENCODE_FAILED;\r
568         erval.encoded = computed_size + ret;\r
569 \r
570         if(!cb) ASN__ENCODED_OK(erval);\r
571 \r
572         /*\r
573          * Encode all members.\r
574          */\r
575         for(edx = 0; edx < td->elements_count; edx++) {\r
576                 asn_TYPE_member_t *elm = &td->elements[edx];\r
577                 asn_enc_rval_t tmperval = {0,0,0};\r
578         const void *memb_ptr;           /* Pointer to the member */\r
579         const void *const *memb_ptr2;   /* Pointer to that pointer */\r
580 \r
581         if(elm->flags & ATF_POINTER) {\r
582             memb_ptr2 =\r
583                 (const void *const *)((const char *)sptr + elm->memb_offset);\r
584             if(!*memb_ptr2) continue;\r
585                 } else {\r
586             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
587             memb_ptr2 = &memb_ptr;\r
588                 }\r
589 \r
590                 /* Eliminate default values */\r
591         if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)\r
592             continue;\r
593 \r
594                 tmperval = elm->type->op->der_encoder(elm->type, *memb_ptr2,\r
595                         elm->tag_mode, elm->tag, cb, app_key);\r
596                 if(tmperval.encoded == -1)\r
597                         return tmperval;\r
598                 computed_size -= tmperval.encoded;\r
599                 ASN_DEBUG("Member %" ASN_PRI_SIZE " %s of SEQUENCE %s encoded in %ld bytes",\r
600                         edx, elm->name, td->name, (long)tmperval.encoded);\r
601         }\r
602 \r
603         if(computed_size != 0)\r
604                 /*\r
605                  * Encoded size is not equal to the computed size.\r
606                  */\r
607                 ASN__ENCODE_FAILED;\r
608 \r
609         ASN__ENCODED_OK(erval);\r
610 }\r
611 \r
612 \r
613 #undef  XER_ADVANCE\r
614 #define XER_ADVANCE(num_bytes)           \\r
615     do {                                 \\r
616         size_t num = (num_bytes);        \\r
617         ptr = ((const char *)ptr) + num; \\r
618         size -= num;                     \\r
619         consumed_myself += num;          \\r
620     } while(0)\r
621 \r
622 /*\r
623  * Decode the XER (XML) data.\r
624  */\r
625 asn_dec_rval_t\r
626 SEQUENCE_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,\r
627                     const asn_TYPE_descriptor_t *td, void **struct_ptr,\r
628                     const char *opt_mname, const void *ptr, size_t size) {\r
629     /*\r
630          * Bring closer parts of structure description.\r
631          */\r
632         const asn_SEQUENCE_specifics_t *specs\r
633                 = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
634         asn_TYPE_member_t *elements = td->elements;\r
635         const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;\r
636 \r
637         /*\r
638          * ... and parts of the structure being constructed.\r
639          */\r
640         void *st = *struct_ptr; /* Target structure. */\r
641         asn_struct_ctx_t *ctx;  /* Decoder context */\r
642 \r
643         asn_dec_rval_t rval;            /* Return value from a decoder */\r
644         ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */\r
645         size_t edx;                     /* Element index */\r
646 \r
647         /*\r
648          * Create the target structure if it is not present already.\r
649          */\r
650         if(st == 0) {\r
651                 st = *struct_ptr = CALLOC(1, specs->struct_size);\r
652                 if(st == 0) RETURN(RC_FAIL);\r
653         }\r
654 \r
655         /*\r
656          * Restore parsing context.\r
657          */\r
658         ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);\r
659 \r
660 \r
661         /*\r
662          * Phases of XER/XML processing:\r
663          * Phase 0: Check that the opening tag matches our expectations.\r
664          * Phase 1: Processing body and reacting on closing tag.\r
665          * Phase 2: Processing inner type.\r
666          * Phase 3: Skipping unknown extensions.\r
667          * Phase 4: PHASED OUT\r
668          */\r
669         for(edx = ctx->step; ctx->phase <= 3;) {\r
670                 pxer_chunk_type_e ch_type;      /* XER chunk type */\r
671                 ssize_t ch_size;                /* Chunk size */\r
672                 xer_check_tag_e tcv;            /* Tag check value */\r
673                 asn_TYPE_member_t *elm;\r
674 \r
675                 /*\r
676                  * Go inside the inner member of a sequence.\r
677                  */\r
678                 if(ctx->phase == 2) {\r
679                         asn_dec_rval_t tmprval;\r
680                         void *memb_ptr_dontuse;         /* Pointer to the member */\r
681                         void **memb_ptr2;       /* Pointer to that pointer */\r
682 \r
683                         elm = &td->elements[edx];\r
684 \r
685                         if(elm->flags & ATF_POINTER) {\r
686                                 /* Member is a pointer to another structure */\r
687                                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
688                         } else {\r
689                                 memb_ptr_dontuse = (char *)st + elm->memb_offset;\r
690                                 memb_ptr2 = &memb_ptr_dontuse;  /* Only use of memb_ptr_dontuse */\r
691                         }\r
692 \r
693                         if(elm->flags & ATF_OPEN_TYPE) {\r
694                                 tmprval = OPEN_TYPE_xer_get(opt_codec_ctx, td, st, elm, ptr, size);\r
695                         } else {\r
696                                 /* Invoke the inner type decoder, m.b. multiple times */\r
697                                 tmprval = elm->type->op->xer_decoder(opt_codec_ctx,\r
698                                                 elm->type, memb_ptr2, elm->name,\r
699                                                 ptr, size);\r
700                         }\r
701                         XER_ADVANCE(tmprval.consumed);\r
702                         if(tmprval.code != RC_OK)\r
703                                 RETURN(tmprval.code);\r
704                         ctx->phase = 1; /* Back to body processing */\r
705                         ctx->step = ++edx;\r
706                         ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",\r
707                                 ctx->phase, ctx->step);\r
708                         /* Fall through */\r
709                 }\r
710 \r
711                 /*\r
712                  * Get the next part of the XML stream.\r
713                  */\r
714                 ch_size = xer_next_token(&ctx->context, ptr, size,\r
715                         &ch_type);\r
716                 if(ch_size == -1) {\r
717                     RETURN(RC_FAIL);\r
718                 } else {\r
719                         switch(ch_type) {\r
720                         case PXER_WMORE:\r
721                                 RETURN(RC_WMORE);\r
722                         case PXER_COMMENT:      /* Got XML comment */\r
723                         case PXER_TEXT:         /* Ignore free-standing text */\r
724                                 XER_ADVANCE(ch_size);   /* Skip silently */\r
725                                 continue;\r
726                         case PXER_TAG:\r
727                                 break;  /* Check the rest down there */\r
728                         }\r
729                 }\r
730 \r
731                 tcv = xer_check_tag(ptr, ch_size, xml_tag);\r
732                 ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",\r
733                         tcv, ctx->phase, xml_tag);\r
734 \r
735                 /* Skip the extensions section */\r
736                 if(ctx->phase == 3) {\r
737                         switch(xer_skip_unknown(tcv, &ctx->left)) {\r
738                         case -1:\r
739                                 ctx->phase = 4;\r
740                                 RETURN(RC_FAIL);\r
741                         case 0:\r
742                                 XER_ADVANCE(ch_size);\r
743                                 continue;\r
744                         case 1:\r
745                                 XER_ADVANCE(ch_size);\r
746                                 ctx->phase = 1;\r
747                                 continue;\r
748                         case 2:\r
749                                 ctx->phase = 1;\r
750                                 break;\r
751                         }\r
752                 }\r
753 \r
754                 switch(tcv) {\r
755                 case XCT_CLOSING:\r
756                         if(ctx->phase == 0) break;\r
757                         ctx->phase = 0;\r
758                         /* Fall through */\r
759                 case XCT_BOTH:\r
760             if(ctx->phase == 0) {\r
761                 if(edx >= td->elements_count ||\r
762                    /* Explicit OPTIONAL specs reaches the end */\r
763                    (edx + elements[edx].optional == td->elements_count) ||\r
764                    /* All extensions are optional */\r
765                    IN_EXTENSION_GROUP(specs, edx)) {\r
766                     XER_ADVANCE(ch_size);\r
767                                         ctx->phase = 4; /* Phase out */\r
768                                         RETURN(RC_OK);\r
769                                 } else {\r
770                                         ASN_DEBUG("Premature end of XER SEQUENCE");\r
771                                         RETURN(RC_FAIL);\r
772                                 }\r
773                         }\r
774                         /* Fall through */\r
775                 case XCT_OPENING:\r
776                         if(ctx->phase == 0) {\r
777                                 XER_ADVANCE(ch_size);\r
778                                 ctx->phase = 1; /* Processing body phase */\r
779                                 continue;\r
780                         }\r
781                         /* Fall through */\r
782                 case XCT_UNKNOWN_OP:\r
783                 case XCT_UNKNOWN_BO:\r
784 \r
785                         ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%" ASN_PRI_SIZE "",\r
786                                 tcv, ctx->phase, edx);\r
787                         if(ctx->phase != 1) {\r
788                                 break;  /* Really unexpected */\r
789                         }\r
790 \r
791                         if(edx < td->elements_count) {\r
792                                 /*\r
793                                  * Search which member corresponds to this tag.\r
794                                  */\r
795                                 size_t n;\r
796                                 size_t edx_end = edx + elements[edx].optional + 1;\r
797                                 if(edx_end > td->elements_count)\r
798                                         edx_end = td->elements_count;\r
799                                 for(n = edx; n < edx_end; n++) {\r
800                                         elm = &td->elements[n];\r
801                                         tcv = xer_check_tag(ptr, ch_size, elm->name);\r
802                                         switch(tcv) {\r
803                                         case XCT_BOTH:\r
804                                         case XCT_OPENING:\r
805                                                 /*\r
806                                                  * Process this member.\r
807                                                  */\r
808                                                 ctx->step = edx = n;\r
809                                                 ctx->phase = 2;\r
810                                                 break;\r
811                                         case XCT_UNKNOWN_OP:\r
812                                         case XCT_UNKNOWN_BO:\r
813                                                 continue;\r
814                                         default:\r
815                                                 n = edx_end;\r
816                                                 break;  /* Phase out */\r
817                                         }\r
818                                         break;\r
819                                 }\r
820                                 if(n != edx_end)\r
821                                         continue;\r
822                         } else {\r
823                                 ASN_DEBUG("Out of defined members: %" ASN_PRI_SIZE "/%u",\r
824                                         edx, td->elements_count);\r
825                         }\r
826 \r
827                         /* It is expected extension */\r
828                         if(IN_EXTENSION_GROUP(specs,\r
829                                 edx + (edx < td->elements_count\r
830                                         ? elements[edx].optional : 0))) {\r
831                                 ASN_DEBUG("Got anticipated extension at %" ASN_PRI_SIZE "",\r
832                                         edx);\r
833                                 /*\r
834                                  * Check for (XCT_BOTH or XCT_UNKNOWN_BO)\r
835                                  * By using a mask. Only record a pure\r
836                                  * <opening> tags.\r
837                                  */\r
838                                 if(tcv & XCT_CLOSING) {\r
839                                         /* Found </extension> without body */\r
840                                 } else {\r
841                                         ctx->left = 1;\r
842                                         ctx->phase = 3; /* Skip ...'s */\r
843                                 }\r
844                                 XER_ADVANCE(ch_size);\r
845                                 continue;\r
846                         }\r
847 \r
848                         /* Fall through */\r
849                 default:\r
850                         break;\r
851                 }\r
852 \r
853                 ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",\r
854                         size>0?((const char *)ptr)[0]:'.',\r
855                         size>1?((const char *)ptr)[1]:'.',\r
856                         size>2?((const char *)ptr)[2]:'.',\r
857                         size>3?((const char *)ptr)[3]:'.',\r
858                         size>4?((const char *)ptr)[4]:'.',\r
859                         size>5?((const char *)ptr)[5]:'.');\r
860                 break;\r
861         }\r
862 \r
863         ctx->phase = 4; /* "Phase out" on hard failure */\r
864         RETURN(RC_FAIL);\r
865 }\r
866 \r
867 asn_enc_rval_t\r
868 SEQUENCE_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,\r
869                     int ilevel, enum xer_encoder_flags_e flags,\r
870                     asn_app_consume_bytes_f *cb, void *app_key) {\r
871     asn_enc_rval_t er = {0,0,0};\r
872     int xcan = (flags & XER_F_CANONICAL);\r
873     asn_TYPE_descriptor_t *tmp_def_val_td = 0;\r
874     void *tmp_def_val = 0;\r
875     size_t edx;\r
876 \r
877     if(!sptr) ASN__ENCODE_FAILED;\r
878 \r
879     er.encoded = 0;\r
880 \r
881     for(edx = 0; edx < td->elements_count; edx++) {\r
882         asn_enc_rval_t tmper = {0,0,0};\r
883         asn_TYPE_member_t *elm = &td->elements[edx];\r
884         const void *memb_ptr;\r
885         const char *mname = elm->name;\r
886         unsigned int mlen = strlen(mname);\r
887 \r
888         if(elm->flags & ATF_POINTER) {\r
889             memb_ptr =\r
890                 *(const void *const *)((const char *)sptr + elm->memb_offset);\r
891             if(!memb_ptr) {\r
892                 assert(tmp_def_val == 0);\r
893                 if(elm->default_value_set) {\r
894                     if(elm->default_value_set(&tmp_def_val)) {\r
895                         ASN__ENCODE_FAILED;\r
896                     } else {\r
897                         memb_ptr = tmp_def_val;\r
898                         tmp_def_val_td = elm->type;\r
899                     }\r
900                 } else if(elm->optional) {\r
901                     continue;\r
902                 } else {\r
903                     /* Mandatory element is missing */\r
904                     ASN__ENCODE_FAILED;\r
905                 }\r
906             }\r
907         } else {\r
908             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
909         }\r
910 \r
911         if(!xcan) ASN__TEXT_INDENT(1, ilevel);\r
912         ASN__CALLBACK3("<", 1, mname, mlen, ">", 1);\r
913 \r
914         /* Print the member itself */\r
915         tmper = elm->type->op->xer_encoder(elm->type, memb_ptr, ilevel + 1,\r
916                                            flags, cb, app_key);\r
917         if(tmp_def_val) {\r
918             ASN_STRUCT_FREE(*tmp_def_val_td, tmp_def_val);\r
919             tmp_def_val = 0;\r
920         }\r
921         if(tmper.encoded == -1) return tmper;\r
922         er.encoded += tmper.encoded;\r
923 \r
924         ASN__CALLBACK3("</", 2, mname, mlen, ">", 1);\r
925     }\r
926 \r
927     if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);\r
928 \r
929     ASN__ENCODED_OK(er);\r
930 cb_failed:\r
931     if(tmp_def_val) ASN_STRUCT_FREE(*tmp_def_val_td, tmp_def_val);\r
932     ASN__ENCODE_FAILED;\r
933 }\r
934 \r
935 int\r
936 SEQUENCE_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,\r
937                asn_app_consume_bytes_f *cb, void *app_key) {\r
938     size_t edx;\r
939         int ret;\r
940 \r
941         if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;\r
942 \r
943         /* Dump preamble */\r
944         if(cb(td->name, strlen(td->name), app_key) < 0\r
945         || cb(" ::= {", 6, app_key) < 0)\r
946                 return -1;\r
947 \r
948         for(edx = 0; edx < td->elements_count; edx++) {\r
949                 asn_TYPE_member_t *elm = &td->elements[edx];\r
950                 const void *memb_ptr;\r
951 \r
952                 if(elm->flags & ATF_POINTER) {\r
953                         memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);\r
954                         if(!memb_ptr) {\r
955                                 if(elm->optional) continue;\r
956                                 /* Print <absent> line */\r
957                                 /* Fall through */\r
958                         }\r
959                 } else {\r
960                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
961                 }\r
962 \r
963                 /* Indentation */\r
964                 _i_INDENT(1);\r
965 \r
966                 /* Print the member's name and stuff */\r
967                 if(cb(elm->name, strlen(elm->name), app_key) < 0\r
968                 || cb(": ", 2, app_key) < 0)\r
969                         return -1;\r
970 \r
971                 /* Print the member itself */\r
972                 ret = elm->type->op->print_struct(elm->type, memb_ptr, ilevel + 1,\r
973                         cb, app_key);\r
974                 if(ret) return ret;\r
975         }\r
976 \r
977         ilevel--;\r
978         _i_INDENT(1);\r
979 \r
980         return (cb("}", 1, app_key) < 0) ? -1 : 0;\r
981 }\r
982 \r
983 void\r
984 SEQUENCE_free(const asn_TYPE_descriptor_t *td, void *sptr,\r
985               enum asn_struct_free_method method) {\r
986     size_t edx;\r
987     const asn_SEQUENCE_specifics_t *specs =\r
988         (const asn_SEQUENCE_specifics_t *)td->specifics;\r
989     asn_struct_ctx_t *ctx; /* Decoder context */\r
990 \r
991         if(!td || !sptr)\r
992                 return;\r
993 \r
994         ASN_DEBUG("Freeing %s as SEQUENCE", td->name);\r
995 \r
996         for(edx = 0; edx < td->elements_count; edx++) {\r
997                 asn_TYPE_member_t *elm = &td->elements[edx];\r
998                 void *memb_ptr;\r
999                 if(elm->flags & ATF_POINTER) {\r
1000                         memb_ptr = *(void **)((char *)sptr + elm->memb_offset);\r
1001                         if(memb_ptr)\r
1002                                 ASN_STRUCT_FREE(*elm->type, memb_ptr);\r
1003                 } else {\r
1004                         memb_ptr = (void *)((char *)sptr + elm->memb_offset);\r
1005                         ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);\r
1006                 }\r
1007         }\r
1008 \r
1009         /* Clean parsing context */\r
1010         ctx = (asn_struct_ctx_t *)((char *)sptr + specs->ctx_offset);\r
1011         FREEMEM(ctx->ptr);\r
1012 \r
1013     switch(method) {\r
1014     case ASFM_FREE_EVERYTHING:\r
1015         FREEMEM(sptr);\r
1016         break;\r
1017     case ASFM_FREE_UNDERLYING:\r
1018         break;\r
1019     case ASFM_FREE_UNDERLYING_AND_RESET:\r
1020         memset(\r
1021             sptr, 0,\r
1022             ((const asn_SEQUENCE_specifics_t *)(td->specifics))->struct_size);\r
1023         break;\r
1024     }\r
1025 }\r
1026 \r
1027 int\r
1028 SEQUENCE_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,\r
1029                     asn_app_constraint_failed_f *ctfailcb, void *app_key) {\r
1030     size_t edx;\r
1031 \r
1032         if(!sptr) {\r
1033                 ASN__CTFAIL(app_key, td, sptr,\r
1034                         "%s: value not given (%s:%d)",\r
1035                         td->name, __FILE__, __LINE__);\r
1036                 return -1;\r
1037         }\r
1038 \r
1039         /*\r
1040          * Iterate over structure members and check their validity.\r
1041          */\r
1042         for(edx = 0; edx < td->elements_count; edx++) {\r
1043                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1044                 const void *memb_ptr;\r
1045 \r
1046                 if(elm->flags & ATF_POINTER) {\r
1047                         memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);\r
1048                         if(!memb_ptr) {\r
1049                                 if(elm->optional)\r
1050                                         continue;\r
1051                                 ASN__CTFAIL(app_key, td, sptr,\r
1052                                 "%s: mandatory element %s absent (%s:%d)",\r
1053                                 td->name, elm->name, __FILE__, __LINE__);\r
1054                                 return -1;\r
1055                         }\r
1056                 } else {\r
1057                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1058                 }\r
1059 \r
1060                 if(elm->encoding_constraints.general_constraints) {\r
1061                         int ret = elm->encoding_constraints.general_constraints(elm->type, memb_ptr,\r
1062                                 ctfailcb, app_key);\r
1063                         if(ret) return ret;\r
1064                 } else {\r
1065                         return elm->type->encoding_constraints.general_constraints(elm->type,\r
1066                                 memb_ptr, ctfailcb, app_key);\r
1067                 }\r
1068         }\r
1069 \r
1070         return 0;\r
1071 }\r
1072 \r
1073 #ifndef ASN_DISABLE_PER_SUPPORT\r
1074 \r
1075 asn_dec_rval_t\r
1076 SEQUENCE_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,\r
1077                      const asn_TYPE_descriptor_t *td,\r
1078                      const asn_per_constraints_t *constraints, void **sptr,\r
1079                      asn_per_data_t *pd) {\r
1080     const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1081         void *st = *sptr;       /* Target structure. */\r
1082         int extpresent;         /* Extension additions are present */\r
1083         uint8_t *opres;         /* Presence of optional root members */\r
1084         asn_per_data_t opmd;\r
1085         asn_dec_rval_t rv;\r
1086         size_t edx;\r
1087 \r
1088         (void)constraints;\r
1089 \r
1090         if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))\r
1091                 ASN__DECODE_FAILED;\r
1092 \r
1093         if(!st) {\r
1094                 st = *sptr = CALLOC(1, specs->struct_size);\r
1095                 if(!st) ASN__DECODE_FAILED;\r
1096         }\r
1097 \r
1098         ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);\r
1099 \r
1100         /* Handle extensions */\r
1101         if(specs->first_extension < 0) {\r
1102                 extpresent = 0;\r
1103         } else {\r
1104                 extpresent = per_get_few_bits(pd, 1);\r
1105                 if(extpresent < 0) ASN__DECODE_STARVED;\r
1106         }\r
1107 \r
1108         /* Prepare a place and read-in the presence bitmap */\r
1109         memset(&opmd, 0, sizeof(opmd));\r
1110         if(specs->roms_count) {\r
1111                 opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);\r
1112                 if(!opres) ASN__DECODE_FAILED;\r
1113                 /* Get the presence map */\r
1114                 if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {\r
1115                         FREEMEM(opres);\r
1116                         ASN__DECODE_STARVED;\r
1117                 }\r
1118                 opmd.buffer = opres;\r
1119                 opmd.nbits = specs->roms_count;\r
1120                 ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",\r
1121                         td->name, specs->roms_count, *opres);\r
1122         } else {\r
1123                 opres = 0;\r
1124         }\r
1125 \r
1126         /*\r
1127          * Get the sequence ROOT elements.\r
1128          */\r
1129     for(edx = 0;\r
1130         edx < (specs->first_extension < 0 ? td->elements_count\r
1131                                           : (size_t)specs->first_extension);\r
1132         edx++) {\r
1133         asn_TYPE_member_t *elm = &td->elements[edx];\r
1134                 void *memb_ptr;         /* Pointer to the member */\r
1135                 void **memb_ptr2;       /* Pointer to that pointer */\r
1136 \r
1137                 assert(!IN_EXTENSION_GROUP(specs, edx));\r
1138 \r
1139                 /* Fetch the pointer to this member */\r
1140                 if(elm->flags & ATF_POINTER) {\r
1141                         memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
1142                 } else {\r
1143                         memb_ptr = (char *)st + elm->memb_offset;\r
1144                         memb_ptr2 = &memb_ptr;\r
1145                 }\r
1146 \r
1147                 /* Deal with optionality */\r
1148                 if(elm->optional) {\r
1149                         int present = per_get_few_bits(&opmd, 1);\r
1150                         ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",\r
1151                                 td->name, elm->name, present,\r
1152                                 (int)opmd.nboff, (int)opmd.nbits);\r
1153                         if(present == 0) {\r
1154                                 /* This element is not present */\r
1155                                 if(elm->default_value_set) {\r
1156                                         /* Fill-in DEFAULT */\r
1157                                         if(elm->default_value_set(memb_ptr2)) {\r
1158                                                 FREEMEM(opres);\r
1159                                                 ASN__DECODE_FAILED;\r
1160                                         }\r
1161                                         ASN_DEBUG("Filled-in default");\r
1162                                 }\r
1163                                 /* The member is just not present */\r
1164                                 continue;\r
1165                         }\r
1166                         /* Fall through */\r
1167                 }\r
1168 \r
1169                 /* Fetch the member from the stream */\r
1170                 ASN_DEBUG("Decoding member \"%s\" in %s", elm->name, td->name);\r
1171 \r
1172                 if(elm->flags & ATF_OPEN_TYPE) {\r
1173                         rv = OPEN_TYPE_uper_get(opt_codec_ctx, td, st, elm, pd);\r
1174                 } else {\r
1175                         rv = elm->type->op->uper_decoder(opt_codec_ctx, elm->type,\r
1176                                         elm->encoding_constraints.per_constraints, memb_ptr2, pd);\r
1177                 }\r
1178                 if(rv.code != RC_OK) {\r
1179                         ASN_DEBUG("Failed decode %s in %s",\r
1180                                 elm->name, td->name);\r
1181                         FREEMEM(opres);\r
1182                         return rv;\r
1183                 }\r
1184         }\r
1185 \r
1186         /* Optionality map is not needed anymore */\r
1187         FREEMEM(opres);\r
1188 \r
1189         /*\r
1190          * Deal with extensions.\r
1191          */\r
1192         if(extpresent) {\r
1193                 ssize_t bmlength;\r
1194                 uint8_t *epres;         /* Presence of extension members */\r
1195                 asn_per_data_t epmd;\r
1196 \r
1197                 bmlength = uper_get_nslength(pd);\r
1198                 if(bmlength < 0) ASN__DECODE_STARVED;\r
1199 \r
1200                 ASN_DEBUG("Extensions %" ASN_PRI_SSIZE " present in %s", bmlength, td->name);\r
1201 \r
1202                 epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);\r
1203                 if(!epres) ASN__DECODE_STARVED;\r
1204 \r
1205                 /* Get the extensions map */\r
1206                 if(per_get_many_bits(pd, epres, 0, bmlength)) {\r
1207                         FREEMEM(epres);\r
1208                         ASN__DECODE_STARVED;\r
1209                 }\r
1210 \r
1211                 memset(&epmd, 0, sizeof(epmd));\r
1212                 epmd.buffer = epres;\r
1213                 epmd.nbits = bmlength;\r
1214                 ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)",\r
1215                         td->name, (long)bmlength, *epres);\r
1216 \r
1217             /* Go over extensions and read them in */\r
1218         for(edx = specs->first_extension; edx < td->elements_count; edx++) {\r
1219             asn_TYPE_member_t *elm = &td->elements[edx];\r
1220             void *memb_ptr;   /* Pointer to the member */\r
1221             void **memb_ptr2; /* Pointer to that pointer */\r
1222             int present;\r
1223 \r
1224             /* Fetch the pointer to this member */\r
1225             if(elm->flags & ATF_POINTER) {\r
1226                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
1227             } else {\r
1228                 memb_ptr = (void *)((char *)st + elm->memb_offset);\r
1229                 memb_ptr2 = &memb_ptr;\r
1230             }\r
1231 \r
1232             present = per_get_few_bits(&epmd, 1);\r
1233             if(present <= 0) {\r
1234                 if(present < 0) break; /* No more extensions */\r
1235                 continue;\r
1236             }\r
1237 \r
1238             ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name,\r
1239                       *memb_ptr2);\r
1240             rv = uper_open_type_get(opt_codec_ctx, elm->type,\r
1241                                     elm->encoding_constraints.per_constraints,\r
1242                                     memb_ptr2, pd);\r
1243             if(rv.code != RC_OK) {\r
1244                 FREEMEM(epres);\r
1245                 return rv;\r
1246             }\r
1247             }\r
1248 \r
1249                 /* Skip over overflow extensions which aren't present\r
1250                  * in this system's version of the protocol */\r
1251                 for(;;) {\r
1252                         ASN_DEBUG("Getting overflow extensions");\r
1253                         switch(per_get_few_bits(&epmd, 1)) {\r
1254                         case -1: break;\r
1255                         case 0: continue;\r
1256                         default:\r
1257                                 if(uper_open_type_skip(opt_codec_ctx, pd)) {\r
1258                                         FREEMEM(epres);\r
1259                                         ASN__DECODE_STARVED;\r
1260                                 }\r
1261                 ASN_DEBUG("Skipped overflow extension");\r
1262                 continue;\r
1263                         }\r
1264                         break;\r
1265                 }\r
1266 \r
1267                 FREEMEM(epres);\r
1268         }\r
1269 \r
1270     if(specs->first_extension >= 0) {\r
1271         unsigned i;\r
1272         /* Fill DEFAULT members in extensions */\r
1273         for(i = specs->roms_count; i < specs->roms_count + specs->aoms_count;\r
1274             i++) {\r
1275             asn_TYPE_member_t *elm;\r
1276             void **memb_ptr2; /* Pointer to member pointer */\r
1277 \r
1278             edx = specs->oms[i];\r
1279             elm = &td->elements[edx];\r
1280 \r
1281             if(!elm->default_value_set) continue;\r
1282 \r
1283             /* Fetch the pointer to this member */\r
1284             if(elm->flags & ATF_POINTER) {\r
1285                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
1286                 if(*memb_ptr2) continue;\r
1287             } else {\r
1288                 continue; /* Extensions are all optionals */\r
1289             }\r
1290 \r
1291             /* Set default value */\r
1292             if(elm->default_value_set(memb_ptr2)) {\r
1293                 ASN__DECODE_FAILED;\r
1294             }\r
1295         }\r
1296     }\r
1297 \r
1298         rv.consumed = 0;\r
1299         rv.code = RC_OK;\r
1300         return rv;\r
1301 }\r
1302 \r
1303 static int\r
1304 SEQUENCE__handle_extensions(const asn_TYPE_descriptor_t *td, const void *sptr,\r
1305                             asn_per_outp_t *po1, asn_per_outp_t *po2) {\r
1306     const asn_SEQUENCE_specifics_t *specs =\r
1307         (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1308     int exts_present = 0;\r
1309     int exts_count = 0;\r
1310     size_t edx;\r
1311 \r
1312     if(specs->first_extension < 0) {\r
1313         return 0;\r
1314     }\r
1315 \r
1316     /* Find out which extensions are present */\r
1317     for(edx = specs->first_extension; edx < td->elements_count; edx++) {\r
1318         asn_TYPE_member_t *elm = &td->elements[edx];\r
1319         const void *memb_ptr;         /* Pointer to the member */\r
1320         const void *const *memb_ptr2; /* Pointer to that pointer */\r
1321         int present;\r
1322 \r
1323         /* Fetch the pointer to this member */\r
1324         if(elm->flags & ATF_POINTER) {\r
1325             memb_ptr2 =\r
1326                 (const void *const *)((const char *)sptr + elm->memb_offset);\r
1327             present = (*memb_ptr2 != 0);\r
1328         } else {\r
1329             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1330             memb_ptr2 = &memb_ptr;\r
1331                         present = 1;\r
1332                 }\r
1333 \r
1334         ASN_DEBUG("checking %s:%s (@%" ASN_PRI_SIZE ") present => %d", elm->name,\r
1335                   elm->type->name, edx, present);\r
1336         exts_count++;\r
1337         exts_present += present;\r
1338 \r
1339         /* Encode as presence marker */\r
1340         if(po1 && per_put_few_bits(po1, present, 1)) {\r
1341             return -1;\r
1342         }\r
1343         /* Encode as open type field */\r
1344         if(po2 && present\r
1345            && uper_open_type_put(elm->type,\r
1346                                  elm->encoding_constraints.per_constraints,\r
1347                                  *memb_ptr2, po2))\r
1348             return -1;\r
1349     }\r
1350 \r
1351     return exts_present ? exts_count : 0;\r
1352 }\r
1353 \r
1354 asn_enc_rval_t\r
1355 SEQUENCE_encode_uper(const asn_TYPE_descriptor_t *td,\r
1356                      const asn_per_constraints_t *constraints, const void *sptr,\r
1357                      asn_per_outp_t *po) {\r
1358     const asn_SEQUENCE_specifics_t *specs\r
1359                 = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1360         asn_enc_rval_t er = {0,0,0};\r
1361         int n_extensions;\r
1362         size_t edx;\r
1363         size_t i;\r
1364 \r
1365         (void)constraints;\r
1366 \r
1367         if(!sptr)\r
1368                 ASN__ENCODE_FAILED;\r
1369 \r
1370         er.encoded = 0;\r
1371 \r
1372         ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);\r
1373 \r
1374         /*\r
1375          * X.691#18.1 Whether structure is extensible\r
1376          * and whether to encode extensions\r
1377          */\r
1378     if(specs->first_extension < 0) {\r
1379         n_extensions = 0; /* There are no extensions to encode */\r
1380     } else {\r
1381         n_extensions = SEQUENCE__handle_extensions(td, sptr, 0, 0);\r
1382         if(n_extensions < 0) ASN__ENCODE_FAILED;\r
1383         if(per_put_few_bits(po, n_extensions ? 1 : 0, 1)) {\r
1384             ASN__ENCODE_FAILED;\r
1385         }\r
1386     }\r
1387 \r
1388         /* Encode a presence bitmap */\r
1389         for(i = 0; i < specs->roms_count; i++) {\r
1390                 asn_TYPE_member_t *elm;\r
1391                 const void *memb_ptr;           /* Pointer to the member */\r
1392         const void *const *memb_ptr2; /* Pointer to that pointer */\r
1393         int present;\r
1394 \r
1395                 edx = specs->oms[i];\r
1396                 elm = &td->elements[edx];\r
1397 \r
1398                 /* Fetch the pointer to this member */\r
1399                 if(elm->flags & ATF_POINTER) {\r
1400             memb_ptr2 =\r
1401                 (const void *const *)((const char *)sptr + elm->memb_offset);\r
1402             present = (*memb_ptr2 != 0);\r
1403                 } else {\r
1404             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1405             memb_ptr2 = &memb_ptr;\r
1406                         present = 1;\r
1407                 }\r
1408 \r
1409                 /* Eliminate default values */\r
1410         if(present && elm->default_value_cmp\r
1411            && elm->default_value_cmp(*memb_ptr2) == 0)\r
1412             present = 0;\r
1413 \r
1414                 ASN_DEBUG("Element %s %s %s->%s is %s",\r
1415                         elm->flags & ATF_POINTER ? "ptr" : "inline",\r
1416                         elm->default_value_cmp ? "def" : "wtv",\r
1417                         td->name, elm->name, present ? "present" : "absent");\r
1418                 if(per_put_few_bits(po, present, 1))\r
1419                         ASN__ENCODE_FAILED;\r
1420         }\r
1421 \r
1422         /*\r
1423          * Encode the sequence ROOT elements.\r
1424          */\r
1425     ASN_DEBUG("first_extension = %d, elements = %d", specs->first_extension,\r
1426               td->elements_count);\r
1427         for(edx = 0;\r
1428                 edx < ((specs->first_extension < 0) ? td->elements_count\r
1429                                             : (size_t)specs->first_extension);\r
1430                 edx++) {\r
1431                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1432                 const void *memb_ptr;         /* Pointer to the member */\r
1433                 const void *const *memb_ptr2; /* Pointer to that pointer */\r
1434 \r
1435                 ASN_DEBUG("About to encode %s", elm->type->name);\r
1436 \r
1437                 /* Fetch the pointer to this member */\r
1438                 if(elm->flags & ATF_POINTER) {\r
1439             memb_ptr2 =\r
1440                 (const void *const *)((const char *)sptr + elm->memb_offset);\r
1441             if(!*memb_ptr2) {\r
1442                                 ASN_DEBUG("Element %s %" ASN_PRI_SIZE " not present",\r
1443                                         elm->name, edx);\r
1444                                 if(elm->optional)\r
1445                                         continue;\r
1446                                 /* Mandatory element is missing */\r
1447                                 ASN__ENCODE_FAILED;\r
1448                         }\r
1449                 } else {\r
1450             memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1451             memb_ptr2 = &memb_ptr;\r
1452                 }\r
1453 \r
1454                 /* Eliminate default values */\r
1455                 if(elm->default_value_cmp && elm->default_value_cmp(*memb_ptr2) == 0)\r
1456                         continue;\r
1457 \r
1458         ASN_DEBUG("Encoding %s->%s:%s", td->name, elm->name, elm->type->name);\r
1459         er = elm->type->op->uper_encoder(\r
1460             elm->type, elm->encoding_constraints.per_constraints, *memb_ptr2,\r
1461             po);\r
1462         if(er.encoded == -1) return er;\r
1463     }\r
1464 \r
1465         /* No extensions to encode */\r
1466         if(!n_extensions) ASN__ENCODED_OK(er);\r
1467 \r
1468         ASN_DEBUG("Length of extensions %d bit-map", n_extensions);\r
1469         /* #18.8. Write down the presence bit-map length. */\r
1470         if(uper_put_nslength(po, n_extensions))\r
1471                 ASN__ENCODE_FAILED;\r
1472 \r
1473         ASN_DEBUG("Bit-map of %d elements", n_extensions);\r
1474         /* #18.7. Encoding the extensions presence bit-map. */\r
1475         /* TODO: act upon NOTE in #18.7 for canonical PER */\r
1476         if(SEQUENCE__handle_extensions(td, sptr, po, 0) != n_extensions)\r
1477                 ASN__ENCODE_FAILED;\r
1478 \r
1479         ASN_DEBUG("Writing %d extensions", n_extensions);\r
1480         /* #18.9. Encode extensions as open type fields. */\r
1481         if(SEQUENCE__handle_extensions(td, sptr, 0, po) != n_extensions)\r
1482                 ASN__ENCODE_FAILED;\r
1483 \r
1484         ASN__ENCODED_OK(er);\r
1485 }\r
1486 \r
1487 asn_dec_rval_t\r
1488 SEQUENCE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,\r
1489                      const asn_TYPE_descriptor_t *td,\r
1490                      const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {\r
1491         const asn_SEQUENCE_specifics_t *specs = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1492         void *st = *sptr;       /* Target structure. */\r
1493         int extpresent;         /* Extension additions are present */\r
1494         uint8_t *opres;         /* Presence of optional root members */\r
1495         asn_per_data_t opmd;\r
1496         asn_dec_rval_t rv;\r
1497         size_t edx;\r
1498 \r
1499         (void)constraints;\r
1500 \r
1501         if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))\r
1502                 ASN__DECODE_FAILED;\r
1503 \r
1504         if(!st) {\r
1505                 st = *sptr = CALLOC(1, specs->struct_size);\r
1506                 if(!st) ASN__DECODE_FAILED;\r
1507         }\r
1508 \r
1509         ASN_DEBUG("Decoding %s as SEQUENCE (APER)", td->name);\r
1510 \r
1511         /* Handle extensions */\r
1512         if(specs->first_extension < 0) {\r
1513                 extpresent = 0;\r
1514         } else {\r
1515                 extpresent = per_get_few_bits(pd, 1);\r
1516                 if(extpresent < 0) ASN__DECODE_STARVED;\r
1517         }\r
1518 \r
1519         /* Prepare a place and read-in the presence bitmap */\r
1520         memset(&opmd, 0, sizeof(opmd));\r
1521         if(specs->roms_count) {\r
1522                 opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);\r
1523                 if(!opres) ASN__DECODE_FAILED;\r
1524                 /* Get the presence map */\r
1525                 if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {\r
1526                         FREEMEM(opres);\r
1527                         ASN__DECODE_STARVED;\r
1528                 }\r
1529                 opmd.buffer = opres;\r
1530                 opmd.nbits = specs->roms_count;\r
1531                 ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",\r
1532                           td->name, specs->roms_count, *opres);\r
1533         } else {\r
1534                 opres = 0;\r
1535         }\r
1536 \r
1537         /*\r
1538          * Get the sequence ROOT elements.\r
1539          */\r
1540         for(edx = 0; edx < td->elements_count; edx++) {\r
1541                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1542                 void *memb_ptr;         /* Pointer to the member */\r
1543                 void **memb_ptr2;       /* Pointer to that pointer */\r
1544 #if 0\r
1545                 int padding;\r
1546 #endif\r
1547 \r
1548                 if(IN_EXTENSION_GROUP(specs, edx))\r
1549                         continue;\r
1550 \r
1551                 /* Fetch the pointer to this member */\r
1552                 if(elm->flags & ATF_POINTER) {\r
1553                         memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
1554                 } else {\r
1555                         memb_ptr = (char *)st + elm->memb_offset;\r
1556                         memb_ptr2 = &memb_ptr;\r
1557                 }\r
1558 #if 0\r
1559                 /* Get Padding */\r
1560                 padding = (8 - (pd->moved % 8)) % 8;\r
1561                 if(padding > 0)\r
1562                         ASN_DEBUG("For element %s,offset= %ld Padding bits = %d", td->name, pd->moved, padding);\r
1563 #if 0 /* old way of removing padding */\r
1564                 per_get_few_bits(pd, padding);\r
1565 #else /* Experimental fix proposed by @mhanna123 */\r
1566                 if(edx != (td->elements_count-1))\r
1567                         per_get_few_bits(pd, padding);\r
1568                 else {\r
1569                         if(specs->roms_count && (padding > 0))\r
1570                                 ASN_DEBUG(">>>>> not skipping padding of %d bits for element:%ld out of %d", padding, edx, td->elements_count);\r
1571                         else\r
1572                                 per_get_few_bits(pd, padding);\r
1573                 }\r
1574 #endif /* dealing with padding */\r
1575 #endif\r
1576                 /* Deal with optionality */\r
1577                 if(elm->optional) {\r
1578                         int present = per_get_few_bits(&opmd, 1);\r
1579                         ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",\r
1580                                   td->name, elm->name, present,\r
1581                                   (int)opmd.nboff, (int)opmd.nbits);\r
1582                         if(present == 0) {\r
1583                                 /* This element is not present */\r
1584                                 if(elm->default_value_set) {\r
1585                                         /* Fill-in DEFAULT */\r
1586                                         if(elm->default_value_set(memb_ptr2)) {\r
1587                                                 FREEMEM(opres);\r
1588                                                 ASN__DECODE_FAILED;\r
1589                                         }\r
1590                                         ASN_DEBUG("Filled-in default");\r
1591                                 }\r
1592                                 /* The member is just not present */\r
1593                                 continue;\r
1594                         }\r
1595                         /* Fall through */\r
1596                 }\r
1597 \r
1598                 /* Fetch the member from the stream */\r
1599                 ASN_DEBUG("Decoding member \"%s\" in %s", elm->name, td->name);\r
1600 \r
1601                 if(elm->flags & ATF_OPEN_TYPE) {\r
1602                         rv = OPEN_TYPE_aper_get(opt_codec_ctx, td, st, elm, pd);\r
1603                 } else {\r
1604                         rv = elm->type->op->aper_decoder(opt_codec_ctx, elm->type,\r
1605                                         elm->encoding_constraints.per_constraints, memb_ptr2, pd);\r
1606                 }\r
1607                 if(rv.code != RC_OK) {\r
1608                         ASN_DEBUG("Failed decode %s in %s",\r
1609                                   elm->name, td->name);\r
1610                         FREEMEM(opres);\r
1611                         return rv;\r
1612                 }\r
1613         }\r
1614 \r
1615         /* Optionality map is not needed anymore */\r
1616         FREEMEM(opres);\r
1617 \r
1618         /*\r
1619          * Deal with extensions.\r
1620          */\r
1621         if(extpresent) {\r
1622                 ssize_t bmlength;\r
1623                 uint8_t *epres;         /* Presence of extension members */\r
1624                 asn_per_data_t epmd;\r
1625 \r
1626                 bmlength = aper_get_nslength(pd);\r
1627                 if(bmlength < 0) ASN__DECODE_STARVED;\r
1628 \r
1629                 ASN_DEBUG("Extensions %" ASN_PRI_SSIZE " present in %s", bmlength, td->name);\r
1630 \r
1631                 epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);\r
1632                 if(!epres) ASN__DECODE_STARVED;\r
1633 \r
1634                 /* Get the extensions map */\r
1635                 if(per_get_many_bits(pd, epres, 0, bmlength))\r
1636                         ASN__DECODE_STARVED;\r
1637 \r
1638                 memset(&epmd, 0, sizeof(epmd));\r
1639                 epmd.buffer = epres;\r
1640                 epmd.nbits = bmlength;\r
1641                 ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)",\r
1642                           td->name, bmlength, *epres);\r
1643 \r
1644                 /* Go over extensions and read them in */\r
1645                 for(edx = specs->first_extension; edx < td->elements_count; edx++) {\r
1646                         asn_TYPE_member_t *elm = &td->elements[edx];\r
1647                         void *memb_ptr;         /* Pointer to the member */\r
1648                         void **memb_ptr2;       /* Pointer to that pointer */\r
1649                         int present;\r
1650 \r
1651                         if(!IN_EXTENSION_GROUP(specs, edx)) {\r
1652                                 ASN_DEBUG("%ld is not extension", edx);\r
1653                                 continue;\r
1654                         }\r
1655 \r
1656                         /* Fetch the pointer to this member */\r
1657                         if(elm->flags & ATF_POINTER) {\r
1658                                 memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
1659                         } else {\r
1660                                 memb_ptr = (void *)((char *)st + elm->memb_offset);\r
1661                                 memb_ptr2 = &memb_ptr;\r
1662                         }\r
1663 \r
1664                         present = per_get_few_bits(&epmd, 1);\r
1665                         if(present <= 0) {\r
1666                                 if(present < 0) break;  /* No more extensions */\r
1667                                 continue;\r
1668                         }\r
1669 \r
1670                         ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);\r
1671                         rv = aper_open_type_get(opt_codec_ctx, elm->type,\r
1672                                                 elm->encoding_constraints.per_constraints, memb_ptr2, pd);\r
1673                         if(rv.code != RC_OK) {\r
1674                                 FREEMEM(epres);\r
1675                                 return rv;\r
1676                         }\r
1677                 }\r
1678 \r
1679                 /* Skip over overflow extensions which aren't present\r
1680                  * in this system's version of the protocol */\r
1681                 for(;;) {\r
1682                         ASN_DEBUG("Getting overflow extensions");\r
1683                         switch(per_get_few_bits(&epmd, 1)) {\r
1684                         case -1:\r
1685                                 break;\r
1686                         case 0:\r
1687                                 continue;\r
1688                         default:\r
1689                                 if(aper_open_type_skip(opt_codec_ctx, pd)) {\r
1690                                         FREEMEM(epres);\r
1691                                         ASN__DECODE_STARVED;\r
1692                                 }\r
1693                         }\r
1694                         break;\r
1695                 }\r
1696 \r
1697                 FREEMEM(epres);\r
1698         }\r
1699 \r
1700         /* Fill DEFAULT members in extensions */\r
1701         for(edx = specs->roms_count; edx < specs->roms_count\r
1702                 + specs->aoms_count; edx++) {\r
1703                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1704                 void **memb_ptr2;       /* Pointer to member pointer */\r
1705 \r
1706                 if(!elm->default_value_set) continue;\r
1707 \r
1708                 /* Fetch the pointer to this member */\r
1709                 if(elm->flags & ATF_POINTER) {\r
1710                         memb_ptr2 = (void **)((char *)st\r
1711                                               + elm->memb_offset);\r
1712                         if(*memb_ptr2) continue;\r
1713                 } else {\r
1714                         continue;       /* Extensions are all optionals */\r
1715                 }\r
1716 \r
1717                 /* Set default value */\r
1718                 if(elm->default_value_set(memb_ptr2)) {\r
1719                         ASN__DECODE_FAILED;\r
1720                 }\r
1721         }\r
1722 \r
1723         rv.consumed = 0;\r
1724         rv.code = RC_OK;\r
1725         return rv;\r
1726 }\r
1727 \r
1728 static int\r
1729 SEQUENCE_handle_extensions_aper(const asn_TYPE_descriptor_t *td,\r
1730                                 const void *sptr,\r
1731                                 asn_per_outp_t *po1, asn_per_outp_t *po2) {\r
1732         const asn_SEQUENCE_specifics_t *specs\r
1733             = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1734         int exts_present = 0;\r
1735         int exts_count = 0;\r
1736         size_t edx;\r
1737 \r
1738         if(specs->first_extension < 0) {\r
1739                 return 0;\r
1740         }\r
1741 \r
1742         /* Find out which extensions are present */\r
1743         for(edx = specs->first_extension; edx < td->elements_count; edx++) {\r
1744                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1745                 const void *memb_ptr;           /* Pointer to the member */\r
1746                 const void * const *memb_ptr2;  /* Pointer to that pointer */\r
1747                 int present;\r
1748 \r
1749                 if(!IN_EXTENSION_GROUP(specs, edx)) {\r
1750                         ASN_DEBUG("%s (@%ld) is not extension", elm->type->name, edx);\r
1751                         continue;\r
1752                 }\r
1753 \r
1754                 /* Fetch the pointer to this member */\r
1755                 if(elm->flags & ATF_POINTER) {\r
1756                         memb_ptr2 = (const void * const *)((const char *)sptr + elm->memb_offset);\r
1757                         present = (*memb_ptr2 != 0);\r
1758                 } else {\r
1759                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1760                         memb_ptr2 = &memb_ptr;\r
1761                         present = 1;\r
1762                 }\r
1763 \r
1764                 ASN_DEBUG("checking %s (@%ld) present => %d",\r
1765                           elm->type->name, edx, present);\r
1766                 exts_count++;\r
1767                 exts_present += present;\r
1768 \r
1769                 /* Encode as presence marker */\r
1770                 if(po1 && per_put_few_bits(po1, present, 1))\r
1771                         return -1;\r
1772                 /* Encode as open type field */\r
1773                 if(po2 && present && aper_open_type_put(elm->type,\r
1774                                                         elm->encoding_constraints.per_constraints, *memb_ptr2, po2))\r
1775                         return -1;\r
1776 \r
1777         }\r
1778 \r
1779         return exts_present ? exts_count : 0;\r
1780 }\r
1781 \r
1782 asn_enc_rval_t\r
1783 SEQUENCE_encode_aper(const asn_TYPE_descriptor_t *td,\r
1784                      const asn_per_constraints_t *constraints,\r
1785                      const void *sptr, asn_per_outp_t *po) {\r
1786         const asn_SEQUENCE_specifics_t *specs\r
1787             = (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1788         asn_enc_rval_t er = {0,0,0};\r
1789         int n_extensions;\r
1790         size_t edx;\r
1791         size_t i;\r
1792 \r
1793         (void)constraints;\r
1794 \r
1795         if(!sptr)\r
1796                 ASN__ENCODE_FAILED;\r
1797 \r
1798         er.encoded = 0;\r
1799 \r
1800         ASN_DEBUG("Encoding %s as SEQUENCE (APER)", td->name);\r
1801 \r
1802         /*\r
1803          * X.691#18.1 Whether structure is extensible\r
1804          * and whether to encode extensions\r
1805          */\r
1806         if(specs->first_extension < 0) {\r
1807                 n_extensions = 0; /* There are no extensions to encode */\r
1808         } else {\r
1809                 n_extensions = SEQUENCE_handle_extensions_aper(td, sptr, 0, 0);\r
1810                 if(n_extensions < 0) ASN__ENCODE_FAILED;\r
1811                 if(per_put_few_bits(po, n_extensions ? 1 : 0, 1)) {\r
1812                         ASN__ENCODE_FAILED;\r
1813                 }\r
1814         }\r
1815 \r
1816         /* Encode a presence bitmap */\r
1817         for(i = 0; i < specs->roms_count; i++) {\r
1818                 asn_TYPE_member_t *elm;\r
1819                 const void *memb_ptr;    /* Pointer to the member */\r
1820                 const void * const *memb_ptr2;       /* Pointer to that pointer */\r
1821                 int present;\r
1822 \r
1823                 edx = specs->oms[i];\r
1824                 elm = &td->elements[edx];\r
1825 \r
1826                 /* Fetch the pointer to this member */\r
1827                 if(elm->flags & ATF_POINTER) {\r
1828                         memb_ptr2 = (const void * const *)((const char *)sptr + elm->memb_offset);\r
1829                         present = (*memb_ptr2 != 0);\r
1830                 } else {\r
1831                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1832                         memb_ptr2 = &memb_ptr;\r
1833                         present = 1;\r
1834                 }\r
1835 \r
1836                 /* Eliminate default values */\r
1837                 if(present && elm->default_value_cmp\r
1838                         && elm->default_value_cmp(memb_ptr2) == 1)\r
1839                         present = 0;\r
1840 \r
1841                 ASN_DEBUG("Element %s %s %s->%s is %s",\r
1842                           elm->flags & ATF_POINTER ? "ptr" : "inline",\r
1843                           elm->default_value_cmp ? "def" : "wtv",\r
1844                           td->name, elm->name, present ? "present" : "absent");\r
1845                 if(per_put_few_bits(po, present, 1))\r
1846                         ASN__ENCODE_FAILED;\r
1847         }\r
1848 \r
1849         /*\r
1850          * Encode the sequence ROOT elements.\r
1851          */\r
1852         ASN_DEBUG("first_extension = %d, elements = %d", specs->first_extension,\r
1853               td->elements_count);\r
1854         for(edx = 0;\r
1855                 edx < ((specs->first_extension < 0) ? td->elements_count\r
1856                                             : (size_t)specs->first_extension);\r
1857                 edx++) {\r
1858                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1859                 const void *memb_ptr;          /* Pointer to the member */\r
1860                 const void * const *memb_ptr2; /* Pointer to that pointer */\r
1861 \r
1862                 if(IN_EXTENSION_GROUP(specs, edx))\r
1863                         continue;\r
1864 \r
1865                 ASN_DEBUG("About to encode %s", elm->type->name);\r
1866 \r
1867                 /* Fetch the pointer to this member */\r
1868                 if(elm->flags & ATF_POINTER) {\r
1869                         memb_ptr2 = (const void * const *)((const char *)sptr + elm->memb_offset);\r
1870                         if(!*memb_ptr2) {\r
1871                                 ASN_DEBUG("Element %s %ld not present",\r
1872                                           elm->name, edx);\r
1873                                 if(elm->optional)\r
1874                                         continue;\r
1875                                 /* Mandatory element is missing */\r
1876                                 ASN__ENCODE_FAILED;\r
1877                         }\r
1878                 } else {\r
1879                         memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);\r
1880                         memb_ptr2 = &memb_ptr;\r
1881                 }\r
1882 \r
1883                 /* Eliminate default values */\r
1884                 if(elm->default_value_cmp && elm->default_value_cmp(memb_ptr2) == 1)\r
1885                         continue;\r
1886 \r
1887                 ASN_DEBUG("Encoding %s->%s", td->name, elm->name);\r
1888                 er = elm->type->op->aper_encoder(elm->type, elm->encoding_constraints.per_constraints,\r
1889                                                  *memb_ptr2, po);\r
1890                 if(er.encoded == -1)\r
1891                         return er;\r
1892         }\r
1893 \r
1894         /* No extensions to encode */\r
1895         if(!n_extensions) ASN__ENCODED_OK(er);\r
1896 \r
1897         ASN_DEBUG("Length of %d bit-map", n_extensions);\r
1898         /* #18.8. Write down the presence bit-map length. */\r
1899         if(aper_put_nslength(po, n_extensions))\r
1900                 ASN__ENCODE_FAILED;\r
1901 \r
1902         ASN_DEBUG("Bit-map of %d elements", n_extensions);\r
1903         /* #18.7. Encoding the extensions presence bit-map. */\r
1904         /* TODO: act upon NOTE in #18.7 for canonical PER */\r
1905         if(SEQUENCE_handle_extensions_aper(td, sptr, po, 0) != n_extensions)\r
1906                 ASN__ENCODE_FAILED;\r
1907 \r
1908         ASN_DEBUG("Writing %d extensions", n_extensions);\r
1909         /* #18.9. Encode extensions as open type fields. */\r
1910         if(SEQUENCE_handle_extensions_aper(td, sptr, 0, po) != n_extensions)\r
1911                 ASN__ENCODE_FAILED;\r
1912 \r
1913         ASN__ENCODED_OK(er);\r
1914 }\r
1915 \r
1916 #endif  /* ASN_DISABLE_PER_SUPPORT */\r
1917 \r
1918 int\r
1919 SEQUENCE_compare(const asn_TYPE_descriptor_t *td, const void *aptr,\r
1920                  const void *bptr) {\r
1921     size_t edx;\r
1922 \r
1923         for(edx = 0; edx < td->elements_count; edx++) {\r
1924                 asn_TYPE_member_t *elm = &td->elements[edx];\r
1925                 const void *amemb;\r
1926                 const void *bmemb;\r
1927         int ret;\r
1928 \r
1929                 if(elm->flags & ATF_POINTER) {\r
1930             amemb =\r
1931                 *(const void *const *)((const char *)aptr + elm->memb_offset);\r
1932             bmemb =\r
1933                 *(const void *const *)((const char *)bptr + elm->memb_offset);\r
1934             if(!amemb) {\r
1935                 if(!bmemb) continue;\r
1936                 if(elm->default_value_cmp\r
1937                    && elm->default_value_cmp(bmemb) == 0) {\r
1938                     /* A is absent, but B is present and equal to DEFAULT */\r
1939                     continue;\r
1940                 }\r
1941                 return -1;\r
1942             } else if(!bmemb) {\r
1943                 if(elm->default_value_cmp\r
1944                    && elm->default_value_cmp(amemb) == 0) {\r
1945                     /* B is absent, but A is present and equal to DEFAULT */\r
1946                     continue;\r
1947                 }\r
1948                 return 1;\r
1949             }\r
1950                 } else {\r
1951             amemb = (const void *)((const char *)aptr + elm->memb_offset);\r
1952             bmemb = (const void *)((const char *)bptr + elm->memb_offset);\r
1953                 }\r
1954 \r
1955         ret = elm->type->op->compare_struct(elm->type, amemb, bmemb);\r
1956         if(ret != 0) return ret;\r
1957     }\r
1958 \r
1959     return 0;\r
1960 }\r
1961 \r
1962 asn_TYPE_operation_t asn_OP_SEQUENCE = {\r
1963         SEQUENCE_free,\r
1964         SEQUENCE_print,\r
1965         SEQUENCE_compare,\r
1966         SEQUENCE_decode_ber,\r
1967         SEQUENCE_encode_der,\r
1968         SEQUENCE_decode_xer,\r
1969         SEQUENCE_encode_xer,\r
1970 #ifdef  ASN_DISABLE_OER_SUPPORT\r
1971         0,\r
1972         0,\r
1973 #else\r
1974         SEQUENCE_decode_oer,\r
1975         SEQUENCE_encode_oer,\r
1976 #endif  /* ASN_DISABLE_OER_SUPPORT */\r
1977 #ifdef ASN_DISABLE_PER_SUPPORT\r
1978         0,\r
1979         0,\r
1980         0,\r
1981         0,\r
1982 #else\r
1983         SEQUENCE_decode_uper,\r
1984         SEQUENCE_encode_uper,\r
1985         SEQUENCE_decode_aper,\r
1986         SEQUENCE_encode_aper,\r
1987 #endif /* ASN_DISABLE_PER_SUPPORT */\r
1988         SEQUENCE_random_fill,\r
1989         0       /* Use generic outmost tag fetcher */\r
1990 };\r
1991 \r
1992 \r
1993 asn_random_fill_result_t\r
1994 SEQUENCE_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,\r
1995                    const asn_encoding_constraints_t *constr,\r
1996                    size_t max_length) {\r
1997     const asn_SEQUENCE_specifics_t *specs =\r
1998         (const asn_SEQUENCE_specifics_t *)td->specifics;\r
1999     asn_random_fill_result_t result_ok = {ARFILL_OK, 0};\r
2000     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};\r
2001     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};\r
2002     void *st = *sptr;\r
2003     size_t edx;\r
2004 \r
2005     if(max_length == 0) return result_skipped;\r
2006 \r
2007     (void)constr;\r
2008 \r
2009     if(st == NULL) {\r
2010         st = CALLOC(1, specs->struct_size);\r
2011         if(st == NULL) {\r
2012             return result_failed;\r
2013         }\r
2014     }\r
2015 \r
2016     for(edx = 0; edx < td->elements_count; edx++) {\r
2017         const asn_TYPE_member_t *elm = &td->elements[edx];\r
2018         void *memb_ptr;   /* Pointer to the member */\r
2019         void **memb_ptr2; /* Pointer to that pointer */\r
2020         asn_random_fill_result_t tmpres;\r
2021 \r
2022         if(elm->optional && asn_random_between(0, 4) == 2) {\r
2023             /* Sometimes decide not to fill the optional value */\r
2024             continue;\r
2025         }\r
2026 \r
2027         if(elm->flags & ATF_POINTER) {\r
2028             /* Member is a pointer to another structure */\r
2029             memb_ptr2 = (void **)((char *)st + elm->memb_offset);\r
2030         } else {\r
2031             memb_ptr = (char *)st + elm->memb_offset;\r
2032             memb_ptr2 = &memb_ptr;\r
2033         }\r
2034 \r
2035         tmpres = elm->type->op->random_fill(\r
2036             elm->type, memb_ptr2, &elm->encoding_constraints,\r
2037             max_length > result_ok.length ? max_length - result_ok.length : 0);\r
2038         switch(tmpres.code) {\r
2039         case ARFILL_OK:\r
2040             result_ok.length += tmpres.length;\r
2041             continue;\r
2042         case ARFILL_SKIPPED:\r
2043             assert(!(elm->flags & ATF_POINTER) || *memb_ptr2 == NULL);\r
2044             continue;\r
2045         case ARFILL_FAILED:\r
2046             if(st == *sptr) {\r
2047                 ASN_STRUCT_RESET(*td, st);\r
2048             } else {\r
2049                 ASN_STRUCT_FREE(*td, st);\r
2050             }\r
2051             return tmpres;\r
2052         }\r
2053     }\r
2054 \r
2055     *sptr = st;\r
2056 \r
2057     return result_ok;\r
2058 }\r
2059 \r