]> git.stg.codes - stg.git/blob - stglibs/smux.lib/BIT_STRING.c
User parser refactoring.
[stg.git] / stglibs / smux.lib / BIT_STRING.c
1 /*-
2  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
5 #include <asn_internal.h>
6 #include <BIT_STRING.h>
7 #include <asn_internal.h>
8
9 /*
10  * BIT STRING basic type description.
11  */
12 static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
13         (ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
14 };
15 static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
16         sizeof(BIT_STRING_t),
17         offsetof(BIT_STRING_t, _asn_ctx),
18         1,      /* Special indicator that this is a BIT STRING type */
19 };
20 asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
21         "BIT STRING",
22         "BIT_STRING",
23         OCTET_STRING_free,         /* Implemented in terms of OCTET STRING */
24         BIT_STRING_print,
25         BIT_STRING_constraint,
26         OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */
27         OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */
28         OCTET_STRING_decode_xer_binary,
29         BIT_STRING_encode_xer,
30         OCTET_STRING_decode_uper,       /* Unaligned PER decoder */
31         OCTET_STRING_encode_uper,       /* Unaligned PER encoder */
32         0, /* Use generic outmost tag fetcher */
33         asn_DEF_BIT_STRING_tags,
34         sizeof(asn_DEF_BIT_STRING_tags)
35           / sizeof(asn_DEF_BIT_STRING_tags[0]),
36         asn_DEF_BIT_STRING_tags,        /* Same as above */
37         sizeof(asn_DEF_BIT_STRING_tags)
38           / sizeof(asn_DEF_BIT_STRING_tags[0]),
39         0,      /* No PER visible constraints */
40         0, 0,   /* No members */
41         &asn_DEF_BIT_STRING_specs
42 };
43
44 /*
45  * BIT STRING generic constraint.
46  */
47 int
48 BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
49                 asn_app_constraint_failed_f *ctfailcb, void *app_key) {
50         const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
51
52         if(st && st->buf) {
53                 if(st->size == 1 && st->bits_unused) {
54                         _ASN_CTFAIL(app_key, td,
55                                 "%s: invalid padding byte (%s:%d)",
56                                 td->name, __FILE__, __LINE__);
57                         return -1;
58                 }
59         } else {
60                 _ASN_CTFAIL(app_key, td,
61                         "%s: value not given (%s:%d)",
62                         td->name, __FILE__, __LINE__);
63                 return -1;
64         }
65
66         return 0;
67 }
68
69 static char *_bit_pattern[16] = {
70         "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
71         "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
72 };
73
74 asn_enc_rval_t
75 BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
76         int ilevel, enum xer_encoder_flags_e flags,
77                 asn_app_consume_bytes_f *cb, void *app_key) {
78         asn_enc_rval_t er;
79         char scratch[128];
80         char *p = scratch;
81         char *scend = scratch + (sizeof(scratch) - 10);
82         const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
83         int xcan = (flags & XER_F_CANONICAL);
84         uint8_t *buf;
85         uint8_t *end;
86
87         if(!st || !st->buf)
88                 _ASN_ENCODE_FAILED;
89
90         er.encoded = 0;
91
92         buf = st->buf;
93         end = buf + st->size - 1;       /* Last byte is special */
94
95         /*
96          * Binary dump
97          */
98         for(; buf < end; buf++) {
99                 int v = *buf;
100                 int nline = xcan?0:(((buf - st->buf) % 8) == 0);
101                 if(p >= scend || nline) {
102                         er.encoded += p - scratch;
103                         _ASN_CALLBACK(scratch, p - scratch);
104                         p = scratch;
105                         if(nline) _i_ASN_TEXT_INDENT(1, ilevel);
106                 }
107                 memcpy(p + 0, _bit_pattern[v >> 4], 4);
108                 memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
109                 p += 8;
110         }
111
112         if(!xcan && ((buf - st->buf) % 8) == 0)
113                 _i_ASN_TEXT_INDENT(1, ilevel);
114         er.encoded += p - scratch;
115         _ASN_CALLBACK(scratch, p - scratch);
116         p = scratch;
117
118         if(buf == end) {
119                 int v = *buf;
120                 int ubits = st->bits_unused;
121                 int i;
122                 for(i = 7; i >= ubits; i--)
123                         *p++ = (v & (1 << i)) ? 0x31 : 0x30;
124                 er.encoded += p - scratch;
125                 _ASN_CALLBACK(scratch, p - scratch);
126         }
127
128         if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
129
130         _ASN_ENCODED_OK(er);
131 cb_failed:
132         _ASN_ENCODE_FAILED;
133 }
134
135
136 /*
137  * BIT STRING specific contents printer.
138  */
139 int
140 BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
141                 asn_app_consume_bytes_f *cb, void *app_key) {
142         static const char *h2c = "0123456789ABCDEF";
143         char scratch[64];
144         const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
145         uint8_t *buf;
146         uint8_t *end;
147         char *p = scratch;
148
149         (void)td;       /* Unused argument */
150
151         if(!st || !st->buf)
152                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
153
154         ilevel++;
155         buf = st->buf;
156         end = buf + st->size;
157
158         /*
159          * Hexadecimal dump.
160          */
161         for(; buf < end; buf++) {
162                 if((buf - st->buf) % 16 == 0 && (st->size > 16)
163                                 && buf != st->buf) {
164                         _i_INDENT(1);
165                         /* Dump the string */
166                         if(cb(scratch, p - scratch, app_key) < 0) return -1;
167                         p = scratch;
168                 }
169                 *p++ = h2c[*buf >> 4];
170                 *p++ = h2c[*buf & 0x0F];
171                 *p++ = 0x20;
172         }
173
174         if(p > scratch) {
175                 p--;    /* Eat the tailing space */
176
177                 if((st->size > 16)) {
178                         _i_INDENT(1);
179                 }
180
181                 /* Dump the incomplete 16-bytes row */
182                 if(cb(scratch, p - scratch, app_key) < 0)
183                         return -1;
184         }
185
186         return 0;
187 }
188