1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.asn1.util;
21
22
23 import org.apache.directory.api.i18n.I18n;
24
25
26
27
28
29
30
31
32 public class BitString
33 {
34
35 public static final BitString EMPTY_STRING = new BitString( 1 );
36
37
38 private int nbUnusedBits;
39
40
41 private byte[] bytes;
42
43
44 private int nbBytes;
45
46
47 private int nbBits;
48
49
50
51
52
53
54
55
56 public BitString( int length )
57 {
58 if ( length <= 0 )
59 {
60
61 throw new IndexOutOfBoundsException( I18n.err( I18n.ERR_00029_NULL_OR_NEG_LENGTH_NOT_ALLOWED ) );
62 }
63
64 nbBits = length;
65
66
67 nbBytes = ( length / 8 );
68
69 if ( ( length % 8 ) != 0 )
70 {
71 nbBytes += 1;
72 }
73
74 nbUnusedBits = ( 8 - ( length % 8 ) ) & 0x07;
75
76 bytes = new byte[nbBytes];
77 }
78
79
80
81
82
83
84
85
86
87 public BitString( byte[] bytes )
88 {
89 if ( ( bytes == null ) || ( bytes.length == 0 ) )
90 {
91 nbBits = -1;
92 return;
93 }
94
95 setData( bytes );
96 }
97
98
99
100
101
102
103
104
105 public void setData( byte[] bytes )
106 {
107 if ( ( bytes == null ) || ( bytes.length == 0 ) )
108 {
109 nbBits = -1;
110 return;
111 }
112
113
114 nbUnusedBits = bytes[0] & 0x07;
115 nbBytes = bytes.length - 1;
116 nbBits = ( nbBytes * 8 ) - nbUnusedBits;
117 this.bytes = new byte[nbBytes];
118
119
120 for ( int i = 0; i < nbBytes; i++ )
121 {
122 this.bytes[i] = bytes[i + 1];
123 }
124 }
125
126
127
128
129
130
131
132
133 public byte[] getData()
134 {
135 byte[] copy = new byte[bytes.length + 1];
136
137 System.arraycopy( bytes, 0, copy, 1, bytes.length );
138 copy[0] = ( byte ) nbUnusedBits;
139
140 return copy;
141 }
142
143
144
145
146
147
148
149 public byte getUnusedBits()
150 {
151 return ( byte ) nbUnusedBits;
152 }
153
154
155
156
157
158
159
160
161
162 public void setBit( int pos )
163 {
164 if ( ( pos < 0 ) || ( pos > nbBits ) )
165 {
166 throw new IndexOutOfBoundsException( I18n.err( I18n.ERR_00030_BIT_NUMBER_OUT_OF_BOUND ) );
167 }
168
169 int posBytes = pos >>> 3;
170 int bitNumber = 7 - pos % 8;
171 byte mask = ( byte ) ( 1 << bitNumber );
172
173 bytes[posBytes] |= mask;
174 }
175
176
177
178
179
180
181
182
183
184
185 public void clearBit( int pos )
186 {
187 if ( ( pos < 0 ) || ( pos > nbBits ) )
188 {
189 throw new IndexOutOfBoundsException( I18n.err( I18n.ERR_00030_BIT_NUMBER_OUT_OF_BOUND ) );
190 }
191
192 int posBytes = pos >>> 3;
193 int bitNumber = 7 - pos % 8;
194 byte mask = ( byte ) ( 1 << bitNumber );
195
196 bytes[posBytes] &= ~mask;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 public boolean getBit( int pos )
220 {
221 if ( pos > nbBits )
222 {
223 throw new IndexOutOfBoundsException( I18n.err( I18n.ERR_00031_CANNOT_FIND_BIT, pos, nbBits ) );
224 }
225
226 int posBytes = pos >>> 3;
227 int bitNumber = 7 - pos % 8;
228 byte mask = ( byte ) ( 1 << bitNumber );
229
230 int res = bytes[posBytes] & mask;
231
232 return res != 0;
233 }
234
235
236
237
238
239 public int size()
240 {
241 return nbBits;
242 }
243
244
245
246
247
248
249
250 @Override
251 public String toString()
252 {
253 StringBuilder sb = new StringBuilder();
254
255 for ( int i = 0; i < nbBits; i++ )
256 {
257 if ( getBit( i ) )
258 {
259 sb.append( '1' );
260 }
261 else
262 {
263 sb.append( '0' );
264 }
265 }
266
267 return sb.toString();
268 }
269 }