5 // Ben Maurer (bmaurer@users.sourceforge.net)
12 namespace System.Collections {
14 public sealed class BitArray : ICollection, ICloneable {
20 public BitArray (BitArray orig)
23 throw new ArgumentNullException ("orig");
25 _length = orig._length;
26 _array = new int [(_length + 31) / 32];
28 Array.Copy(orig._array, _array, _array.Length);
31 public BitArray (bool [] bits)
34 throw new ArgumentNullException ("bits");
36 _length = bits.Length;
37 _array = new int [(_length + 31) / 32];
39 for (int i = 0; i < bits.Length; i++)
43 public BitArray (byte [] bytes)
46 throw new ArgumentNullException ("bytes");
48 _length = bytes.Length * 8;
49 _array = new int [(_length + 31) / 32];
51 for (int i = 0; i < bytes.Length; i++)
52 setByte (i, bytes [i]);
55 public BitArray (int [] words)
58 throw new ArgumentNullException ("words");
60 int arrlen = words.Length;
62 _array = new int [arrlen];
63 Array.Copy (words, _array, arrlen);
66 public BitArray (int capacity)
69 throw new ArgumentOutOfRangeException ("capacity");
72 _array = new int [(_length + 31) / 32];
75 public BitArray (int capacity, bool value) : this (capacity)
78 for (int i = 0; i < _array.Length; i++)
83 private BitArray (int [] array, int length)
89 #region Utility Methods
91 byte getByte (int byteIndex)
93 int index = byteIndex / 4;
94 int shift = (byteIndex % 4) * 8;
96 int theByte = _array [index] & (0xff << shift);
98 return (byte)((theByte >> shift) & 0xff);
101 void setByte (int byteIndex, byte value)
103 int index = byteIndex / 4;
104 int shift = (byteIndex % 4) * 8;
107 _array [index] &= ~(0xff << shift);
108 // or in the new byte
109 _array [index] |= value << shift;
114 void checkOperand (BitArray operand)
117 throw new ArgumentNullException ();
118 if (operand._length != _length)
119 throw new ArgumentException ();
124 get { return _length; }
127 public bool IsReadOnly {
128 get { return false; }
131 public bool IsSynchronized {
132 get { return false; }
135 public bool this [int index] {
136 get { return Get (index); }
137 set { Set (index, value); }
141 get { return _length; }
144 throw new ArgumentOutOfRangeException ();
147 if (_length != newLen) {
148 int numints = (newLen + 31) / 32;
149 int [] newArr = new int [numints];
150 int copylen = (numints > _array.Length) ? _array.Length : numints;
151 Array.Copy (_array, newArr, copylen);
153 // set the internal state
161 public object SyncRoot {
165 public object Clone ()
167 // LAMESPEC: docs say shallow, MS makes deep.
168 return new BitArray (this);
171 public void CopyTo (Array array, int index)
174 throw new ArgumentNullException ("array");
176 throw new ArgumentOutOfRangeException ("index");
179 throw new ArgumentException ("array", "Array rank must be 1");
181 if (index >= array.Length)
182 throw new ArgumentException ("index", "index is greater than array.Length");
184 // in each case, check to make sure enough space in array
186 if (array is bool []) {
187 if (array.Length - index < _length)
188 throw new ArgumentException ();
190 bool [] barray = (bool []) array;
192 // Copy the bits into the array
193 for (int i = 0; i < _length; i++)
194 barray[index + i] = this [i];
196 } else if (array is byte []) {
197 int numbytes = (_length + 7) / 8;
199 if ((array.Length - index) < numbytes)
200 throw new ArgumentException ();
202 byte [] barray = (byte []) array;
203 // Copy the bytes into the array
204 for (int i = 0; i < numbytes; i++)
205 barray [index + i] = getByte (i);
207 } else if (array is int []) {
209 Array.Copy (_array, 0, array, index, (_length + 31) / 32);
212 throw new ArgumentException ("array", "Unsupported type");
216 public BitArray Not ()
218 int ints = (_length + 31) / 32;
219 for (int i = 0; i < ints; i++)
220 _array [i] = ~_array [i];
226 public BitArray And (BitArray operand)
228 checkOperand (operand);
230 int ints = (_length + 31) / 32;
231 for (int i = 0; i < ints; i++)
232 _array [i] &= operand._array [i];
238 public BitArray Or (BitArray operand)
240 checkOperand (operand);
242 int ints = (_length + 31) / 32;
243 for (int i = 0; i < ints; i++)
244 _array [i] |= operand._array [i];
250 public BitArray Xor (BitArray operand)
252 checkOperand (operand);
254 int ints = (_length + 31) / 32;
255 for (int i = 0; i < ints; i++)
256 _array [i] ^= operand._array [i];
262 public bool Get (int index)
264 if (index < 0 || index >= _length)
265 throw new ArgumentOutOfRangeException ();
267 return (_array [index / 32] & (1 << (index % 32))) != 0;
270 public void Set (int index, bool value)
272 if (index < 0 || index >= _length)
273 throw new ArgumentOutOfRangeException ();
276 _array [index / 32] |= (1 << (index % 32));
278 _array [index / 32] &= ~(1 << (index % 32));
283 public void SetAll (bool value)
286 for (int i = 0; i < _array.Length; i++)
290 Array.Clear (_array, 0, _array.Length);
295 public IEnumerator GetEnumerator ()
297 return new BitArrayEnumerator (this);
301 class BitArrayEnumerator : IEnumerator, ICloneable {
304 int _index, _max, _version;
306 public object Clone () {
307 return MemberwiseClone ();
310 public BitArrayEnumerator (BitArray ba)
315 _version = ba._version;
318 public object Current {
321 throw new InvalidOperationException ("Enum not started");
322 if (_index >= _bitArray.Count)
323 throw new InvalidOperationException ("Enum Ended");
329 public bool MoveNext ()
333 if (_index < (_bitArray.Count - 1)) {
334 _current = _bitArray [++_index];
338 _index = _bitArray.Count;
351 if (_version != _bitArray._version)
352 throw new InvalidOperationException ();