~ubuntu-branches/ubuntu/raring/freerdp/raring

« back to all changes in this revision

Viewing changes to asn1/constr_SEQUENCE.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2010-06-23 21:39:09 UTC
  • Revision ID: james.westby@ubuntu.com-20100623213909-bb9pvvv03913tdv6
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
 
3
 * All rights reserved.
 
4
 * Redistribution and modifications are permitted subject to BSD license.
 
5
 */
 
6
#include <asn_internal.h>
 
7
#include <constr_SEQUENCE.h>
 
8
#include <per_opentype.h>
 
9
 
 
10
/*
 
11
 * Number of bytes left for this structure.
 
12
 * (ctx->left) indicates the number of bytes _transferred_ for the structure.
 
13
 * (size) contains the number of bytes in the buffer passed.
 
14
 */
 
15
#define LEFT    ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
 
16
 
 
17
/*
 
18
 * If the subprocessor function returns with an indication that it wants
 
19
 * more data, it may well be a fatal decoding problem, because the
 
20
 * size is constrained by the <TLV>'s L, even if the buffer size allows
 
21
 * reading more data.
 
22
 * For example, consider the buffer containing the following TLVs:
 
23
 * <T:5><L:1><V> <T:6>...
 
24
 * The TLV length clearly indicates that one byte is expected in V, but
 
25
 * if the V processor returns with "want more data" even if the buffer
 
26
 * contains way more data than the V processor have seen.
 
27
 */
 
28
#define SIZE_VIOLATION  (ctx->left >= 0 && (size_t)ctx->left <= size)
 
29
 
 
30
/*
 
31
 * This macro "eats" the part of the buffer which is definitely "consumed",
 
32
 * i.e. was correctly converted into local representation or rightfully skipped.
 
33
 */
 
34
#undef  ADVANCE
 
35
#define ADVANCE(num_bytes)      do {            \
 
36
                size_t num = num_bytes;         \
 
37
                ptr = ((const char *)ptr) + num;\
 
38
                size -= num;                    \
 
39
                if(ctx->left >= 0)              \
 
40
                        ctx->left -= num;       \
 
41
                consumed_myself += num;         \
 
42
        } while(0)
 
43
 
 
44
/*
 
45
 * Switch to the next phase of parsing.
 
46
 */
 
47
#undef  NEXT_PHASE
 
48
#undef  PHASE_OUT
 
49
#define NEXT_PHASE(ctx) do {                    \
 
50
                ctx->phase++;                   \
 
51
                ctx->step = 0;                  \
 
52
        } while(0)
 
53
#define PHASE_OUT(ctx)  do { ctx->phase = 10; } while(0)
 
54
 
 
55
/*
 
56
 * Return a standardized complex structure.
 
57
 */
 
58
#undef  RETURN
 
59
#define RETURN(_code)   do {                    \
 
60
                rval.code = _code;              \
 
61
                rval.consumed = consumed_myself;\
 
62
                return rval;                    \
 
63
        } while(0)
 
64
 
 
65
/*
 
66
 * Check whether we are inside the extensions group.
 
67
 */
 
68
#define IN_EXTENSION_GROUP(specs, memb_idx)     \
 
69
        ( ((memb_idx) > (specs)->ext_after)     \
 
70
        &&((memb_idx) < (specs)->ext_before))
 
71
 
 
72
 
 
73
/*
 
74
 * Tags are canonically sorted in the tag2element map.
 
75
 */
 
76
static int
 
77
_t2e_cmp(const void *ap, const void *bp) {
 
78
        const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
 
79
        const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
 
80
 
 
81
        int a_class = BER_TAG_CLASS(a->el_tag);
 
82
        int b_class = BER_TAG_CLASS(b->el_tag);
 
83
 
 
84
        if(a_class == b_class) {
 
85
                ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
 
86
                ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
 
87
 
 
88
                if(a_value == b_value) {
 
89
                        if(a->el_no > b->el_no)
 
90
                                return 1;
 
91
                        /*
 
92
                         * Important: we do not check
 
93
                         * for a->el_no <= b->el_no!
 
94
                         */
 
95
                        return 0;
 
96
                } else if(a_value < b_value)
 
97
                        return -1;
 
98
                else
 
99
                        return 1;
 
100
        } else if(a_class < b_class) {
 
101
                return -1;
 
102
        } else {
 
103
                return 1;
 
104
        }
 
105
}
 
106
 
 
107
 
 
108
/*
 
109
 * The decoder of the SEQUENCE type.
 
110
 */
 
111
asn_dec_rval_t
 
112
SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 
113
        void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
 
114
        /*
 
115
         * Bring closer parts of structure description.
 
116
         */
 
117
        asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
 
118
        asn_TYPE_member_t *elements = td->elements;
 
119
 
 
120
        /*
 
121
         * Parts of the structure being constructed.
 
122
         */
 
123
        void *st = *struct_ptr; /* Target structure. */
 
124
        asn_struct_ctx_t *ctx;  /* Decoder context */
 
125
 
 
126
        ber_tlv_tag_t tlv_tag;  /* T from TLV */
 
127
        asn_dec_rval_t rval;    /* Return code from subparsers */
 
128
 
 
129
        ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
 
130
        int edx;                        /* SEQUENCE element's index */
 
131
 
 
132
        ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
 
133
        
 
134
        /*
 
135
         * Create the target structure if it is not present already.
 
136
         */
 
137
        if(st == 0) {
 
138
                st = *struct_ptr = CALLOC(1, specs->struct_size);
 
139
                if(st == 0) {
 
140
                        RETURN(RC_FAIL);
 
141
                }
 
142
        }
 
143
 
 
144
        /*
 
145
         * Restore parsing context.
 
146
         */
 
147
        ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
 
148
        
 
149
        /*
 
150
         * Start to parse where left previously
 
151
         */
 
152
        switch(ctx->phase) {
 
153
        case 0:
 
154
                /*
 
155
                 * PHASE 0.
 
156
                 * Check that the set of tags associated with given structure
 
157
                 * perfectly fits our expectations.
 
158
                 */
 
159
 
 
160
                rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
 
161
                        tag_mode, 1, &ctx->left, 0);
 
162
                if(rval.code != RC_OK) {
 
163
                        ASN_DEBUG("%s tagging check failed: %d",
 
164
                                td->name, rval.code);
 
165
                        return rval;
 
166
                }
 
167
 
 
168
                if(ctx->left >= 0)
 
169
                        ctx->left += rval.consumed; /* ?Substracted below! */
 
170
                ADVANCE(rval.consumed);
 
171
 
 
172
                NEXT_PHASE(ctx);
 
173
 
 
174
                ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
 
175
                        (long)ctx->left, (long)size);
 
176
 
 
177
                /* Fall through */
 
178
        case 1:
 
179
                /*
 
180
                 * PHASE 1.
 
181
                 * From the place where we've left it previously,
 
182
                 * try to decode the next member from the list of
 
183
                 * this structure's elements.
 
184
                 * (ctx->step) stores the member being processed
 
185
                 * between invocations and the microphase {0,1} of parsing
 
186
                 * that member:
 
187
                 *      step = (<member_number> * 2 + <microphase>).
 
188
                 */
 
