~ubuntu-branches/ubuntu/intrepid/asn1c/intrepid

« back to all changes in this revision

Viewing changes to skeletons/OCTET_STRING.c

  • Committer: Bazaar Package Importer
  • Author(s): W. Borgert
  • Date: 2005-05-28 12:36:42 UTC
  • Revision ID: james.westby@ubuntu.com-20050528123642-3h6kstws5u0xcovl
Tags: upstream-0.9.14
ImportĀ upstreamĀ versionĀ 0.9.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003, 2004, 2005 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 <OCTET_STRING.h>
 
8
#include <BIT_STRING.h> /* for .bits_unused member */
 
9
#include <errno.h>
 
10
 
 
11
/*
 
12
 * OCTET STRING basic type description.
 
13
 */
 
14
static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
 
15
        (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
 
16
};
 
17
static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
 
18
        sizeof(OCTET_STRING_t),
 
19
        offsetof(OCTET_STRING_t, _asn_ctx),
 
20
        0
 
21
};
 
22
asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
 
23
        "OCTET STRING",         /* Canonical name */
 
24
        "OCTET_STRING",         /* XML tag name */
 
25
        OCTET_STRING_free,
 
26
        OCTET_STRING_print,     /* non-ascii stuff, generally */
 
27
        asn_generic_no_constraint,
 
28
        OCTET_STRING_decode_ber,
 
29
        OCTET_STRING_encode_der,
 
30
        OCTET_STRING_decode_xer_hex,
 
31
        OCTET_STRING_encode_xer,
 
32
        0, /* Use generic outmost tag fetcher */
 
33
        asn_DEF_OCTET_STRING_tags,
 
34
        sizeof(asn_DEF_OCTET_STRING_tags)
 
35
          / sizeof(asn_DEF_OCTET_STRING_tags[0]),
 
36
        asn_DEF_OCTET_STRING_tags,      /* Same as above */
 
37
        sizeof(asn_DEF_OCTET_STRING_tags)
 
38
          / sizeof(asn_DEF_OCTET_STRING_tags[0]),
 
39
        0, 0,   /* No members */
 
40
        &asn_DEF_OCTET_STRING_specs
 
41
};
 
42
 
 
43
#undef  _CH_PHASE
 
44
#undef  NEXT_PHASE
 
45
#undef  PREV_PHASE
 
46
#define _CH_PHASE(ctx, inc) do {                                        \
 
47
                if(ctx->phase == 0)                                     \
 
48
                        ctx->context = 0;                               \
 
49
                ctx->phase += inc;                                      \
 
50
        } while(0)
 
51
#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
 
52
#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
 
53
 
 
54
#undef  ADVANCE
 
55
#define ADVANCE(num_bytes)      do {                                    \
 
56
                size_t num = (num_bytes);                               \
 
57
                buf_ptr = ((const char *)buf_ptr) + num;                \
 
58
                size -= num;                                            \
 
59
                consumed_myself += num;                                 \
 
60
        } while(0)
 
61
 
 
62
#undef  RETURN
 
63
#define RETURN(_code)   do {                                            \
 
64
                rval.code = _code;                                      \
 
65
                rval.consumed = consumed_myself;                        \
 
66
                return rval;                                            \
 
67
        } while(0)
 
68
 
 
69
#undef  APPEND
 
70
#define APPEND(bufptr, bufsize) do {                                    \
 
71
                size_t _bs = (bufsize);         /* Append size */       \
 
72
                size_t _ns = ctx->context;      /* Allocated now */     \
 
73
                size_t _es = st->size + _bs;    /* Expected size */     \
 
74
                /* int is really a typeof(st->size): */                 \
 
75
                if((int)_es < 0) RETURN(RC_FAIL);                       \
 
76
                if(_ns <= _es) {                                        \
 
77
                        void *ptr;                                      \
 
78
                        /* Be nice and round to the memory allocator */ \
 
79
                        do { _ns = _ns ? _ns << 1 : 16; }               \
 
80
                            while(_ns <= _es);                          \
 
81
                        /* int is really a typeof(st->size): */         \
 
82
                        if((int)_ns < 0) RETURN(RC_FAIL);               \
 
83
                        ptr = REALLOC(st->buf, _ns);                    \
 
84
                        if(ptr) {                                       \
 
85
                                st->buf = (uint8_t *)ptr;               \
 
86
                                ctx->context = _ns;                     \
 
87
                        } else {                                        \
 
88
                                RETURN(RC_FAIL);                        \
 
89
                        }                                               \
 
90
                        ASN_DEBUG("Reallocating into %ld", _ns);        \
 
91
                }                                                       \
 
92
                memcpy(st->buf + st->size, bufptr, _bs);                \
 
93
                /* Convenient nul-termination */                        \
 
94
                st->buf[_es] = '\0';                                    \
 
95
                st->size = _es;                                         \
 
96
        } while(0)
 
97
 
 
98
/*
 
99
 * Internal variant of the OCTET STRING.
 
100
 */
 
101
typedef enum OS_type {
 
102
        _TT_GENERIC     = 0,    /* Just a random OCTET STRING */
 
103
        _TT_BIT_STRING  = 1,    /* BIT STRING type, a special case */
 
104
        _TT_ANY         = 2,    /* ANY type, a special case too */
 
105
} OS_type_e;
 
106
 
 
107
/*
 
108
 * The main reason why ASN.1 is still alive is that too much time and effort
 
109
 * is necessary for learning it more or less adequately, thus creating a gut
 
110
 * necessity to demonstrate that aquired skill everywhere afterwards.
 
111
 * No, I am not going to explain what the following stuff is.
 
112
 */
 
113
struct _stack_el {
 
114
        ber_tlv_len_t   left;   /* What's left to read (or -1) */
 
115
        ber_tlv_len_t   got;    /* What was actually processed */
 
116
        int     cont_level;     /* Depth of subcontainment */
 
117
        int     want_nulls;     /* Want null "end of content" octets? */
 
118
        int     bits_chopped;   /* Flag in BIT STRING mode */
 
119
        ber_tlv_tag_t   tag;    /* For debugging purposes */
 
120
        struct _stack_el *prev;
 
121
        struct _stack_el *next;
 
122
};
 
123
struct _stack {
 
124
        struct _stack_el *tail;
 
125
        struct _stack_el *cur_ptr;
 
126
};
 
127
 
 
128
static struct _stack_el *
 
129
OS__add_stack_el(struct _stack *st) {
 
130
        struct _stack_el *nel;
 
131
 
 
132
        /*
 
133
         * Reuse the old stack frame or allocate a new one.
 
134
         */
 
135
        if(st->cur_ptr && st->cur_ptr->next) {
 
136
                nel = st->cur_ptr->next;
 
137
                nel->bits_chopped = 0;
 
138
                nel->got = 0;
 
139
                /* Retain the nel->cont_level, it's correct. */
 
140
        } else {
 
141
                nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
 
142
                if(nel == NULL)
 
143
                        return NULL;
 
144
        
 
145
                if(st->tail) {
 
146
                        /* Increase a subcontainment depth */
 
147
                        nel->cont_level = st->tail->cont_level + 1;
 
148
                        st->tail->next = nel;
 
149
                }
 
150
                nel->prev = st->tail;
 
151
                st->tail = nel;
 
152
        }
 
153
 
 
154
        st->cur_ptr = nel;
 
155
 
 
156
        return nel;
 
157
}
 
