blob: ad2ca604d9ddc825eeabc0de84d6fef9b71514f1 [file] [log] [blame]
Harald Welte43ab79f2018-10-03 23:34:21 +02001/*-
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 */
12static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
13 (ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
14};
15static 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};
20asn_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 OCTET_STRING_decode_aper, /* Aligned PER decoder */
33 OCTET_STRING_encode_aper, /* Aligned PER encoder */
34 0, /* Use generic outmost tag fetcher */
35 asn_DEF_BIT_STRING_tags,
36 sizeof(asn_DEF_BIT_STRING_tags)
37 / sizeof(asn_DEF_BIT_STRING_tags[0]),
38 asn_DEF_BIT_STRING_tags, /* Same as above */
39 sizeof(asn_DEF_BIT_STRING_tags)
40 / sizeof(asn_DEF_BIT_STRING_tags[0]),
41 0, /* No PER visible constraints */
42 0, 0, /* No members */
43 &asn_DEF_BIT_STRING_specs
44};
45
46/*
47 * BIT STRING generic constraint.
48 */
49int
50BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
51 asn_app_constraint_failed_f *ctfailcb, void *app_key) {
52 const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
53
54 if(st && st->buf) {
55 if((st->size == 0 && st->bits_unused)
56 || st->bits_unused < 0 || st->bits_unused > 7) {
57 _ASN_CTFAIL(app_key, td, sptr,
58 "%s: invalid padding byte (%s:%d)",
59 td->name, __FILE__, __LINE__);
60 return -1;
61 }
62 } else {
63 _ASN_CTFAIL(app_key, td, sptr,
64 "%s: value not given (%s:%d)",
65 td->name, __FILE__, __LINE__);
66 return -1;
67 }
68
69 return 0;
70}
71
72static char *_bit_pattern[16] = {
73 "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
74 "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
75};
76
77asn_enc_rval_t
78BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
79 int ilevel, enum xer_encoder_flags_e flags,
80 asn_app_consume_bytes_f *cb, void *app_key) {
81 asn_enc_rval_t er;
82 char scratch[128];
83 char *p = scratch;
84 char *scend = scratch + (sizeof(scratch) - 10);
85 const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
86 int xcan = (flags & XER_F_CANONICAL);
87 uint8_t *buf;
88 uint8_t *end;
89
90 if(!st || !st->buf)
91 _ASN_ENCODE_FAILED;
92
93 er.encoded = 0;
94
95 buf = st->buf;
96 end = buf + st->size - 1; /* Last byte is special */
97
98 /*
99 * Binary dump
100 */
101 for(; buf < end; buf++) {
102 int v = *buf;
103 int nline = xcan?0:(((buf - st->buf) % 8) == 0);
104 if(p >= scend || nline) {
105 er.encoded += p - scratch;
106 _ASN_CALLBACK(scratch, p - scratch);
107 p = scratch;
108 if(nline) _i_ASN_TEXT_INDENT(1, ilevel);
109 }
110 memcpy(p + 0, _bit_pattern[v >> 4], 4);
111 memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
112 p += 8;
113 }
114
115 if(!xcan && ((buf - st->buf) % 8) == 0)
116 _i_ASN_TEXT_INDENT(1, ilevel);
117 er.encoded += p - scratch;
118 _ASN_CALLBACK(scratch, p - scratch);
119 p = scratch;
120
121 if(buf == end) {
122 int v = *buf;
123 int ubits = st->bits_unused;
124 int i;
125 for(i = 7; i >= ubits; i--)
126 *p++ = (v & (1 << i)) ? 0x31 : 0x30;
127 er.encoded += p - scratch;
128 _ASN_CALLBACK(scratch, p - scratch);
129 }
130
131 if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
132
133 _ASN_ENCODED_OK(er);
134cb_failed:
135 _ASN_ENCODE_FAILED;
136}
137
138
139/*
140 * BIT STRING specific contents printer.
141 */
142int
143BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
144 asn_app_consume_bytes_f *cb, void *app_key) {
145 const char * const h2c = "0123456789ABCDEF";
146 char scratch[64];
147 const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
148 uint8_t *buf;
149 uint8_t *end;
150 char *p = scratch;
151
152 (void)td; /* Unused argument */
153
154 if(!st || !st->buf)
155 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
156
157 ilevel++;
158 buf = st->buf;
159 end = buf + st->size;
160
161 /*
162 * Hexadecimal dump.
163 */
164 for(; buf < end; buf++) {
165 if((buf - st->buf) % 16 == 0 && (st->size > 16)
166 && buf != st->buf) {
167 _i_INDENT(1);
168 /* Dump the string */
169 if(cb(scratch, p - scratch, app_key) < 0) return -1;
170 p = scratch;
171 }
172 *p++ = h2c[*buf >> 4];
173 *p++ = h2c[*buf & 0x0F];
174 *p++ = 0x20;
175 }
176
177 if(p > scratch) {
178 p--; /* Eat the tailing space */
179
180 if((st->size > 16)) {
181 _i_INDENT(1);
182 }
183
184 /* Dump the incomplete 16-bytes row */
185 if(cb(scratch, p - scratch, app_key) < 0)
186 return -1;
187 }
188
189 return 0;
190}
191