189
          for(edx = (ctx->step >> 1); edx < td->elements_count;
 
190
                        edx++, ctx->step = (ctx->step & ~1) + 2) {
 
191
                void *memb_ptr;         /* Pointer to the member */
 
192
                void **memb_ptr2;       /* Pointer to that pointer */
 
193
                ssize_t tag_len;        /* Length of TLV's T */
 
194
                int opt_edx_end;        /* Next non-optional element */
 
195
                int use_bsearch;
 
196
                int n;
 
197
 
 
198
                if(ctx->step & 1)
 
199
                        goto microphase2;
 
200
 
 
201
                /*
 
202
                 * MICROPHASE 1: Synchronize decoding.
 
203
                 */
 
204
                ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
 
205
                                " opt=%d ec=%d",
 
206
                        td->name, (int)ctx->left, edx,
 
207
                        elements[edx].flags, elements[edx].optional,
 
208
                        td->elements_count);
 
209
 
 
210
                if(ctx->left == 0       /* No more stuff is expected */
 
211
                && (
 
212
                        /* Explicit OPTIONAL specification reaches the end */
 
213
                        (edx + elements[edx].optional
 
214
                                        == td->elements_count)
 
215
                        ||
 
216
                        /* All extensions are optional */
 
217
                        (IN_EXTENSION_GROUP(specs, edx)
 
218
                                && specs->ext_before > td->elements_count)
 
219
                   )
 
220
                ) {
 
221
                        ASN_DEBUG("End of SEQUENCE %s", td->name);
 
222
                        /*
 
223
                         * Found the legitimate end of the structure.
 
224
                         */
 
225
                        PHASE_OUT(ctx);
 
226
                        RETURN(RC_OK);
 
227
                }
 
228
 
 
229
                /*
 
230
                 * Fetch the T from TLV.
 
231
                 */
 
232
                tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
 
233
                ASN_DEBUG("Current tag in %s SEQUENCE for element %d "
 
234
                        "(%s) is %s encoded in %d bytes, of frame %ld",
 
235
                        td->name, edx, elements[edx].name,
 
236
                        ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
 
237
                switch(tag_len) {
 
238
                case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
239
                        /* Fall through */
 
240
                case -1: RETURN(RC_FAIL);
 
241
                }
 
242
 
 
243
                if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
 
244
                        if(LEFT < 2) {
 
245
                                if(SIZE_VIOLATION)
 
246
                                        RETURN(RC_FAIL);
 
247
                                else
 
248
                                        RETURN(RC_WMORE);
 
249
                        } else if(((const uint8_t *)ptr)[1] == 0) {
 
250
                        ASN_DEBUG("edx = %d, opt = %d, ec=%d",
 
251
                                edx, elements[edx].optional,
 
252
                                td->elements_count);
 
253
                                if((edx + elements[edx].optional
 
254
                                        == td->elements_count)
 
255
                                || (IN_EXTENSION_GROUP(specs, edx)
 
256
                                        && specs->ext_before
 
257
                                                > td->elements_count)) {
 
258
                                        /*
 
259
                                         * Yeah, baby! Found the terminator
 
260
                                         * of the indefinite length structure.
 
261
                                         */
 
262
                                        /*
 
263
                                         * Proceed to the canonical
 
264
                                         * finalization function.
 
265
                                         * No advancing is necessary.
 
266
                                         */
 
267
                                        goto phase3;
 
268
                                }
 
269
                        }
 
270
                }
 
271
 
 
272
                /*
 
273
                 * Find the next available type with this tag.
 
274
                 */
 
275
                use_bsearch = 0;
 
276
                opt_edx_end = edx + elements[edx].optional + 1;
 
277
                if(opt_edx_end > td->elements_count)
 
278
                        opt_edx_end = td->elements_count;       /* Cap */
 
279
                else if(opt_edx_end - edx > 8) {
 
280
                        /* Limit the scope of linear search... */
 
281
                        opt_edx_end = edx + 8;
 
282
                        use_bsearch = 1;
 
283
                        /* ... and resort to bsearch() */
 
284
                }
 
285
                for(n = edx; n < opt_edx_end; n++) {
 
286
                        if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
 
287
                                /*
 
288
                                 * Found element corresponding to the tag
 
289
                                 * being looked at.
 
290
                                 * Reposition over the right element.
 
291
                                 */
 
292
                                edx = n;
 
293
                                ctx->step = 1 + 2 * edx;        /* Remember! */
 
294
                                goto microphase2;
 
295
                        } else if(elements[n].flags & ATF_OPEN_TYPE) {
 
296
                                /*
 
297
                                 * This is the ANY type, which may bear
 
298
                                 * any flag whatsoever.
 
299
                                 */
 
300
                                edx = n;
 
301
                                ctx->step = 1 + 2 * edx;        /* Remember! */
 
302
                                goto microphase2;
 
303
                        } else if(elements[n].tag == (ber_tlv_tag_t)-1) {
 
304
                                use_bsearch = 1;
 
305
                                break;
 
306
                        }
 
307
                }
 
308
                if(use_bsearch) {
 
309
                        /*
 
310
                         * Resort to a binary search over
 
311
                         * sorted array of tags.
 
312
                         */
 
313
                        asn_TYPE_tag2member_t *t2m;
 
314
                        asn_TYPE_tag2member_t key;
 
315
                        key.el_tag = tlv_tag;
 
316
                        key.el_no = edx;
 
317
                        t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
 
318
                                specs->tag2el, specs->tag2el_count,
 
319
                                sizeof(specs->tag2el[0]), _t2e_cmp);
 
320
                        if(t2m) {
 
321
                                asn_TYPE_tag2member_t *best = 0;
 
322
                                asn_TYPE_tag2member_t *t2m_f, *t2m_l;
 
323
                                int edx_max = edx + elements[edx].optional;
 
324
                                /*
 
325
                                 * Rewind to the first element with that tag,
 
326
                                 * `cause bsearch() does not guarantee order.
 
327
                                 */
 
328
                                t2m_f = t2m + t2m->toff_first;
 
329
                                t2m_l = t2m + t2m->toff_last;
 
330
                                for(t2m = t2m_f; t2m <= t2m_l; t2m++) {
 
331
                                        if(t2m->el_no > edx_max) break;
 
332
                                        if(t2m->el_no < edx) continue;
 
333
                                        best = t2m;
 
334
                                }
 
335
                                if(best) {
 
336
                                        edx = best->el_no;
 
337
                                        ctx->step = 1 + 2 * edx;
 
338
                                        goto microphase2;
 
339
                                }
 
340
                        }
 
341
                        n = opt_edx_end;
 
342
                }
 