158
 
 
159
static struct _stack *
 
160
_new_stack() {
 
161
        return (struct _stack *)CALLOC(1, sizeof(struct _stack));
 
162
}
 
163
 
 
164
/*
 
165
 * Decode OCTET STRING type.
 
166
 */
 
167
asn_dec_rval_t
 
168
OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
 
169
        asn_TYPE_descriptor_t *td,
 
170
        void **os_structure, const void *buf_ptr, size_t size, int tag_mode) {
 
171
        asn_OCTET_STRING_specifics_t *specs = td->specifics
 
172
                                ? (asn_OCTET_STRING_specifics_t *)td->specifics
 
173
                                : &asn_DEF_OCTET_STRING_specs;
 
174
        BIT_STRING_t *st = (BIT_STRING_t *)*os_structure;
 
175
        asn_dec_rval_t rval;
 
176
        asn_struct_ctx_t *ctx;
 
177
        ssize_t consumed_myself = 0;
 
178
        struct _stack *stck;            /* Expectations stack structure */
 
179
        struct _stack_el *sel = 0;      /* Stack element */
 
180
        int tlv_constr;
 
181
        OS_type_e type_variant = (OS_type_e)specs->subvariant;
 
182
 
 
183
        ASN_DEBUG("Decoding %s as %s (frame %ld)",
 
184
                td->name,
 
185
                (type_variant == _TT_GENERIC) ?
 
186
                        "OCTET STRING" : "OS-SpecialCase",
 
187
                (long)size);
 
188
 
 
189
        /*
 
190
         * Create the string if does not exist.
 
191
         */
 
192
        if(st == NULL) {
 
193
                *os_structure = CALLOC(1, specs->struct_size);
 
194
                st = (BIT_STRING_t *)*os_structure;
 
195
                if(st == NULL)
 
196
                        RETURN(RC_FAIL);
 
197
        }
 
198
 
 
199
        /* Restore parsing context */
 
200
        ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
 
201
 
 
202
        switch(ctx->phase) {
 
203
        case 0:
 
204
                /*
 
205
                 * Check tags.
 
206
                 */
 
207
                rval = ber_check_tags(opt_codec_ctx, td, ctx,
 
208
                        buf_ptr, size, tag_mode, -1,
 
209
                        &ctx->left, &tlv_constr);
 
210
                if(rval.code != RC_OK)
 
211
                        return rval;
 
212
 
 
213
                if(tlv_constr) {
 
214
                        /*
 
215
                         * Complex operation, requires stack of expectations.
 
216
                         */
 
217
                        ctx->ptr = _new_stack();
 
218
                        if(ctx->ptr) {
 
219
                                stck = (struct _stack *)ctx->ptr;
 
220
                        } else {
 
221
                                RETURN(RC_FAIL);
 
222
                        }
 
223
                } else {
 
224
                        /*
 
225
                         * Jump into stackless primitive decoding.
 
226
                         */
 
227
                        _CH_PHASE(ctx, 3);
 
228
                        if(type_variant == _TT_ANY && tag_mode != 1)
 
229
                                APPEND(buf_ptr, rval.consumed);
 
230
                        ADVANCE(rval.consumed);
 
231
                        goto phase3;
 
232
                }
 
233
 
 
234
                NEXT_PHASE(ctx);
 
235
                /* Fall through */
 
236
        case 1:
 
237
        phase1:
 
238
                /*
 
239
                 * Fill the stack with expectations.
 
240
                 */
 
241
                stck = (struct _stack *)ctx->ptr;
 
242
                sel = stck->cur_ptr;
 
243
          do {
 
244
                ber_tlv_tag_t tlv_tag;
 
245
                ber_tlv_len_t tlv_len;
 
246
                ber_tlv_tag_t expected_tag;
 
247
                ssize_t tl, ll, tlvl;
 
248
                                /* This one works even if (sel->left == -1) */
 
249
                ssize_t Left = ((!sel||(size_t)sel->left >= size)
 
250
                                        ?(ssize_t)size:sel->left);
 
251
 
 
252
 
 
253
                ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
 
254
                        (long)(sel?sel->left:0),
 
255
                        (long)(sel?sel->want_nulls:0),
 
256
                        (long)(sel?sel->got:0)
 
257
                );
 
258
                if(sel && sel->left <= 0 && sel->want_nulls == 0) {
 
259
                        if(sel->prev) {
 
260
                                struct _stack_el *prev = sel->prev;
 
261
                                if(prev->left != -1) {
 
262
                                        if(prev->left < sel->got)
 
263
                                                RETURN(RC_FAIL);
 
264
                                        prev->left -= sel->got;
 
265
                                }
 
266
                                prev->got += sel->got;
 
267
                                sel = stck->cur_ptr = prev;
 
268
                                if(!sel) break;
 
269
                                tlv_constr = 1;
 
270
                                continue;
 
271
                        } else {
 
272
                                sel = stck->cur_ptr = 0;
 
273
                                break;  /* Nothing to wait */
 
274
                        }
 
275
                }
 
276
 
 
277
                tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
 
278
                ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
 
279
                        (long)size, (long)Left, sel?"":"!",
 
280
                        (long)(sel?sel->left:0),
 
281
                        (long)(sel?sel->want_nulls:0),
 
282
                        (long)tl);
 
283
                switch(tl) {
 
284
                case -1: RETURN(RC_FAIL);
 
285
                case 0: RETURN(RC_WMORE);
 
286
                }
 
287
 
 
288
                tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
 
289
 
 
290
                ll = ber_fetch_length(tlv_constr,
 
291
                                (const char *)buf_ptr + tl,Left - tl,&tlv_len);
 
292
                ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
 
293
                        ber_tlv_tag_string(tlv_tag), tlv_constr,
 
294
                                (long)Left, (long)tl, (long)tlv_len, (long)ll);
 
295
                switch(ll) {
 
296
                case -1: RETURN(RC_FAIL);
 
297
                case 0: RETURN(RC_WMORE);
 
298
                }
 
299
 
 
300
                if(sel && sel->want_nulls
 
301
                        && ((const uint8_t *)buf_ptr)[0] == 0
 
302
                        && ((const uint8_t *)buf_ptr)[1] == 0)
 
303
                {
 
304
 
 
305
                        ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
 
306
 
 
307
                        if(type_variant == _TT_ANY
 
308
                        && (tag_mode != 1 || sel->cont_level))
 
309
                                APPEND("\0\0", 2);
 
310
 
 
311
                        ADVANCE(2);
 
312
                        sel->got += 2;
 
313
                        if(sel->left != -1) {
 
314
                                sel->left -= 2; /* assert(sel->left >= 2) */
 
315
                        }
 
316
 
 
317
                        sel->want_nulls--;
 
318
                        if(sel->want_nulls == 0) {
 
319
                                /* Move to the next expectation */
 
320
                                sel->left = 0;
 
321
                                tlv_constr = 1;
 
322
                        }
 
323
 
 
324
                        continue;
 
325
                }
 
