]> git.stg.codes - stg.git/blob - libs/smux/BIT_STRING.c
Fight Optional
[stg.git] / libs / smux / 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 const 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         ASN_OSUBV_BIT
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 == 0 && st->bits_unused)
54                 || st->bits_unused < 0 || st->bits_unused > 7) {
55                         ASN__CTFAIL(app_key, td, sptr,
56                                 "%s: invalid padding byte (%s:%d)",
57                                 td->name, __FILE__, __LINE__);
58                         return -1;
59                 }
60         } else {
61                 ASN__CTFAIL(app_key, td, sptr,
62                         "%s: value not given (%s:%d)",
63                         td->name, __FILE__, __LINE__);
64                 return -1;
65         }
66
67         return 0;
68 }
69
70 static char *_bit_pattern[16] = {
71         "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
72         "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
73 };
74
75 asn_enc_rval_t
76 BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
77         int ilevel, enum xer_encoder_flags_e flags,
78                 asn_app_consume_bytes_f *cb, void *app_key) {
79         asn_enc_rval_t er;
80         char scratch[128];
81         char *p = scratch;
82         char *scend = scratch + (sizeof(scratch) - 10);
83         const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
84         int xcan = (flags & XER_F_CANONICAL);
85         uint8_t *buf;
86         uint8_t *end;
87
88         if(!st || !st->buf)
89                 ASN__ENCODE_FAILED;
90
91         er.encoded = 0;
92
93         buf = st->buf;
94         end = buf + st->size - 1;       /* Last byte is special */
95
96         /*
97          * Binary dump
98          */
99         for(; buf < end; buf++) {
100                 int v = *buf;
101                 int nline = xcan?0:(((buf - st->buf) % 8) == 0);
102                 if(p >= scend || nline) {
103                         er.encoded += p - scratch;
104                         ASN__CALLBACK(scratch, p - scratch);
105                         p = scratch;
106                         if(nline) ASN__TEXT_INDENT(1, ilevel);
107                 }
108                 memcpy(p + 0, _bit_pattern[v >> 4], 4);
109                 memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
110                 p += 8;
111         }
112
113         if(!xcan && ((buf - st->buf) % 8) == 0)
114                 ASN__TEXT_INDENT(1, ilevel);
115         er.encoded += p - scratch;
116         ASN__CALLBACK(scratch, p - scratch);
117         p = scratch;
118
119         if(buf == end) {
120                 int v = *buf;
121                 int ubits = st->bits_unused;
122                 int i;
123                 for(i = 7; i >= ubits; i--)
124                         *p++ = (v & (1 << i)) ? 0x31 : 0x30;
125                 er.encoded += p - scratch;
126                 ASN__CALLBACK(scratch, p - scratch);
127         }
128
129         if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
130
131         ASN__ENCODED_OK(er);
132 cb_failed:
133         ASN__ENCODE_FAILED;
134 }
135
136
137 /*
138  * BIT STRING specific contents printer.
139  */
140 int
141 BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
142                 asn_app_consume_bytes_f *cb, void *app_key) {
143         const char * const h2c = "0123456789ABCDEF";
144         char scratch[64];
145         const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
146         uint8_t *buf;
147         uint8_t *end;
148         char *p = scratch;
149
150         (void)td;       /* Unused argument */
151
152         if(!st || !st->buf)
153                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
154
155         ilevel++;
156         buf = st->buf;
157         end = buf + st->size;
158
159         /*
160          * Hexadecimal dump.
161          */
162         for(; buf < end; buf++) {
163                 if((buf - st->buf) % 16 == 0 && (st->size > 16)
164                                 && buf != st->buf) {
165                         _i_INDENT(1);
166                         /* Dump the string */
167                         if(cb(scratch, p - scratch, app_key) < 0) return -1;
168                         p = scratch;
169                 }
170                 *p++ = h2c[*buf >> 4];
171                 *p++ = h2c[*buf & 0x0F];
172                 *p++ = 0x20;
173         }
174
175         if(p > scratch) {
176                 p--;    /* Eat the tailing space */
177
178                 if((st->size > 16)) {
179                         _i_INDENT(1);
180                 }
181
182                 /* Dump the incomplete 16-bytes row */
183                 if(cb(scratch, p - scratch, app_key) < 0)
184                         return -1;
185         }
186
187         return 0;
188 }
189