343
                if(n == opt_edx_end) {
 
344
                        /*
 
345
                         * If tag is unknown, it may be either
 
346
                         * an unknown (thus, incorrect) tag,
 
347
                         * or an extension (...),
 
348
                         * or an end of the indefinite-length structure.
 
349
                         */
 
350
                        if(!IN_EXTENSION_GROUP(specs,
 
351
                                edx + elements[edx].optional)) {
 
352
                                ASN_DEBUG("Unexpected tag %s (at %d)",
 
353
                                        ber_tlv_tag_string(tlv_tag), edx);
 
354
                                ASN_DEBUG("Expected tag %s (%s)%s",
 
355
                                        ber_tlv_tag_string(elements[edx].tag),
 
356
                                        elements[edx].name,
 
357
                                        elements[edx].optional
 
358
                                                ?" or alternatives":"");
 
359
                                RETURN(RC_FAIL);
 
360
                        } else {
 
361
                                /* Skip this tag */
 
362
                                ssize_t skip;
 
363
                                edx += elements[edx].optional;
 
364
 
 
365
                                ASN_DEBUG("Skipping unexpected %s (at %d)",
 
366
                                        ber_tlv_tag_string(tlv_tag), edx);
 
367
                                skip = ber_skip_length(opt_codec_ctx,
 
368
                                        BER_TLV_CONSTRUCTED(ptr),
 
369
                                        (const char *)ptr + tag_len,
 
370
                                        LEFT - tag_len);
 
371
                                ASN_DEBUG("Skip length %d in %s",
 
372
                                        (int)skip, td->name);
 
373
                                switch(skip) {
 
374
                                case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
375
                                        /* Fall through */
 
376
                                case -1: RETURN(RC_FAIL);
 
377
                                }
 
378
 
 
379
                                ADVANCE(skip + tag_len);
 
380
                                ctx->step -= 2;
 
381
                                edx--;
 
382
                                continue;  /* Try again with the next tag */
 
383
                        }
 
384
                }
 
385
 
 
386
                /*
 
387
                 * MICROPHASE 2: Invoke the member-specific decoder.
 
388
                 */
 
389
                ctx->step |= 1;         /* Confirm entering next microphase */
 
390
        microphase2:
 
391
                ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
 
392
                
 
393
                /*
 
394
                 * Compute the position of the member inside a structure,
 
395
                 * and also a type of containment (it may be contained
 
396
                 * as pointer or using inline inclusion).
 
397
                 */
 
398
                if(elements[edx].flags & ATF_POINTER) {
 
399
                        /* Member is a pointer to another structure */
 
400
                        memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
 
401
                } else {
 
402
                        /*
 
403
                         * A pointer to a pointer
 
404
                         * holding the start of the structure
 
405
                         */
 
406
                        memb_ptr = (char *)st + elements[edx].memb_offset;
 
407
                        memb_ptr2 = &memb_ptr;
 
408
                }
 
409
                /*
 
410
                 * Invoke the member fetch routine according to member's type
 
411
                 */
 
412
                rval = elements[edx].type->ber_decoder(opt_codec_ctx,
 
413
                                elements[edx].type,
 
414
                                memb_ptr2, ptr, LEFT,
 
415
                                elements[edx].tag_mode);
 
416
                ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d "
 
417
                        "in %d bytes rval.code %d, size=%d",
 
418
                        td->name, edx, elements[edx].type->name,
 
419
                        (int)LEFT, (int)rval.consumed, rval.code, (int)size);
 
420
                switch(rval.code) {
 
421
                case RC_OK:
 
422
                        break;
 
423
                case RC_WMORE: /* More data expected */
 
424
                        if(!SIZE_VIOLATION) {
 
425
                                ADVANCE(rval.consumed);
 
426
                                RETURN(RC_WMORE);
 
427
                        }
 
428
                        ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
 
429
                                (long)ctx->left, (long)size);
 
430
                        /* Fall through */
 
431
                case RC_FAIL: /* Fatal error */
 
432
                        RETURN(RC_FAIL);
 
433
                } /* switch(rval) */
 
434
                
 
435
                ADVANCE(rval.consumed);
 
436
          }     /* for(all structure members) */
 
437
 
 
438
        phase3:
 
439
                ctx->phase = 3;
 
440
        case 3: /* 00 and other tags expected */
 
441
        case 4: /* only 00's expected */
 
442
 
 
443
                ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
 
444
                        td->name, (long)ctx->left, (long)size);
 
445
 
 
446
                /*
 
447
                 * Skip everything until the end of the SEQUENCE.
 
448
                 */
 
449
                while(ctx->left) {
 
450
                        ssize_t tl, ll;
 
451
 
 
452
                        tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
 
453
                        switch(tl) {
 
454
                        case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
455
                                /* Fall through */
 
456
                        case -1: RETURN(RC_FAIL);
 
457
                        }
 
458
 
 
459
                        /*
 
460
                         * If expected <0><0>...
 
461
                         */
 
462
                        if(ctx->left < 0
 
463
                                && ((const uint8_t *)ptr)[0] == 0) {
 
464
                                if(LEFT < 2) {
 
465
                                        if(SIZE_VIOLATION)
 
466
                                                RETURN(RC_FAIL);
 
467
                                        else
 
468
                                                RETURN(RC_WMORE);
 
469
                                } else if(((const uint8_t *)ptr)[1] == 0) {
 
470
                                        /*
 
471
                                         * Correctly finished with <0><0>.
 
472
                                         */
 
473
                                        ADVANCE(2);
 
474
                                        ctx->left++;
 
475
                                        ctx->phase = 4;
 
476
                                        continue;
 
477
                                }
 
478
                        }
 
479
 
 
480
                        if(!IN_EXTENSION_GROUP(specs, td->elements_count)
 
481
                        || ctx->phase == 4) {
 
482
                                ASN_DEBUG("Unexpected continuation "
 
483
                                        "of a non-extensible type "
 
484
                                        "%s (SEQUENCE): %s",
 
485
                                        td->name,
 
486
                                        ber_tlv_tag_string(tlv_tag));
 
487
                                RETURN(RC_FAIL);
 
488
                        }
 
489
 
 
490
                        ll = ber_skip_length(opt_codec_ctx,
 
491
                                BER_TLV_CONSTRUCTED(ptr),
 
492
                                (const char *)ptr + tl, LEFT - tl);
 
493
                        switch(ll) {
 
494
                        case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 
495
                                /* Fall through */
 
496
                        case -1: RETURN(RC_FAIL);
 
497
                        }
 
498
 
 
499
                        ADVANCE(tl + ll);
 
500
                }
 
501
 
 
502
                PHASE_OUT(ctx);
 
503
        }
 
504
        
 
505
        RETURN(RC_OK);
 
506
}
 
507
 
 
508
 
 
509
/*
 
510
 * The DER encoder of the SEQUENCE type.
 
511
 */
 
512
asn_enc_rval_t
 