326
 
 
327
                /*
 
328
                 * Set up expected tags,
 
329
                 * depending on ASN.1 type being decoded.
 
330
                 */
 
331
                switch(type_variant) {
 
332
                case _TT_BIT_STRING:
 
333
                        /* X.690: 8.6.4.1, NOTE 2 */
 
334
                        /* Fall through */
 
335
                case _TT_GENERIC:
 
336
                default:
 
337
                        if(sel) {
 
338
                                int level = sel->cont_level;
 
339
                                if(level < td->all_tags_count) {
 
340
                                        expected_tag = td->all_tags[level];
 
341
                                        break;
 
342
                                } else if(td->all_tags_count) {
 
343
                                        expected_tag = td->all_tags
 
344
                                                [td->all_tags_count - 1];
 
345
                                        break;
 
346
                                }
 
347
                                /* else, Fall through */
 
348
                        }
 
349
                        /* Fall through */
 
350
                case _TT_ANY:
 
351
                        expected_tag = tlv_tag;
 
352
                        break;
 
353
                }
 
354
 
 
355
 
 
356
                if(tlv_tag != expected_tag) {
 
357
                        char buf[2][32];
 
358
                        ber_tlv_tag_snprint(tlv_tag,
 
359
                                buf[0], sizeof(buf[0]));
 
360
                        ber_tlv_tag_snprint(td->tags[td->tags_count-1],
 
361
                                buf[1], sizeof(buf[1]));
 
362
                        ASN_DEBUG("Tag does not match expectation: %s != %s",
 
363
                                buf[0], buf[1]);
 
364
                        RETURN(RC_FAIL);
 
365
                }
 
366
 
 
367
                tlvl = tl + ll; /* Combined length of T and L encoding */
 
368
                if((tlv_len + tlvl) < 0) {
 
369
                        /* tlv_len value is too big */
 
370
                        ASN_DEBUG("TLV encoding + length (%ld) is too big",
 
371
                                (long)tlv_len);
 
372
                        RETURN(RC_FAIL);
 
373
                }
 
374
 
 
375
                /*
 
376
                 * Append a new expectation.
 
377
                 */
 
378
                sel = OS__add_stack_el(stck);
 
379
                if(!sel) RETURN(RC_FAIL);
 
380
 
 
381
                sel->tag = tlv_tag;
 
382
 
 
383
                sel->want_nulls = (tlv_len==-1);
 
384
                if(sel->prev && sel->prev->left != -1) {
 
385
                        /* Check that the parent frame is big enough */
 
386
                        if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
 
387
                                RETURN(RC_FAIL);
 
388
                        if(tlv_len == -1)
 
389
                                sel->left = sel->prev->left - tlvl;
 
390
                        else
 
391
                                sel->left = tlv_len;
 
392
                } else {
 
393
                        sel->left = tlv_len;
 
394
                }
 
395
                if(type_variant == _TT_ANY
 
396
                && (tag_mode != 1 || sel->cont_level))
 
397
                        APPEND(buf_ptr, tlvl);
 
398
                sel->got += tlvl;
 
399
                ADVANCE(tlvl);
 
400
 
 
401
                ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
 
402
                        (long)sel->got, (long)sel->left,
 
403
                        sel->want_nulls, sel->cont_level);
 
404
 
 
405
          } while(tlv_constr);
 
406
                if(sel == NULL) {
 
407
                        /* Finished operation, "phase out" */
 
408
                        ASN_DEBUG("Phase out");
 
409
                        _CH_PHASE(ctx, +3);
 
410
                        break;
 
411
                }
 
412
 
 
413
                NEXT_PHASE(ctx);
 
414
                /* Fall through */
 
415
        case 2:
 
416
                stck = (struct _stack *)ctx->ptr;
 
417
                sel = stck->cur_ptr;
 
418
                ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
 
419
                        (long)sel->left, (long)size, (long)sel->got,
 
420
                                sel->want_nulls);
 
421
            {
 
422
                ber_tlv_len_t len;
 
423
 
 
424
                assert(sel->left >= 0);
 
425
 
 
426
                len = ((ber_tlv_len_t)size < sel->left)
 
427
                                ? (ber_tlv_len_t)size : sel->left;
 
428
                if(len > 0) {
 
429
                        if(type_variant == _TT_BIT_STRING
 
430
                        && sel->bits_chopped == 0) {
 
431
                                /* Put the unused-bits-octet away */
 
432
                                st->bits_unused = *(const uint8_t *)buf_ptr;
 
433
                                APPEND(((const char *)buf_ptr+1), (len - 1));
 
434
                                sel->bits_chopped = 1;
 
435
                        } else {
 
436
                                APPEND(buf_ptr, len);
 
437
                        }
 
438
                        ADVANCE(len);
 
439
                        sel->left -= len;
 
440
                        sel->got += len;
 
441
                }
 
442
 
 
443
                if(sel->left) {
 
444
                        ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
 
445
                                (long)sel->left, (long)size, sel->want_nulls);
 
446
                        RETURN(RC_WMORE);
 
447
                }
 
448
 
 
449
                PREV_PHASE(ctx);
 
450
                goto phase1;
 
451
            }
 
452
                break;
 
453
        case 3:
 
454
        phase3:
 
455
                /*
 
456
                 * Primitive form, no stack required.
 
457
                 */
 
458
                assert(ctx->left >= 0);
 
459
 
 
460
                if(size < (size_t)ctx->left) {
 
461
                        if(!size) RETURN(RC_WMORE);
 
462
                        if(type_variant == _TT_BIT_STRING && !ctx->context) {
 
463
                                st->bits_unused = *(const uint8_t *)buf_ptr;
 
464
                                ctx->left--;
 
465
                                ADVANCE(1);
 
466
                        }
 
467
                        APPEND(buf_ptr, size);
 
468
                        assert(ctx->context > 0);
 
469
                        ctx->left -= size;
 
470
                        ADVANCE(size);
 
471
                        RETURN(RC_WMORE);
 
472
                } else {
 
473
                        if(type_variant == _TT_BIT_STRING
 
474
                        && !ctx->context && ctx->left) {
 
475
                                st->bits_unused = *(const uint8_t *)buf_ptr;
 
476
                                ctx->left--;
 
477
                                ADVANCE(1);
 
478
                        }
 
479
                        APPEND(buf_ptr, ctx->left);
 
480
                        ADVANCE(ctx->left);
 
481
                        ctx->left = 0;
 
482
 
 
483
                        NEXT_PHASE(ctx);
 
484
                }
 
485
                break;
 
486
        }
 
487
 
 
488
        if(sel) {
 
489
                ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
 
490
                        sel->prev, sel->want_nulls,
 
491
                        (long)sel->left, (long)sel->got, (long)size);
 
492
                if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
 
493
                        RETURN(RC_WMORE);
 
494
                }
 
495
        }
 
496
 
 
497
        /*
 
498
         * BIT STRING-specific processing.
 
499
         */
 
