5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Marek Safar (marek.safar@gmail.com)
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.Runtime
.InteropServices
;
37 namespace System
.Collections
{
45 sealed class BitArray
: ICollection
, ICloneable
{
51 public BitArray (BitArray bits
)
54 throw new ArgumentNullException ("bits");
56 m_length
= bits
.m_length
;
57 m_array
= new int [(m_length
+ 31) / 32];
58 if (m_array
.Length
== 1)
59 m_array
[0] = bits
.m_array
[0];
61 Array
.Copy(bits
.m_array
, m_array
, m_array
.Length
);
64 public BitArray (bool [] values
)
67 throw new ArgumentNullException ("values");
69 m_length
= values
.Length
;
70 m_array
= new int [(m_length
+ 31) / 32];
72 for (int i
= 0; i
< values
.Length
; i
++)
73 this [i
] = values
[i
];
76 public BitArray (byte [] bytes
)
79 throw new ArgumentNullException ("bytes");
81 m_length
= bytes
.Length
* 8;
82 m_array
= new int [(m_length
+ 31) / 32];
84 for (int i
= 0; i
< bytes
.Length
; i
++)
85 setByte (i
, bytes
[i
]);
88 public BitArray (int [] values
)
91 throw new ArgumentNullException ("values");
93 int arrlen
= values
.Length
;
95 m_array
= new int [arrlen
];
96 Array
.Copy (values
, m_array
, arrlen
);
99 public BitArray (int length
)
102 throw new ArgumentOutOfRangeException ("length");
105 m_array
= new int [(m_length
+ 31) / 32];
108 public BitArray (int length
, bool defaultValue
) : this (length
)
111 for (int i
= 0; i
< m_array
.Length
; i
++)
116 private BitArray (int [] array
, int length
)
122 #region Utility Methods
124 byte getByte (int byteIndex
)
126 int index
= byteIndex
/ 4;
127 int shift
= (byteIndex
% 4) * 8;
129 int theByte
= m_array
[index
] & (0xff << shift
);
131 return (byte)((theByte
>> shift
) & 0xff);
134 void setByte (int byteIndex
, byte value)
136 int index
= byteIndex
/ 4;
137 int shift
= (byteIndex
% 4) * 8;
140 m_array
[index
] &= ~
(0xff << shift
);
141 // or in the new byte
142 m_array
[index
] |= value << shift
;
147 void checkOperand (BitArray operand
)
150 throw new ArgumentNullException ();
151 if (operand
.m_length
!= m_length
)
152 throw new ArgumentException ();
157 get { return m_length; }
160 public bool IsReadOnly
{
161 get { return false; }
164 public bool IsSynchronized
{
165 get { return false; }
168 public bool this [int index
] {
169 get { return Get (index); }
170 set { Set (index, value); }
174 get { return m_length; }
176 if (m_length
== value)
180 throw new ArgumentOutOfRangeException ();
182 // Currently we never shrink the array
183 if (value > m_length
) {
184 int numints
= (value + 31) / 32;
185 int old_numints
= (m_length
+ 31) / 32;
186 if (numints
> m_array
.Length
) {
187 int [] newArr
= new int [numints
];
188 Array
.Copy (m_array
, newArr
, m_array
.Length
);
191 Array
.Clear(m_array
, old_numints
, numints
- old_numints
);
194 int mask
= m_length
% 32;
196 m_array
[old_numints
- 1] &= (1 << mask
) - 1;
199 // set the internal state
205 public object SyncRoot
{
209 public object Clone ()
211 // LAMESPEC: docs say shallow, MS makes deep.
212 return new BitArray (this);
215 public void CopyTo (Array array
, int index
)
218 throw new ArgumentNullException ("array");
220 throw new ArgumentOutOfRangeException ("index");
223 throw new ArgumentException ("array", "Array rank must be 1");
225 if (index
>= array
.Length
&& m_length
> 0)
226 throw new ArgumentException ("index", "index is greater than array.Length");
228 // in each case, check to make sure enough space in array
230 if (array
is bool []) {
231 if (array
.Length
- index
< m_length
)
232 throw new ArgumentException ();
234 bool [] barray
= (bool []) array
;
236 // Copy the bits into the array
237 for (int i
= 0; i
< m_length
; i
++)
238 barray
[index
+ i
] = this [i
];
240 } else if (array
is byte []) {
241 int numbytes
= (m_length
+ 7) / 8;
243 if ((array
.Length
- index
) < numbytes
)
244 throw new ArgumentException ();
246 byte [] barray
= (byte []) array
;
247 // Copy the bytes into the array
248 for (int i
= 0; i
< numbytes
; i
++)
249 barray
[index
+ i
] = getByte (i
);
251 } else if (array
is int []) {
253 Array
.Copy (m_array
, 0, array
, index
, (m_length
+ 31) / 32);
256 throw new ArgumentException ("array", "Unsupported type");
260 public BitArray
Not ()
262 int ints
= (m_length
+ 31) / 32;
263 for (int i
= 0; i
< ints
; i
++)
264 m_array
[i
] = ~m_array
[i
];
270 public BitArray
And (BitArray
value)
272 checkOperand (value);
274 int ints
= (m_length
+ 31) / 32;
275 for (int i
= 0; i
< ints
; i
++)
276 m_array
[i
] &= value.m_array
[i
];
282 public BitArray
Or (BitArray
value)
284 checkOperand (value);
286 int ints
= (m_length
+ 31) / 32;
287 for (int i
= 0; i
< ints
; i
++)
288 m_array
[i
] |= value.m_array
[i
];
294 public BitArray
Xor (BitArray
value)
296 checkOperand (value);
298 int ints
= (m_length
+ 31) / 32;
299 for (int i
= 0; i
< ints
; i
++)
300 m_array
[i
] ^
= value.m_array
[i
];
306 public bool Get (int index
)
308 if (index
< 0 || index
>= m_length
)
309 throw new ArgumentOutOfRangeException ();
311 return (m_array
[index
>> 5] & (1 << (index
& 31))) != 0;
314 public void Set (int index
, bool value)
316 if (index
< 0 || index
>= m_length
)
317 throw new ArgumentOutOfRangeException ();
320 m_array
[index
>> 5] |= (1 << (index
& 31));
322 m_array
[index
>> 5] &= ~
(1 << (index
& 31));
327 public void SetAll (bool value)
330 for (int i
= 0; i
< m_array
.Length
; i
++)
334 Array
.Clear (m_array
, 0, m_array
.Length
);
339 public IEnumerator
GetEnumerator ()
341 return new BitArrayEnumerator (this);
345 class BitArrayEnumerator
: IEnumerator
, ICloneable
{
348 int _index
, _version
;
350 public object Clone () {
351 return MemberwiseClone ();
354 public BitArrayEnumerator (BitArray ba
)
358 _version
= ba
._version
;
361 public object Current
{
364 throw new InvalidOperationException ("Enum not started");
365 if (_index
>= _bitArray
.Count
)
366 throw new InvalidOperationException ("Enum Ended");
372 public bool MoveNext ()
376 if (_index
< (_bitArray
.Count
- 1)) {
377 _current
= _bitArray
[++_index
];
381 _index
= _bitArray
.Count
;
393 if (_version
!= _bitArray
._version
)
394 throw new InvalidOperationException ();