513
SEQUENCE_encode_der(asn_TYPE_descriptor_t *td,
 
514
        void *sptr, int tag_mode, ber_tlv_tag_t tag,
 
515
        asn_app_consume_bytes_f *cb, void *app_key) {
 
516
        size_t computed_size = 0;
 
517
        asn_enc_rval_t erval;
 
518
        ssize_t ret;
 
519
        int edx;
 
520
 
 
521
        ASN_DEBUG("%s %s as SEQUENCE",
 
522
                cb?"Encoding":"Estimating", td->name);
 
523
 
 
524
        /*
 
525
         * Gather the length of the underlying members sequence.
 
526
         */
 
527
        for(edx = 0; edx < td->elements_count; edx++) {
 
528
                asn_TYPE_member_t *elm = &td->elements[edx];
 
529
                void *memb_ptr;
 
530
                if(elm->flags & ATF_POINTER) {
 
531
                        memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
532
                        if(!memb_ptr) {
 
533
                                if(elm->optional) continue;
 
534
                                /* Mandatory element is missing */
 
535
                                _ASN_ENCODE_FAILED;
 
536
                        }
 
537
                } else {
 
538
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
539
                }
 
540
                erval = elm->type->der_encoder(elm->type, memb_ptr,
 
541
                        elm->tag_mode, elm->tag,
 
542
                        0, 0);
 
543
                if(erval.encoded == -1)
 
544
                        return erval;
 
545
                computed_size += erval.encoded;
 
546
                ASN_DEBUG("Member %d %s estimated %ld bytes",
 
547
                        edx, elm->name, (long)erval.encoded);
 
548
        }
 
549
 
 
550
        /*
 
551
         * Encode the TLV for the sequence itself.
 
552
         */
 
553
        ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
 
554
        ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
 
555
        if(ret == -1)
 
556
                _ASN_ENCODE_FAILED;
 
557
        erval.encoded = computed_size + ret;
 
558
 
 
559
        if(!cb) _ASN_ENCODED_OK(erval);
 
560
 
 
561
        /*
 
562
         * Encode all members.
 
563
         */
 
564
        for(edx = 0; edx < td->elements_count; edx++) {
 
565
                asn_TYPE_member_t *elm = &td->elements[edx];
 
566
                asn_enc_rval_t tmperval;
 
567
                void *memb_ptr;
 
568
 
 
569
                if(elm->flags & ATF_POINTER) {
 
570
                        memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
571
                        if(!memb_ptr) continue;
 
572
                } else {
 
573
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
574
                }
 
575
                tmperval = elm->type->der_encoder(elm->type, memb_ptr,
 
576
                        elm->tag_mode, elm->tag,
 
577
                        cb, app_key);
 
578
                if(tmperval.encoded == -1)
 
579
                        return tmperval;
 
580
                computed_size -= tmperval.encoded;
 
581
                ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes",
 
582
                        edx, elm->name, td->name, (long)tmperval.encoded);
 
583
        }
 
584
 
 
585
        if(computed_size != 0)
 
586
                /*
 
587
                 * Encoded size is not equal to the computed size.
 
588
                 */
 
589
                _ASN_ENCODE_FAILED;
 
590
 
 
591
        _ASN_ENCODED_OK(erval);
 
592
}
 
593
 
 
594
 
 
595
#undef  XER_ADVANCE
 
596
#define XER_ADVANCE(num_bytes)  do {                    \
 
597
                size_t num = num_bytes;                 \
 
598
                buf_ptr = ((const char *)buf_ptr) + num;\
 
599
                size -= num;                            \
 
600
                consumed_myself += num;                 \
 
601
        } while(0)
 
602
 
 
603
/*
 
604
 * Decode the XER (XML) data.
 
605
 */
 
606
asn_dec_rval_t
 
607
SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 
608
        void **struct_ptr, const char *opt_mname,
 
609
                const void *buf_ptr, size_t size) {
 
610
        /*
 
611
         * Bring closer parts of structure description.
 
612
         */
 
613
        asn_SEQUENCE_specifics_t *specs
 
614
                = (asn_SEQUENCE_specifics_t *)td->specifics;
 
615
        asn_TYPE_member_t *elements = td->elements;
 
616
        const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 
617
 
 
618
        /*
 
619
         * ... and parts of the structure being constructed.
 
620
         */
 
621
        void *st = *struct_ptr; /* Target structure. */
 
622
        asn_struct_ctx_t *ctx;  /* Decoder context */
 
623
 
 
624
        asn_dec_rval_t rval;            /* Return value from a decoder */
 
625
        ssize_t consumed_myself = 0;    /* Consumed bytes from ptr */
 
626
        int edx;                        /* Element index */
 
627
        int edx_end;
 
628
 
 
629
        /*
 
630
         * Create the target structure if it is not present already.
 
631
         */
 
632
        if(st == 0) {
 
633
                st = *struct_ptr = CALLOC(1, specs->struct_size);
 
634
                if(st == 0) RETURN(RC_FAIL);
 
635
        }
 
636
 
 
637
        /*
 
638
         * Restore parsing context.
 
639
         */
 
640
        ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
 
641
 
 
642
 
 
643
        /*
 
644
         * Phases of XER/XML processing:
 
645
         * Phase 0: Check that the opening tag matches our expectations.
 
646
         * Phase 1: Processing body and reacting on closing tag.
 
647
         * Phase 2: Processing inner type.
 
648
         * Phase 3: Skipping unknown extensions.
 
649
         * Phase 4: PHASED OUT
 
650
         */
 
651
        for(edx = ctx->step; ctx->phase <= 3;) {
 
652
                pxer_chunk_type_e ch_type;      /* XER chunk type */
 
653
                ssize_t ch_size;                /* Chunk size */
 
654
                xer_check_tag_e tcv;            /* Tag check value */
 
655
                asn_TYPE_member_t *elm;
 
656
                int n;
 
657
 
 
658
                /*
 
659
                 * Go inside the inner member of a sequence.
 
660
                 */
 
661
                if(ctx->phase == 2) {
 
662
                        asn_dec_rval_t tmprval;
 
663
                        void *memb_ptr;         /* Pointer to the member */
 
664
                        void **memb_ptr2;       /* Pointer to that pointer */
 
665
 
 
666
                        elm = &td->elements[edx];
 
667
 
 
668
                        if(elm->flags & ATF_POINTER) {
 
669
                                /* Member is a pointer to another structure */
 
670
                                memb_ptr2 = (void **)((char *)st
 
671
                                        + elm->memb_offset);
 
672
                        } else {
 
673
                                memb_ptr = (char *)st + elm->memb_offset;
 
674
                                memb_ptr2 = &memb_ptr;
 
675
                        }
 
676
 
 
677
                        /* Invoke the inner type decoder, m.b. multiple times */
 
678
                        tmprval = elm->type->xer_decoder(opt_codec_ctx,
 
679
                                        elm->type, memb_ptr2, elm->name,
 
680
                                        buf_ptr, size);
 
681
                        XER_ADVANCE(tmprval.consumed);
 
682
                        if(tmprval.code != RC_OK)
 
683
                                RETURN(tmprval.code);
 
684
                        ctx->phase = 1; /* Back to body processing */
 
685
                        ctx->step = ++edx;
 
686
                        ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
 
687
                                ctx->phase, ctx->step);
 
688
                        /* Fall through */
 
689
                }
 
690
 
 
691
                /*
 
692
                 * Get the next part of the XML stream.
 
693
                 */
 
694
                ch_size = xer_next_token(&ctx->context, buf_ptr, size,
 
695
                        &ch_type);
 
696
                switch(ch_size) {
 
697
                case -1: RETURN(RC_FAIL);
 
698
                case 0:  RETURN(RC_WMORE);
 
699
                default:
 
700
                        switch(ch_type) {
 
701
                        case PXER_COMMENT:      /* Got XML comment */
 
702
                        case PXER_TEXT:         /* Ignore free-standing text */
 
703
                                XER_ADVANCE(ch_size);   /* Skip silently */
 
704
                                continue;
 
705
                        case PXER_TAG:
 
706
                                break;  /* Check the rest down there */
 
707
                        }
 
708
                }
 
709
 
 
710
                tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
 
711
                ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
 
712
                        tcv, ctx->phase, xml_tag);
 