500
        if(type_variant == _TT_BIT_STRING && st->size) {
 
501
                /* Finalize BIT STRING: zero out unused bits. */
 
502
                st->buf[st->size-1] &= 0xff << st->bits_unused;
 
503
        }
 
504
 
 
505
        ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
 
506
                (long)consumed_myself, td->name,
 
507
                (type_variant == _TT_GENERIC) ? (char *)st->buf : "<data>",
 
508
                (long)st->size);
 
509
 
 
510
 
 
511
        RETURN(RC_OK);
 
512
}
 
513
 
 
514
/*
 
515
 * Encode OCTET STRING type using DER.
 
516
 */
 
517
asn_enc_rval_t
 
518
OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
 
519
        int tag_mode, ber_tlv_tag_t tag,
 
520
        asn_app_consume_bytes_f *cb, void *app_key) {
 
521
        asn_enc_rval_t er;
 
522
        asn_OCTET_STRING_specifics_t *specs = td->specifics
 
523
                                ? (asn_OCTET_STRING_specifics_t *)td->specifics
 
524
                                : &asn_DEF_OCTET_STRING_specs;
 
525
        BIT_STRING_t *st = (BIT_STRING_t *)sptr;
 
526
        OS_type_e type_variant = (OS_type_e)specs->subvariant;
 
527
        int fix_last_byte = 0;
 
528
 
 
529
        ASN_DEBUG("%s %s as OCTET STRING",
 
530
                cb?"Estimating":"Encoding", td->name);
 
531
 
 
532
        /*
 
533
         * Write tags.
 
534
         */
 
535
        if(type_variant != _TT_ANY || tag_mode == 1) {
 
536
                er.encoded = der_write_tags(td,
 
537
                                (type_variant == _TT_BIT_STRING) + st->size,
 
538
                        tag_mode, type_variant == _TT_ANY, tag, cb, app_key);
 
539
                if(er.encoded == -1) {
 
540
                        er.failed_type = td;
 
541
                        er.structure_ptr = sptr;
 
542
                        return er;
 
543
                }
 
544
        } else {
 
545
                /* Disallow: [<tag>] IMPLICIT ANY */
 
546
                assert(type_variant != _TT_ANY || tag_mode != -1);
 
547
                er.encoded = 0;
 
548
        }
 
549
 
 
550
        if(!cb) {
 
551
                er.encoded += (type_variant == _TT_BIT_STRING) + st->size;
 
552
                return er;
 
553
        }
 
554
 
 
555
        /*
 
556
         * Prepare to deal with the last octet of BIT STRING.
 
557
         */
 
558
        if(type_variant == _TT_BIT_STRING) {
 
559
                uint8_t b = st->bits_unused & 0x07;
 
560
                if(b && st->size) fix_last_byte = 1;
 
561
                _ASN_CALLBACK(&b, 1);
 
562
                er.encoded++;
 
563
        }
 
564
 
 
565
        /* Invoke callback for the main part of the buffer */
 
566
        _ASN_CALLBACK(st->buf, st->size - fix_last_byte);
 
567
 
 
568
        /* The last octet should be stripped off the unused bits */
 
569
        if(fix_last_byte) {
 
570
                uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
 
571
                _ASN_CALLBACK(&b, 1);
 
572
        }
 
573
 
 
574
        er.encoded += st->size;
 
575
        return er;
 
576
cb_failed:
 
577
        _ASN_ENCODE_FAILED;
 
578
}
 
579
 
 
580
asn_enc_rval_t
 
581
OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
 
582
        int ilevel, enum xer_encoder_flags_e flags,
 
583
                asn_app_consume_bytes_f *cb, void *app_key) {
 
584
        static const char *h2c = "0123456789ABCDEF";
 
585
        const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
 
586
        asn_enc_rval_t er;
 
587
        char scratch[16 * 3 + 4];
 
588
        char *p = scratch;
 
589
        uint8_t *buf;
 
590
        uint8_t *end;
 
591
        size_t i;
 
592
 
 
593
        if(!st || !st->buf)
 
594
                _ASN_ENCODE_FAILED;
 
595
 
 
596
        er.encoded = 0;
 
597
 
 
598
        /*
 
599
         * Dump the contents of the buffer in hexadecimal.
 
600
         */
 
601
        buf = st->buf;
 
602
        end = buf + st->size;
 
603
        if(flags & XER_F_CANONICAL) {
 
604
                char *scend = scratch + (sizeof(scratch) - 2);
 
605
                for(; buf < end; buf++) {
 
606
                        if(p >= scend) {
 
607
                                _ASN_CALLBACK(scratch, p - scratch);
 
608
                                er.encoded += p - scratch;
 
609
                                p = scratch;
 
610
                        }
 
611
                        *p++ = h2c[(*buf >> 4) & 0x0F];
 
612
                        *p++ = h2c[*buf & 0x0F];
 
613
                }
 
614
 
 
615
                _ASN_CALLBACK(scratch, p-scratch);      /* Dump the rest */
 
616
                er.encoded += p - scratch;
 
617
        } else {
 
618
                for(i = 0; buf < end; buf++, i++) {
 
619
                        if(!(i % 16) && (i || st->size > 16)) {
 
620
                                _ASN_CALLBACK(scratch, p-scratch);
 
621
                                er.encoded += (p-scratch);
 
622
                                p = scratch;
 
623
                                _i_ASN_TEXT_INDENT(1, ilevel);
 
624
                        }
 
625
                        *p++ = h2c[(*buf >> 4) & 0x0F];
 
626
                        *p++ = h2c[*buf & 0x0F];
 
627
                        *p++ = 0x20;
 
628
                }
 
629
                if(p - scratch) {
 
630
                        p--;    /* Remove the tail space */
 
631
                        _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */
 
632
                        er.encoded += p - scratch;
 
633
                        if(st->size > 16)
 
634
                                _i_ASN_TEXT_INDENT(1, ilevel-1);
 
635
                }
 
636
        }
 
637
 
 
638
        return er;
 
639
cb_failed:
 
640
        _ASN_ENCODE_FAILED;
 
641
}
 