713
 
 
714
                /* Skip the extensions section */
 
715
                if(ctx->phase == 3) {
 
716
                        switch(xer_skip_unknown(tcv, &ctx->left)) {
 
717
                        case -1:
 
718
                                ctx->phase = 4;
 
719
                                RETURN(RC_FAIL);
 
720
                        case 0:
 
721
                                XER_ADVANCE(ch_size);
 
722
                                continue;
 
723
                        case 1:
 
724
                                XER_ADVANCE(ch_size);
 
725
                                ctx->phase = 1;
 
726
                                continue;
 
727
                        case 2:
 
728
                                ctx->phase = 1;
 
729
                                break;
 
730
                        }
 
731
                }
 
732
 
 
733
                switch(tcv) {
 
734
                case XCT_CLOSING:
 
735
                        if(ctx->phase == 0) break;
 
736
                        ctx->phase = 0;
 
737
                        /* Fall through */
 
738
                case XCT_BOTH:
 
739
                        if(ctx->phase == 0) {
 
740
                                if(edx >= td->elements_count
 
741
                                   ||
 
742
                                   /* Explicit OPTIONAL specs reaches the end */
 
743
                                    (edx + elements[edx].optional
 
744
                                        == td->elements_count)
 
745
                                   ||
 
746
                                   /* All extensions are optional */
 
747
                                   (IN_EXTENSION_GROUP(specs, edx)
 
748
                                        && specs->ext_before
 
749
                                                > td->elements_count)
 
750
                                ) {
 
751
                                        XER_ADVANCE(ch_size);
 
752
                                        ctx->phase = 4; /* Phase out */
 
753
                                        RETURN(RC_OK);
 
754
                                } else {
 
755
                                        ASN_DEBUG("Premature end of XER SEQUENCE");
 
756
                                        RETURN(RC_FAIL);
 
757
                                }
 
758
                        }
 
759
                        /* Fall through */
 
760
                case XCT_OPENING:
 
761
                        if(ctx->phase == 0) {
 
762
                                XER_ADVANCE(ch_size);
 
763
                                ctx->phase = 1; /* Processing body phase */
 
764
                                continue;
 
765
                        }
 
766
                        /* Fall through */
 
767
                case XCT_UNKNOWN_OP:
 
768
                case XCT_UNKNOWN_BO:
 
769
 
 
770
                        ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d",
 
771
                                tcv, ctx->phase, edx);
 
772
                        if(ctx->phase != 1) {
 
773
                                break;  /* Really unexpected */
 
774
                        }
 
775
 
 
776
                        if(edx < td->elements_count) {
 
777
                                /*
 
778
                                 * Search which member corresponds to this tag.
 
779
                                 */
 
780
                                edx_end = edx + elements[edx].optional + 1;
 
781
                                if(edx_end > td->elements_count)
 
782
                                        edx_end = td->elements_count;
 
783
                                for(n = edx; n < edx_end; n++) {
 
784
                                        elm = &td->elements[n];
 
785
                                        tcv = xer_check_tag(buf_ptr,
 
786
                                                ch_size, elm->name);
 
787
                                        switch(tcv) {
 
788
                                        case XCT_BOTH:
 
789
                                        case XCT_OPENING:
 
790
                                                /*
 
791
                                                 * Process this member.
 
792
                                                 */
 
793
                                                ctx->step = edx = n;
 
794
                                                ctx->phase = 2;
 
795
                                                break;
 
796
                                        case XCT_UNKNOWN_OP:
 
797
                                        case XCT_UNKNOWN_BO:
 
798
                                                continue;
 
799
                                        default:
 
800
                                                n = edx_end;
 
801
                                                break;  /* Phase out */
 
802
                                        }
 
803
                                        break;
 
804
                                }
 
805
                                if(n != edx_end)
 
806
                                        continue;
 
807
                        } else {
 
808
                                ASN_DEBUG("Out of defined members: %d/%d",
 
809
                                        edx, td->elements_count);
 
810
                        }
 
811
 
 
812
                        /* It is expected extension */
 
813
                        if(IN_EXTENSION_GROUP(specs,
 
814
                                edx + (edx < td->elements_count
 
815
                                        ? elements[edx].optional : 0))) {
 
816
                                ASN_DEBUG("Got anticipated extension at %d",
 
817
                                        edx);
 
818
                                /*
 
819
                                 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
 
820
                                 * By using a mask. Only record a pure
 
821
                                 * <opening> tags.
 
822
                                 */
 
823
                                if(tcv & XCT_CLOSING) {
 
824
                                        /* Found </extension> without body */
 
825
                                } else {
 
826
                                        ctx->left = 1;
 
827
                                        ctx->phase = 3; /* Skip ...'s */
 
828
                                }
 
829
                                XER_ADVANCE(ch_size);
 
830
                                continue;
 
831
                        }
 
832
 
 
833
                        /* Fall through */
 
834
                default:
 
835
                        break;
 
836
                }
 
837
 
 
838
                ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
 
839
                        size>0?((const char *)buf_ptr)[0]:'.',
 
840
                        size>1?((const char *)buf_ptr)[1]:'.',
 
841
                        size>2?((const char *)buf_ptr)[2]:'.',
 
842
                        size>3?((const char *)buf_ptr)[3]:'.',
 
843
                        size>4?((const char *)buf_ptr)[4]:'.',
 
844
                        size>5?((const char *)buf_ptr)[5]:'.');
 
845
                break;
 
846
        }
 
847
 
 
848
        ctx->phase = 4; /* "Phase out" on hard failure */
 
849
        RETURN(RC_FAIL);
 
850
}
 
851
 
 
852
asn_enc_rval_t
 
853
SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
 
854
        int ilevel, enum xer_encoder_flags_e flags,
 
855
                asn_app_consume_bytes_f *cb, void *app_key) {
 
856
        asn_enc_rval_t er;
 
857
        int xcan = (flags & XER_F_CANONICAL);
 
858
        int edx;
 
859
 
 
860
        if(!sptr)
 
861
                _ASN_ENCODE_FAILED;
 
862
 
 
863
        er.encoded = 0;
 
864
 
 
865
        for(edx = 0; edx < td->elements_count; edx++) {
 
866
                asn_enc_rval_t tmper;
 
867
                asn_TYPE_member_t *elm = &td->elements[edx];
 
868
                void *memb_ptr;
 
869
                const char *mname = elm->name;
 
870
                unsigned int mlen = strlen(mname);
 
871
 
 
872
                if(elm->flags & ATF_POINTER) {
 
873
                        memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
874
                        if(!memb_ptr) {
 
875
                                if(elm->optional)
 
876
                                        continue;
 
877
                                /* Mandatory element is missing */
 
878
                                _ASN_ENCODE_FAILED;
 
879
                        }
 
880
                } else {
 
881
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
882
                }
 
883
 
 
884
                if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel);
 
885
                _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
 
886
 
 
887
                /* Print the member itself */
 
888
                tmper = elm->type->xer_encoder(elm->type, memb_ptr,
 
889
                        ilevel + 1, flags, cb, app_key);
 
890
                if(tmper.encoded == -1) return tmper;
 
891
 
 
892
                _ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
 
893
                er.encoded += 5 + (2 * mlen) + tmper.encoded;
 
894
        }
 