642
 
 
643
static struct OCTET_STRING__xer_escape_table_s {
 
644
        char *string;
 
645
        int size;
 
646
} OCTET_STRING__xer_escape_table[] = {
 
647
#define OSXET(s)        { s, sizeof(s) - 1 }
 
648
        OSXET("\074\156\165\154\057\076"),      /* <nul/> */
 
649
        OSXET("\074\163\157\150\057\076"),      /* <soh/> */
 
650
        OSXET("\074\163\164\170\057\076"),      /* <stx/> */
 
651
        OSXET("\074\145\164\170\057\076"),      /* <etx/> */
 
652
        OSXET("\074\145\157\164\057\076"),      /* <eot/> */
 
653
        OSXET("\074\145\156\161\057\076"),      /* <enq/> */
 
654
        OSXET("\074\141\143\153\057\076"),      /* <ack/> */
 
655
        OSXET("\074\142\145\154\057\076"),      /* <bel/> */
 
656
        OSXET("\074\142\163\057\076"),          /* <bs/> */
 
657
        OSXET("\011"),                          /* \t */
 
658
        OSXET("\012"),                          /* \n */
 
659
        OSXET("\074\166\164\057\076"),          /* <vt/> */
 
660
        OSXET("\074\146\146\057\076"),          /* <ff/> */
 
661
        OSXET("\015"),                          /* \r */
 
662
        OSXET("\074\163\157\057\076"),          /* <so/> */
 
663
        OSXET("\074\163\151\057\076"),          /* <si/> */
 
664
        OSXET("\074\144\154\145\057\076"),      /* <dle/> */
 
665
        OSXET("\074\144\143\061\057\076"),      /* <de1/> */
 
666
        OSXET("\074\144\143\062\057\076"),      /* <de2/> */
 
667
        OSXET("\074\144\143\063\057\076"),      /* <de3/> */
 
668
        OSXET("\074\144\143\064\057\076"),      /* <de4/> */
 
669
        OSXET("\074\156\141\153\057\076"),      /* <nak/> */
 
670
        OSXET("\074\163\171\156\057\076"),      /* <syn/> */
 
671
        OSXET("\074\145\164\142\057\076"),      /* <etb/> */
 
672
        OSXET("\074\143\141\156\057\076"),      /* <can/> */
 
673
        OSXET("\074\145\155\057\076"),          /* <em/> */
 
674
        OSXET("\074\163\165\142\057\076"),      /* <sub/> */
 
675
        OSXET("\074\145\163\143\057\076"),      /* <esc/> */
 
676
        OSXET("\074\151\163\064\057\076"),      /* <is4/> */
 
677
        OSXET("\074\151\163\063\057\076"),      /* <is3/> */
 
678
        OSXET("\074\151\163\062\057\076"),      /* <is2/> */
 
679
        OSXET("\074\151\163\061\057\076"),      /* <is1/> */
 
680
        { 0, 0 },       /* " " */
 
681
        { 0, 0 },       /* ! */
 
682
        { 0, 0 },       /* \" */
 
683
        { 0, 0 },       /* # */
 
684
        { 0, 0 },       /* $ */
 
685
        { 0, 0 },       /* % */
 
686
        OSXET("\046\141\155\160\073"),  /* &amp; */
 
687
        { 0, 0 },       /* ' */
 
688
        {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */
 
689
        {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */
 
690
        {0,0},{0,0},{0,0},{0,0},                         /* 89:; */
 
691
        OSXET("\046\154\164\073"),      /* &lt; */
 
692
        { 0, 0 },       /* = */
 
693
        OSXET("\046\147\164\073"),      /* &gt; */
 
694
};
 
695
 
 
696
static int
 
697
OS__check_escaped_control_char(const void *buf, int size) {
 
698
        size_t i;
 
699
        /*
 
700
         * Inefficient algorithm which translates the escape sequences
 
701
         * defined above into characters. Returns -1 if not found.
 
702
         * TODO: replace by a faster algorithm (bsearch(), hash or
 
703
         * nested table lookups).
 
704
         */
 
705
        for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
 
706
                struct OCTET_STRING__xer_escape_table_s *el;
 
707
                el = &OCTET_STRING__xer_escape_table[i];
 
708
                if(el->size == size && memcmp(buf, el->string, size) == 0)
 
709
                        return i;
 
710
        }
 
711
        return -1;
 
712
}
 
713
 
 
714
static int
 
715
OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) {
 
716
        /*
 
717
         * This might be one of the escape sequences
 
718
         * for control characters. Check it out.
 
719
         * #11.15.5
 
720
         */
 
721
        int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size);
 
722
        if(control_char >= 0) {
 
723
                OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr;
 
724
                void *p = REALLOC(st->buf, st->size + 2);
 
725
                if(p) {
 
726
                        st->buf = (uint8_t *)p;
 
727
                        st->buf[st->size++] = control_char;
 
728
                        st->buf[st->size] = '\0';       /* nul-termination */
 
729
                        return 0;
 
730
                }
 
731
        }
 
732
        
 
733
        return -1;      /* No, it's not */
 
734
}
 
735
 
 
736
asn_enc_rval_t
 
737
OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
 
738
        int ilevel, enum xer_encoder_flags_e flags,
 
739
                asn_app_consume_bytes_f *cb, void *app_key) {
 
740
        const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
 
741
        asn_enc_rval_t er;
 
742
        uint8_t *buf, *end;
 
743
        uint8_t *ss;    /* Sequence start */
 
744
        ssize_t encoded_len = 0;
 
745
 
 
746
        (void)ilevel;   /* Unused argument */
 
747
        (void)flags;    /* Unused argument */
 
748
 
 
749
        if(!st || !st->buf)
 
750
                _ASN_ENCODE_FAILED;
 
751
 
 
752
        buf = st->buf;
 
753
        end = buf + st->size;
 
754
        for(ss = buf; buf < end; buf++) {
 
755
                unsigned int ch = *buf;
 
756
                int s_len;      /* Special encoding sequence length */
 
757
 
 
758
                /*
 
759
                 * Escape certain characters: X.680/11.15
 
760
                 */
 
761
                if(ch < sizeof(OCTET_STRING__xer_escape_table)
 
762
                        /sizeof(OCTET_STRING__xer_escape_table[0])
 
763
                && (s_len = OCTET_STRING__xer_escape_table[ch].size)) {
 
764
                        if(((buf - ss) && cb(ss, buf - ss, app_key) < 0)
 
765
                        || cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
 
766
                                        app_key) < 0)
 
767
                                _ASN_ENCODE_FAILED;
 
768
                        encoded_len += (buf - ss) + s_len;
 
769
                        ss = buf + 1;
 
770
                }
 
771
        }
 
772
 
 
773
        encoded_len += (buf - ss);
 
774
        if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
 
775
                _ASN_ENCODE_FAILED;
 
776
 
 
777
        er.encoded = encoded_len;
 
778
        return er;
 
779
}
 
780
 
 
781
/*
 
782
 * Convert from hexadecimal format (cstring): "AB CD EF"
 
783
 */
 
784
static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
 
785
        OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
 
786
        const char *chunk_stop = (const char *)chunk_buf;
 
787
        const char *p = chunk_stop;
 
788
        const char *pend = p + chunk_size;
 
789
        unsigned int clv = 0;
 
790
        int half = 0;   /* Half bit */
 
791
        uint8_t *buf;
 
792
 
 
793
        /* Reallocate buffer according to high cap estimation */
 
794
        ssize_t _ns = st->size + (chunk_size + 1) / 2;
 
795
        void *nptr = REALLOC(st->buf, _ns + 1);
 
796
        if(!nptr) return -1;
 
797
        st->buf = (uint8_t *)nptr;
 
798
        buf = st->buf + st->size;
 
799
 
 
800
        /*
 
801
         * If something like " a b c " appears here, the " a b":3 will be
 
802
         * converted, and the rest skipped. That is, unless buf_size is greater
 
803
         * than chunk_size, then it'll be equivalent to "ABC0".
 
804
         */
 
805
        for(; p < pend; p++) {
 
806
                int ch = *(const unsigned char *)p;
 
807
                switch(ch) {
 
808
                case 0x09: case 0x0a: case 0x0c: case 0x0d:
 
809
                case 0x20:
 
810
                        /* Ignore whitespace */
 
811
                        continue;
 
812
                case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
 
813
                case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
 
814
                        clv = (clv << 4) + (ch - 0x30);
 
815
                        break;
 
816
                case 0x41: case 0x42: case 0x43:        /* ABC */
 
817
                case 0x44: case 0x45: case 0x46:        /* DEF */
 
818
                        clv = (clv << 4) + (ch - 0x41 + 10);
 
819
                        break;
 
820
                case 0x61: case 0x62: case 0x63:        /* abc */
 
821
                case 0x64: case 0x65: case 0x66:        /* def */
 
822
                        clv = (clv << 4) + (ch - 0x61 + 10);
 
823
                        break;
 
824
                default:
 
825
                        *buf = 0;       /* JIC */
 
826
                        return -1;
 
827
                }
 
828
                if(half++) {
 
829
                        half = 0;
 
830
                        *buf++ = clv;
 
831
                        chunk_stop = p + 1;
 
832
                }
 
833
        }
 
834
 
 
835
        /*
 
836
         * Check partial decoding.
 
837
         */
 
838
        if(half) {
 
839
                if(have_more) {
 
840
                        /*
 
841
                         * Partial specification is fine,
 
842
                         * because no more more PXER_TEXT data is available.
 
843
                         */
 
844
                        *buf++ = clv << 4;
 
845
                        chunk_stop = p;
 
846
                }
 
847
        } else {
 
848
                chunk_stop = p;
 
849
        }
 
850
 
 
851
        st->size = buf - st->buf;       /* Adjust the buffer size */
 
852
        assert(st->size <= _ns);
 
853
        st->buf[st->size] = 0;          /* Courtesy termination */
 
854
 
 
855
        return (chunk_stop - (const char *)chunk_buf);  /* Converted size */
 
856
}
 
857
 
 
858
/*
 
859
 * Convert from binary format: "00101011101"
 
860
 */
 
861
static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
 
862
        BIT_STRING_t *st = (BIT_STRING_t *)sptr;
 
863
        const char *p = (const char *)chunk_buf;
 
864
        const char *pend = p + chunk_size;
 
865
        int bits_unused = st->bits_unused & 0x7;
 
866
        uint8_t *buf;
 
867
 
 
868
        /* Reallocate buffer according to high cap estimation */
 
869
        ssize_t _ns = st->size + (chunk_size + 7) / 8;
 
870
        void *nptr = REALLOC(st->buf, _ns + 1);
 
871
        if(!nptr) return -1;
 
872
        st->buf = (uint8_t *)nptr;
 
873
        buf = st->buf + st->size;
 
874
 
 
875
        (void)have_more;
 
876
 
 
877
        if(bits_unused == 0)
 
878
                bits_unused = 8;
 
879
        else if(st->size)
 
880
                buf--;
 
881
 
 
882
        /*
 
883
         * Convert series of 0 and 1 into the octet string.
 
884
         */
 
885
        for(; p < pend; p++) {
 
886
                int ch = *(const unsigned char *)p;
 
887
                switch(ch) {
 
888
                case 0x09: case 0x0a: case 0x0c: case 0x0d:
 
889
                case 0x20:
 
890
                        /* Ignore whitespace */
 
891
                        break;
 
892
                case 0x30:
 
893
                case 0x31:
 
894
                        if(bits_unused-- <= 0) {
 
895
                                *++buf = 0;     /* Clean the cell */
 
896
                                bits_unused = 7;
 
897
                        }
 
898
                        *buf |= (ch&1) << bits_unused;
 
899
                        break;
 
900
                default:
 
901
                        st->bits_unused = bits_unused;
 
902
                        return -1;
 
903
                }
 
904
        }
 
905
 
 
906
        if(bits_unused == 8) {
 
907
                st->size = buf - st->buf;
 
908
                st->bits_unused = 0;
 
909
        } else {
 
910
                st->size = buf - st->buf + 1;
 
911
                st->bits_unused = bits_unused;
 
912
        }
 
913
 
 
914
        assert(st->size <= _ns);
 
915
        st->buf[st->size] = 0;          /* Courtesy termination */
 
916
 
 
917
        return chunk_size;      /* Converted in full */
 
918
}
 
919
 
 
920
/*
 
921
 * Something like strtod(), but with stricter rules.
 
922
 */
 
923
static int
 
924
OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
 
925
        int32_t val = 0;
 
926
        const char *p;
 
927
 
 
928
        for(p = buf; p < end; p++) {
 
929
                int ch = *p;
 
930
                if((val * base + base) < 0) return -1;  /* Strange huge value */
 
931
                switch(ch) {
 
932
                case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
 
933
                case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
 
934
                        val = val * base + (ch - 0x30);
 
935
                        break;
 
936
                case 0x41: case 0x42: case 0x43:        /* ABC */
 
937
                case 0x44: case 0x45: case 0x46:        /* DEF */
 
938
                        val = val * base + (ch - 0x41 + 10);
 
939
                        break;
 
940
                case 0x61: case 0x62: case 0x63:        /* abc */
 
941
                case 0x64: case 0x65: case 0x66:        /* def */
 
942
                        val = val * base + (ch - 0x61 + 10);
 
943
                        break;
 
944
                case 0x3b:      /* ';' */
 
945
                        *ret_value = val;
 
946
                        return (p - buf) + 1;
 
947
                default:
 
948
                        return -1;      /* Character set error */
 
949
                }
 
950
        }
 
951
 
 
952
        /* Do not return value. It's an error we're talking about here. */
 
953
        return (p - buf);
 
954
}
 
955
 
 
956
/*
 
957
 * Convert from the plain UTF-8 format, expanding entity references: "2 &lt; 3"
 
958
 */
 
959
static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
 
960
        OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
 
961
        const char *p = (const char *)chunk_buf;
 
962
        const char *pend = p + chunk_size;
 
963
        uint8_t *buf;
 
964
 
 
965
        /* Reallocate buffer */
 
966
        ssize_t _ns = st->size + chunk_size;
 
967
        void *nptr = REALLOC(st->buf, _ns + 1);
 
968
        if(!nptr) return -1;
 
969
        st->buf = (uint8_t *)nptr;
 
970
        buf = st->buf + st->size;
 
971
 
 
972
        /*
 
973
         * Convert series of 0 and 1 into the octet string.
 
974
         */
 