895
 
 
896
        if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
 
897
 
 
898
        _ASN_ENCODED_OK(er);
 
899
cb_failed:
 
900
        _ASN_ENCODE_FAILED;
 
901
}
 
902
 
 
903
int
 
904
SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 
905
                asn_app_consume_bytes_f *cb, void *app_key) {
 
906
        int edx;
 
907
        int ret;
 
908
 
 
909
        if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
910
 
 
911
        /* Dump preamble */
 
912
        if(cb(td->name, strlen(td->name), app_key) < 0
 
913
        || cb(" ::= {", 6, app_key) < 0)
 
914
                return -1;
 
915
 
 
916
        for(edx = 0; edx < td->elements_count; edx++) {
 
917
                asn_TYPE_member_t *elm = &td->elements[edx];
 
918
                const void *memb_ptr;
 
919
 
 
920
                if(elm->flags & ATF_POINTER) {
 
921
                        memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 
922
                        if(!memb_ptr) {
 
923
                                if(elm->optional) continue;
 
924
                                /* Print <absent> line */
 
925
                                /* Fall through */
 
926
                        }
 
927
                } else {
 
928
                        memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 
929
                }
 
930
 
 
931
                /* Indentation */
 
932
                _i_INDENT(1);
 
933
 
 
934
                /* Print the member's name and stuff */
 
935
                if(cb(elm->name, strlen(elm->name), app_key) < 0
 
936
                || cb(": ", 2, app_key) < 0)
 
937
                        return -1;
 
938
 
 
939
                /* Print the member itself */
 
940
                ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
 
941
                        cb, app_key);
 
942
                if(ret) return ret;
 
943
        }
 
944
 
 
945
        ilevel--;
 
946
        _i_INDENT(1);
 
947
 
 
948
        return (cb("}", 1, app_key) < 0) ? -1 : 0;
 
949
}
 
950
 
 
951
void
 
952
SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
 
953
        int edx;
 
954
 
 
955
        if(!td || !sptr)
 
956
                return;
 
957
 
 
958
        ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
 
959
 
 
960
        for(edx = 0; edx < td->elements_count; edx++) {
 
961
                asn_TYPE_member_t *elm = &td->elements[edx];
 
962
                void *memb_ptr;
 
963
                if(elm->flags & ATF_POINTER) {
 
964
                        memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 
965
                        if(memb_ptr)
 
966
                                ASN_STRUCT_FREE(*elm->type, memb_ptr);
 
967
                } else {
 
968
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
969
                        ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
 
970
                }
 
971
        }
 
972
 
 
973
        if(!contents_only) {
 
974
                FREEMEM(sptr);
 
975
        }
 
976
}
 
977
 
 
978
int
 
979
SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 
980
                asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 
981
        int edx;
 
982
 
 
983
        if(!sptr) {
 
984
                _ASN_CTFAIL(app_key, td, sptr,
 
985
                        "%s: value not given (%s:%d)",
 
986
                        td->name, __FILE__, __LINE__);
 
987
                return -1;
 
988
        }
 
989
 
 
990
        /*
 
991
         * Iterate over structure members and check their validity.
 
992
         */
 
993
        for(edx = 0; edx < td->elements_count; edx++) {
 
994
                asn_TYPE_member_t *elm = &td->elements[edx];
 
995
                const void *memb_ptr;
 
996
 
 
997
                if(elm->flags & ATF_POINTER) {
 
998
                        memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 
999
                        if(!memb_ptr) {
 
1000
                                if(elm->optional)
 
1001
                                        continue;
 
1002
                                _ASN_CTFAIL(app_key, td, sptr,
 
1003
                                "%s: mandatory element %s absent (%s:%d)",
 
1004
                                td->name, elm->name, __FILE__, __LINE__);
 
1005
                                return -1;
 
1006
                        }
 
1007
                } else {
 
1008
                        memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 
1009
                }
 
1010
 
 
1011
                if(elm->memb_constraints) {
 
1012
                        int ret = elm->memb_constraints(elm->type, memb_ptr,
 
1013
                                ctfailcb, app_key);
 
1014
                        if(ret) return ret;
 
1015
                } else {
 
1016
                        int ret = elm->type->check_constraints(elm->type,
 
1017
                                memb_ptr, ctfailcb, app_key);
 
1018
                        if(ret) return ret;
 
1019
                        /*
 
1020
                         * Cannot inherit it earlier:
 
1021
                         * need to make sure we get the updated version.
 
1022
                         */
 
1023
                        elm->memb_constraints = elm->type->check_constraints;
 
1024
                }
 
1025
        }
 
1026
 
 
1027
        return 0;
 
1028
}
 
1029
 
 
1030
asn_dec_rval_t
 
1031
SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 
1032
        asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
 
1033
        asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
 
1034
        void *st = *sptr;       /* Target structure. */
 
1035
        int extpresent;         /* Extension additions are present */
 
1036
        uint8_t *opres;         /* Presence of optional root members */
 
1037
        asn_per_data_t opmd;
 
1038
        asn_dec_rval_t rv;
 
1039
        int edx;
 
1040
 
 
1041
        (void)constraints;
 
1042
 
 
1043
        if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
 
1044
                _ASN_DECODE_FAILED;
 
1045
 
 
1046
        if(!st) {
 
1047
                st = *sptr = CALLOC(1, specs->struct_size);
 
1048
                if(!st) _ASN_DECODE_FAILED;
 
1049
        }
 
1050
 
 
1051
        ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);
 
1052
 
 
1053
        /* Handle extensions */
 
1054
        if(specs->ext_before >= 0) {
 
1055
                extpresent = per_get_few_bits(pd, 1);
 
1056
                if(extpresent < 0) _ASN_DECODE_STARVED;
 
1057
        } else {
 
1058
                extpresent = 0;
 
1059
        }
 
1060
 
 
1061
        /* Prepare a place and read-in the presence bitmap */
 
1062
        memset(&opmd, 0, sizeof(opmd));
 
1063
        if(specs->roms_count) {
 
1064
                opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
 
1065
                if(!opres) _ASN_DECODE_FAILED;
 
1066
                /* Get the presence map */
 
1067
                if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
 
1068
                        FREEMEM(opres);
 
1069
                        _ASN_DECODE_STARVED;
 
1070
                }
 
1071
                opmd.buffer = opres;
 
1072
                opmd.nbits = specs->roms_count;
 
1073
                ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
 
1074
                        td->name, specs->roms_count, *opres);
 
1075
        } else {
 
1076
                opres = 0;
 
1077
        }
 
1078
 
 
1079
        /*
 
1080
         * Get the sequence ROOT elements.
 
1081
         */
 
1082
        for(edx = 0; edx < td->elements_count; edx++) {
 
1083
                asn_TYPE_member_t *elm = &td->elements[edx];
 
1084
                void *memb_ptr;         /* Pointer to the member */
 
1085
                void **memb_ptr2;       /* Pointer to that pointer */
 
1086
 
 
1087
                if(IN_EXTENSION_GROUP(specs, edx))
 
1088
                        continue;
 
1089
 
 
1090
                /* Fetch the pointer to this member */
 
1091
                if(elm->flags & ATF_POINTER) {
 
1092
                        memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 
1093
                } else {
 
1094
                        memb_ptr = (char *)st + elm->memb_offset;
 
1095
                        memb_ptr2 = &memb_ptr;
 
1096
                }
 
1097
 
 
1098
                /* Deal with optionality */
 
1099
                if(elm->optional) {
 
1100
                        int present = per_get_few_bits(&opmd, 1);
 
1101
                        ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
 
1102
                                td->name, elm->name, present,
 
1103
                                (int)opmd.nboff, (int)opmd.nbits);
 
1104
                        if(present == 0) {
 
1105
                                /* This element is not present */
 
1106
                                if(elm->default_value) {
 
1107
                                        /* Fill-in DEFAULT */
 
1108
                                        if(elm->default_value(1, memb_ptr2)) {
 
1109
                                                FREEMEM(opres);
 
1110
                                                _ASN_DECODE_FAILED;
 
1111
                                        }
 
1112
                                        ASN_DEBUG("Filled-in default");
 
1113
                                }
 
1114
                                /* The member is just not present */
 
1115
                                continue;
 
1116
                        }
 
1117
                        /* Fall through */
 
1118
                }
 
1119
 
 
1120
                /* Fetch the member from the stream */
 
1121
                ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
 
1122
                rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
 
1123
                        elm->per_constraints, memb_ptr2, pd);
 
1124
                if(rv.code != RC_OK) {
 
1125
                        ASN_DEBUG("Failed decode %s in %s",
 
1126
                                elm->name, td->name);
 
1127
                        FREEMEM(opres);
 
1128
                        return rv;
 
1129
                }
 
1130
        }
 
1131
 
 
1132
        /* Optionality map is not needed anymore */
 
1133
        FREEMEM(opres);
 
1134
 
 
1135
        /*
 
1136
         * Deal with extensions.
 
1137
         */
 
1138
        if(extpresent) {
 
1139
                ssize_t bmlength;
 
1140
                uint8_t *epres;         /* Presence of extension members */
 
1141
                asn_per_data_t epmd;
 
1142
 
 
1143
                bmlength = uper_get_nslength(pd);
 
1144
                if(bmlength < 0) _ASN_DECODE_STARVED;
 
1145
 
 
1146
                ASN_DEBUG("Extensions %d present in %s", bmlength, td->name);
 
1147
 
 
1148
                epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
 
1149
                if(!epres) _ASN_DECODE_STARVED;
 
1150
 
 
1151
                /* Get the extensions map */
 
1152
                if(per_get_many_bits(pd, epres, 0, bmlength))
 
1153
                        _ASN_DECODE_STARVED;
 
1154
 
 
1155
                memset(&epmd, 0, sizeof(epmd));
 
1156
                epmd.buffer = epres;
 
1157
                epmd.nbits = bmlength;
 
1158
                ASN_DEBUG("Read in extensions bitmap for %s of %d bits (%x..)",
 
1159
                        td->name, bmlength, *epres);
 
1160
 
 
1161
            /* Go over extensions and read them in */
 
1162
            for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
 
1163
                asn_TYPE_member_t *elm = &td->elements[edx];
 
1164
                void *memb_ptr;         /* Pointer to the member */
 
1165
                void **memb_ptr2;       /* Pointer to that pointer */
 
1166
                int present;
 
1167
 
 
1168
                if(!IN_EXTENSION_GROUP(specs, edx)) {
 
1169
                        ASN_DEBUG("%d is not extension", edx);
 
1170
                        continue;
 
1171
                }
 
1172
 
 
1173
                /* Fetch the pointer to this member */
 
1174
                if(elm->flags & ATF_POINTER) {
 
1175
                        memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 
1176
                } else {
 
1177
                        memb_ptr = (void *)((char *)st + elm->memb_offset);
 
1178
                        memb_ptr2 = &memb_ptr;
 
1179
                }
 
1180
 
 
1181
                present = per_get_few_bits(&epmd, 1);
 
1182
                if(present <= 0) {
 
1183
                        if(present < 0) break;  /* No more extensions */
 
1184
                        continue;
 
1185
                }
 
1186
 
 
1187
                ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
 
1188
                rv = uper_open_type_get(opt_codec_ctx, elm->type,
 
1189
                        elm->per_constraints, memb_ptr2, pd);
 
1190
                if(rv.code != RC_OK) {
 
1191
                        FREEMEM(epres);
 
1192
                        return rv;
 
1193
                }
 
1194
            }
 
1195
 
 
1196
                /* Skip over overflow extensions which aren't present
 
1197
                 * in this system's version of the protocol */
 
1198
                for(;;) {
 
1199
                        ASN_DEBUG("Getting overflow extensions");
 
1200
                        switch(per_get_few_bits(&epmd, 1)) {
 
1201
                        case -1: break;
 
1202
                        case 0: continue;
 
1203
                        default:
 
1204
                                if(uper_open_type_skip(opt_codec_ctx, pd)) {
 
1205
                                        FREEMEM(epres);
 
1206
                                        _ASN_DECODE_STARVED;
 
1207
                                }
 
1208
                        }
 
1209
                        break;
 
1210
                }
 
1211
 
 
1212
                FREEMEM(epres);
 
1213
        }
 
1214
 
 
1215
        /* Fill DEFAULT members in extensions */
 
1216
        for(edx = specs->roms_count; edx < specs->roms_count
 
1217
                        + specs->aoms_count; edx++) {
 
1218
                asn_TYPE_member_t *elm = &td->elements[edx];
 
1219
                void **memb_ptr2;       /* Pointer to member pointer */
 
1220
 
 
1221
                if(!elm->default_value) continue;
 
1222
 
 
1223
                /* Fetch the pointer to this member */
 
1224
                if(elm->flags & ATF_POINTER) {
 
1225
                        memb_ptr2 = (void **)((char *)st
 
1226
                                        + elm->memb_offset);
 
1227
                        if(*memb_ptr2) continue;
 
1228
                } else {
 
1229
                        continue;       /* Extensions are all optionals */
 
1230
                }
 
1231
 
 
1232
                /* Set default value */
 
1233
                if(elm->default_value(1, memb_ptr2)) {
 
1234
                        _ASN_DECODE_FAILED;
 
1235
                }
 
1236
        }
 
1237
 
 
1238
        rv.consumed = 0;
 
1239
        rv.code = RC_OK;
 
1240
        return rv;
 
1241
}
 
1242
 
 
1243
static int
 
1244
SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
 