975
        for(; p < pend; p++) {
 
976
                int ch = *(const unsigned char *)p;
 
977
                int len;        /* Length of the rest of the chunk */
 
978
 
 
979
                if(ch != 0x26 /* '&' */) {
 
980
                        *buf++ = ch;
 
981
                        continue;       /* That was easy... */
 
982
                }
 
983
 
 
984
                /*
 
985
                 * Process entity reference.
 
986
                 */
 
987
                len = chunk_size - (p - (const char *)chunk_buf);
 
988
                if(len == 1 /* "&" */) goto want_more;
 
989
                if(p[1] == 0x23 /* '#' */) {
 
990
                        const char *pval;       /* Pointer to start of digits */
 
991
                        int32_t val;            /* Entity reference value */
 
992
                        int base;
 
993
 
 
994
                        if(len == 2 /* "&#" */) goto want_more;
 
995
                        if(p[2] == 0x78 /* 'x' */)
 
996
                                pval = p + 3, base = 16;
 
997
                        else
 
998
                                pval = p + 2, base = 10;
 
999
                        len = OS__strtoent(base, pval, p + len, &val);
 
1000
                        if(len == -1) {
 
1001
                                /* Invalid charset. Just copy verbatim. */
 
1002
                                *buf++ = ch;
 
1003
                                continue;
 
1004
                        }
 
1005
                        if(!len || pval[len-1] != 0x3b) goto want_more;
 
1006
                        assert(val > 0);
 
1007
                        p += (pval - p) + len - 1; /* Advance past entref */
 
1008
 
 
1009
                        if(val < 0x80) {
 
1010
                                *buf++ = (char)val;
 
1011
                        } else if(val < 0x800) {
 
1012
                                *buf++ = 0xc0 | ((val >> 6));
 
1013
                                *buf++ = 0x80 | ((val & 0x3f));
 
1014
                        } else if(val < 0x10000) {
 
1015
                                *buf++ = 0xe0 | ((val >> 12));
 
1016
                                *buf++ = 0x80 | ((val >> 6) & 0x3f);
 
1017
                                *buf++ = 0x80 | ((val & 0x3f));
 
1018
                        } else if(val < 0x200000) {
 
1019
                                *buf++ = 0xf0 | ((val >> 18));
 
1020
                                *buf++ = 0x80 | ((val >> 12) & 0x3f);
 
1021
                                *buf++ = 0x80 | ((val >> 6) & 0x3f);
 
1022
                                *buf++ = 0x80 | ((val & 0x3f));
 
1023
                        } else if(val < 0x4000000) {
 
1024
                                *buf++ = 0xf8 | ((val >> 24));
 
1025
                                *buf++ = 0x80 | ((val >> 18) & 0x3f);
 
1026
                                *buf++ = 0x80 | ((val >> 12) & 0x3f);
 
1027
                                *buf++ = 0x80 | ((val >> 6) & 0x3f);
 
1028
                                *buf++ = 0x80 | ((val & 0x3f));
 
1029
                        } else {
 
1030
                                *buf++ = 0xfc | ((val >> 30) & 0x1);
 
1031
                                *buf++ = 0x80 | ((val >> 24) & 0x3f);
 
1032
                                *buf++ = 0x80 | ((val >> 18) & 0x3f);
 
1033
                                *buf++ = 0x80 | ((val >> 12) & 0x3f);
 
1034
                                *buf++ = 0x80 | ((val >> 6) & 0x3f);
 
1035
                                *buf++ = 0x80 | ((val & 0x3f));
 
1036
                        }
 
1037
                } else {
 
1038
                        /*
 
1039
                         * Ugly, limited parsing of &amp; &gt; &lt;
 
1040
                         */
 
1041
                        char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len);
 
1042
                        if(!sc) goto want_more;
 
1043
                        if((sc - p) == 4
 
1044
                                && p[1] == 0x61 /* 'a' */
 
1045
                                && p[2] == 0x6d /* 'm' */
 
1046
                                && p[3] == 0x70 /* 'p' */) {
 
1047
                                *buf++ = 0x26;
 
1048
                                p = sc;
 
1049
                                continue;
 
1050
                        }
 
1051
                        if((sc - p) == 3) {
 
1052
                                if(p[1] == 0x6c) {
 
1053
                                        *buf = 0x3c;    /* '<' */
 
1054
                                } else if(p[1] == 0x67) {
 
1055
                                        *buf = 0x3e;    /* '>' */
 
1056
                                } else {
 
1057
                                        /* Unsupported entity reference */
 
1058
                                        *buf++ = ch;
 
1059
                                        continue;
 
1060
                                }
 
1061
                                if(p[2] != 0x74) {
 
1062
                                        /* Unsupported entity reference */
 
1063
                                        *buf++ = ch;
 
1064
                                        continue;
 
1065
                                }
 
1066
                                buf++;
 
1067
                                p = sc;
 
1068
                                continue;
 
1069
                        }
 
1070
                        /* Unsupported entity reference */
 
1071
                        *buf++ = ch;
 
1072
                }
 
1073
 
 
1074
                continue;
 
1075
        want_more:
 
1076
                if(have_more) {
 
1077
                        /*
 
1078
                         * We know that no more data (of the same type)
 
1079
                         * is coming. Copy the rest verbatim.
 
1080
                         */
 
1081
                        *buf++ = ch;
 
1082
                        continue;
 
1083
                }
 
1084
                chunk_size = (p - (const char *)chunk_buf);
 
1085
                /* Processing stalled: need more data */
 
1086
                break;
 
1087
        }
 
1088
 
 
1089
        st->size = buf - st->buf;
 
1090
        assert(st->size <= _ns);
 
1091
        st->buf[st->size] = 0;          /* Courtesy termination */
 
1092
 
 
1093
        return chunk_size;      /* Converted in full */
 
1094
}
 
1095
 
 
1096
/*
 
1097
 * Decode OCTET STRING from the XML element's body.
 
1098
 */
 
1099
static asn_dec_rval_t
 
1100
OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
 
1101
        asn_TYPE_descriptor_t *td, void **sptr,
 
1102
        const char *opt_mname, const void *buf_ptr, size_t size,
 
1103
        int (*opt_unexpected_tag_decoder)
 
1104
                (void *struct_ptr, const void *chunk_buf, size_t chunk_size),
 
1105
        ssize_t (*body_receiver)
 
1106
                (void *struct_ptr, const void *chunk_buf, size_t chunk_size,
 
1107
                        int have_more)
 
1108
) {
 
1109
        OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
 
1110
        asn_OCTET_STRING_specifics_t *specs = td->specifics
 
1111
                                ? (asn_OCTET_STRING_specifics_t *)td->specifics
 
1112
                                : &asn_DEF_OCTET_STRING_specs;
 
1113
        const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 
1114
        asn_struct_ctx_t *ctx;          /* Per-structure parser context */
 
1115
        asn_dec_rval_t rval;            /* Return value from the decoder */
 
1116
        int st_allocated;
 
1117
 
 
1118
        /*
 
1119
         * Create the string if does not exist.
 
1120
         */
 
1121
        if(!st) {
 
1122
                st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
 
1123
                *sptr = (void *)st;
 
1124
                if(!st) goto sta_failed;
 
1125
                st_allocated = 1;
 
1126
        } else {
 
1127
                st_allocated = 0;
 
1128
        }
 
1129
        if(!st->buf) {
 
1130
                /* This is separate from above section */
 
1131
                st->buf = (uint8_t *)CALLOC(1, 1);
 
1132
                if(!st->buf) {
 
1133
                        if(st_allocated) {
 
1134
                                *sptr = 0;
 
1135
                                goto stb_failed;
 
1136
                        } else {
 
1137
                                goto sta_failed;
 
1138
                        }
 
1139
                }
 
1140
        }
 
1141
 
 
1142
        /* Restore parsing context */
 
1143
        ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset);
 
1144
 
 
1145
        return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
 
1146
                buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
 
1147
 
 
1148
stb_failed:
 
1149
        FREEMEM(st);
 
1150
sta_failed:
 
1151
        rval.code = RC_FAIL;
 
1152
        rval.consumed = 0;
 
1153
        return rval;
 
1154
}
 
1155
 
 
1156
/*
 
1157
 * Decode OCTET STRING from the hexadecimal data.
 
1158
 */
 
1159
asn_dec_rval_t
 
1160
OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
 
1161
        asn_TYPE_descriptor_t *td, void **sptr,
 
1162
                const char *opt_mname, const void *buf_ptr, size_t size) {
 
1163
        return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
 
1164
                buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
 
1165
}
 
1166
 
 
1167
/*
 
1168
 * Decode OCTET STRING from the binary (0/1) data.
 
1169
 */
 
1170
asn_dec_rval_t
 
1171
OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
 
1172
        asn_TYPE_descriptor_t *td, void **sptr,
 
1173
                const char *opt_mname, const void *buf_ptr, size_t size) {
 
1174
        return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
 
1175
                buf_ptr, size, 0, OCTET_STRING__convert_binary);
 
1176
}
 
1177
 
 
1178
/*
 
1179
 * Decode OCTET STRING from the string (ASCII/UTF-8) data.
 
1180
 */
 
1181
asn_dec_rval_t
 
1182
OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
 
1183
        asn_TYPE_descriptor_t *td, void **sptr,
 
1184
                const char *opt_mname, const void *buf_ptr, size_t size) {
 
1185
        return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
 
1186
                buf_ptr, size,
 
1187
                OCTET_STRING__handle_control_chars,
 
1188
                OCTET_STRING__convert_entrefs);
 
1189
}
 
1190
 
 
1191
 
 
1192
int
 
1193
OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 
1194
        asn_app_consume_bytes_f *cb, void *app_key) {
 
1195
        static const char *h2c = "0123456789ABCDEF";
 
1196
        const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
 
1197
        char scratch[16 * 3 + 4];
 
1198
        char *p = scratch;
 
1199
        uint8_t *buf;
 
1200
        uint8_t *end;
 
1201
        size_t i;
 
1202
 
 
1203
        (void)td;       /* Unused argument */
 
1204
 
 
1205
        if(!st || !st->buf) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
1206
 
 
1207
        /*
 
1208
         * Dump the contents of the buffer in hexadecimal.
 
1209
         */
 
1210
        buf = st->buf;
 
1211
        end = buf + st->size;
 
1212
        for(i = 0; buf < end; buf++, i++) {
 
1213
                if(!(i % 16) && (i || st->size > 16)) {
 
1214
                        if(cb(scratch, p - scratch, app_key) < 0)
 
1215
                                return -1;
 
1216
                        _i_INDENT(1);
 
1217
                        p = scratch;
 
1218
                }
 
1219
                *p++ = h2c[(*buf >> 4) & 0x0F];
 
1220
                *p++ = h2c[*buf & 0x0F];
 
1221
                *p++ = 0x20;
 
1222
        }
 
1223
 
 
1224
        if(p > scratch) {
 
1225
                p--;    /* Remove the tail space */
 
1226
                if(cb(scratch, p - scratch, app_key) < 0)
 
1227
                        return -1;
 
1228
        }
 
1229
 
 
1230
        return 0;
 
1231
}
 
1232
 
 
1233
int
 
1234
OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
 
1235
                int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
 
1236
        const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
 
1237
 
 
1238
        (void)td;       /* Unused argument */
 
1239
        (void)ilevel;   /* Unused argument */
 
1240
 
 
1241
        if(st && st->buf) {
 
1242
                return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
 
1243
        } else {
 
1244
                return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
1245
        }
 
1246
}
 
1247
 
 
1248
void
 
1249
OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
 
1250
        OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
 
1251
        asn_OCTET_STRING_specifics_t *specs = td->specifics
 
1252
                                ? (asn_OCTET_STRING_specifics_t *)td->specifics
 
1253
                                : &asn_DEF_OCTET_STRING_specs;
 
1254
        asn_struct_ctx_t *ctx = (asn_struct_ctx_t *)
 
1255
                                        ((char *)st + specs->ctx_offset);
 
1256
        struct _stack *stck;
 
1257
 
 
1258
        if(!td || !st)
 
1259
                return;
 
1260
 
 
1261
        ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
 
1262
 
 
1263
        if(st->buf) {
 
1264
                FREEMEM(st->buf);
 
1265
        }
 
1266
 
 
1267
        /*
 
1268
         * Remove decode-time stack.
 
1269
         */
 
1270
        stck = (struct _stack *)ctx->ptr;
 
1271
        if(stck) {
 
1272
                while(stck->tail) {
 
1273
                        struct _stack_el *sel = stck->tail;
 
1274
                        stck->tail = sel->prev;
 
1275
                        FREEMEM(sel);
 
1276
                }
 
1277
                FREEMEM(stck);
 
1278
        }
 
1279
 
 
1280
        if(!contents_only) {
 
1281
                FREEMEM(st);
 
1282
        }
 
1283
}
 
1284
 
 
1285
/*
 
1286
 * Conversion routines.
 
1287
 */
 
1288
int
 
1289
OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
 
1290
        void *buf;
 
1291
 
 
1292
        if(st == 0 || (str == 0 && len)) {
 
1293
                errno = EINVAL;
 
1294
                return -1;
 
1295
        }
 
1296
 
 
1297
        /*
 
1298
         * Clear the OCTET STRING.
 
1299
         */
 
1300
        if(str == NULL) {
 
1301
                if(st->buf)
 
1302
                        FREEMEM(st->buf);
 
1303
                st->size = 0;
 
1304
                return 0;
 
1305
        }
 
1306
 
 
1307
        /* Determine the original string size, if not explicitly given */
 
1308
        if(len < 0)
 
1309
                len = strlen(str);
 
1310
 
 
1311
        /* Allocate and fill the memory */
 
1312
        buf = MALLOC(len + 1);
 
1313
        if(buf == NULL) {
 
1314
                return -1;
 
1315
        } else {
 
1316
                st->buf = (uint8_t *)buf;
 
1317
                st->size = len;
 
1318
        }
 
1319
 
 
1320
        memcpy(buf, str, len);
 
1321
        st->buf[st->size] = '\0';       /* Couldn't use memcpy(len+1)! */
 
1322
 
 
1323
        return 0;
 
1324
}
 
1325
 
 
1326
OCTET_STRING_t *
 
1327
OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
 
1328
        asn_OCTET_STRING_specifics_t *specs = td->specifics
 
1329
                                ? (asn_OCTET_STRING_specifics_t *)td->specifics
 
1330
                                : &asn_DEF_OCTET_STRING_specs;
 
1331
        OCTET_STRING_t *st;
 
1332
 
 
1333
        st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
 
1334
        if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
 
1335
                free(st);
 
1336
                st = NULL;
 
1337
        }
 
1338
 
 
1339
        return st;
 
1340
}
 
1341