1245
                asn_per_outp_t *po1, asn_per_outp_t *po2) {
 
1246
        asn_SEQUENCE_specifics_t *specs
 
1247
                = (asn_SEQUENCE_specifics_t *)td->specifics;
 
1248
        int exts_present = 0;
 
1249
        int exts_count = 0;
 
1250
        int edx;
 
1251
 
 
1252
        if(specs->ext_before < 0)
 
1253
                return 0;
 
1254
 
 
1255
        /* Find out which extensions are present */
 
1256
        for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
 
1257
                asn_TYPE_member_t *elm = &td->elements[edx];
 
1258
                void *memb_ptr;         /* Pointer to the member */
 
1259
                void **memb_ptr2;       /* Pointer to that pointer */
 
1260
                int present;
 
1261
 
 
1262
                if(!IN_EXTENSION_GROUP(specs, edx)) {
 
1263
                        ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx);
 
1264
                        continue;
 
1265
                }
 
1266
 
 
1267
                /* Fetch the pointer to this member */
 
1268
                if(elm->flags & ATF_POINTER) {
 
1269
                        memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 
1270
                        present = (*memb_ptr2 != 0);
 
1271
                } else {
 
1272
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
1273
                        memb_ptr2 = &memb_ptr;
 
1274
                        present = 1;
 
1275
                }
 
1276
 
 
1277
                ASN_DEBUG("checking %s (@%d) present => %d",
 
1278
                        elm->type->name, edx, present);
 
1279
                exts_count++;
 
1280
                exts_present += present;
 
1281
 
 
1282
                /* Encode as presence marker */
 
1283
                if(po1 && per_put_few_bits(po1, present, 1))
 
1284
                        return -1;
 
1285
                /* Encode as open type field */
 
1286
                if(po2 && present && uper_open_type_put(elm->type,
 
1287
                                elm->per_constraints, *memb_ptr2, po2))
 
1288
                        return -1;
 
1289
 
 
1290
        }
 
1291
 
 
1292
        return exts_present ? exts_count : 0;
 
1293
}
 
1294
 
 
1295
asn_enc_rval_t
 
1296
SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
 
1297
        asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
 
1298
        asn_SEQUENCE_specifics_t *specs
 
1299
                = (asn_SEQUENCE_specifics_t *)td->specifics;
 
1300
        asn_enc_rval_t er;
 
1301
        int n_extensions;
 
1302
        int edx;
 
1303
        int i;
 
1304
 
 
1305
        (void)constraints;
 
1306
 
 
1307
        if(!sptr)
 
1308
                _ASN_ENCODE_FAILED;
 
1309
 
 
1310
        er.encoded = 0;
 
1311
 
 
1312
        ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
 
1313
 
 
1314
 
 
1315
        /*
 
1316
         * X.691#18.1 Whether structure is extensible
 
1317
         * and whether to encode extensions
 
1318
         */
 
1319
        if(specs->ext_before >= 0) {
 
1320
                n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
 
1321
                per_put_few_bits(po, n_extensions ? 1 : 0, 1);
 
1322
        } else {
 
1323
                n_extensions = 0;       /* There are no extensions to encode */
 
1324
        }
 
1325
 
 
1326
        /* Encode a presence bitmap */
 
1327
        for(i = 0; i < specs->roms_count; i++) {
 
1328
                asn_TYPE_member_t *elm;
 
1329
                void *memb_ptr;         /* Pointer to the member */
 
1330
                void **memb_ptr2;       /* Pointer to that pointer */
 
1331
                int present;
 
1332
 
 
1333
                edx = specs->oms[i];
 
1334
                elm = &td->elements[edx];
 
1335
 
 
1336
                /* Fetch the pointer to this member */
 
1337
                if(elm->flags & ATF_POINTER) {
 
1338
                        memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 
1339
                        present = (*memb_ptr2 != 0);
 
1340
                } else {
 
1341
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
1342
                        memb_ptr2 = &memb_ptr;
 
1343
                        present = 1;
 
1344
                }
 
1345
 
 
1346
                /* Eliminate default values */
 
1347
                if(present && elm->default_value
 
1348
                && elm->default_value(0, memb_ptr2) == 1)
 
1349
                        present = 0;
 
1350
 
 
1351
                ASN_DEBUG("Element %s %s %s->%s is %s",
 
1352
                        elm->flags & ATF_POINTER ? "ptr" : "inline",
 
1353
                        elm->default_value ? "def" : "wtv",
 
1354
                        td->name, elm->name, present ? "present" : "absent");
 
1355
                if(per_put_few_bits(po, present, 1))
 
1356
                        _ASN_ENCODE_FAILED;
 
1357
        }
 
1358
 
 
1359
        /*
 
1360
         * Encode the sequence ROOT elements.
 
1361
         */
 
1362
        ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
 
1363
        for(edx = 0; edx < ((specs->ext_after < 0)
 
1364
                ? td->elements_count : specs->ext_before - 1); edx++) {
 
1365
 
 
1366
                asn_TYPE_member_t *elm = &td->elements[edx];
 
1367
                void *memb_ptr;         /* Pointer to the member */
 
1368
                void **memb_ptr2;       /* Pointer to that pointer */
 
1369
 
 
1370
                if(IN_EXTENSION_GROUP(specs, edx))
 
1371
                        continue;
 
1372
 
 
1373
                ASN_DEBUG("About to encode %s", elm->type->name);
 
1374
 
 
1375
                /* Fetch the pointer to this member */
 
1376
                if(elm->flags & ATF_POINTER) {
 
1377
                        memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 
1378
                        if(!*memb_ptr2) {
 
1379
                                ASN_DEBUG("Element %s %d not present",
 
1380
                                        elm->name, edx);
 
1381
                                if(elm->optional)
 
1382
                                        continue;
 
1383
                                /* Mandatory element is missing */
 
1384
                                _ASN_ENCODE_FAILED;
 
1385
                        }
 
1386
                } else {
 
1387
                        memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 
1388
                        memb_ptr2 = &memb_ptr;
 
1389
                }
 
1390
 
 
1391
                /* Eliminate default values */
 
1392
                if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
 
1393
                        continue;
 
1394
 
 
1395
                ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
 
1396
                er = elm->type->uper_encoder(elm->type, elm->per_constraints,
 
1397
                        *memb_ptr2, po);
 
1398
                if(er.encoded == -1)
 
1399
                        return er;
 
1400
        }
 
1401
 
 
1402
        /* No extensions to encode */
 
1403
        if(!n_extensions) _ASN_ENCODED_OK(er);
 
1404
 
 
1405
        ASN_DEBUG("Length of %d bit-map", n_extensions);
 
1406
        /* #18.8. Write down the presence bit-map length. */
 
1407
        if(uper_put_nslength(po, n_extensions))
 
1408
                _ASN_ENCODE_FAILED;
 
1409
 
 
1410
        ASN_DEBUG("Bit-map of %d elements", n_extensions);
 
1411
        /* #18.7. Encoding the extensions presence bit-map. */
 
1412
        /* TODO: act upon NOTE in #18.7 for canonical PER */
 
1413
        if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
 
1414
                _ASN_ENCODE_FAILED;
 
1415
 
 
1416
        ASN_DEBUG("Writing %d extensions", n_extensions);
 
1417
        /* #18.9. Encode extensions as open type fields. */
 
1418
        if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
 
1419
                _ASN_ENCODE_FAILED;
 
1420
 
 
1421
        _ASN_ENCODED_OK(er);
 
1422
}
 
1423