5 // Ben Maurer (bmaurer@users.sourceforge.net)
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Runtime.InteropServices;
36 namespace System.Collections {
41 public sealed class BitArray : ICollection, ICloneable {
47 public BitArray (BitArray bits)
50 throw new ArgumentNullException ("bits");
52 m_length = bits.m_length;
53 m_array = new int [(m_length + 31) / 32];
55 Array.Copy(bits.m_array, m_array, m_array.Length);
58 public BitArray (bool [] values)
61 throw new ArgumentNullException ("values");
63 m_length = values.Length;
64 m_array = new int [(m_length + 31) / 32];
66 for (int i = 0; i < values.Length; i++)
67 this [i] = values [i];
70 public BitArray (byte [] bytes)
73 throw new ArgumentNullException ("bytes");
75 m_length = bytes.Length * 8;
76 m_array = new int [(m_length + 31) / 32];
78 for (int i = 0; i < bytes.Length; i++)
79 setByte (i, bytes [i]);
82 public BitArray (int [] values)
85 throw new ArgumentNullException ("values");
87 int arrlen = values.Length;
89 m_array = new int [arrlen];
90 Array.Copy (values, m_array, arrlen);
93 public BitArray (int length)
96 throw new ArgumentOutOfRangeException ("length");
99 m_array = new int [(m_length + 31) / 32];
102 public BitArray (int length, bool defaultValue) : this (length)
105 for (int i = 0; i < m_array.Length; i++)
110 private BitArray (int [] array, int length)
116 #region Utility Methods
118 byte getByte (int byteIndex)
120 int index = byteIndex / 4;
121 int shift = (byteIndex % 4) * 8;
123 int theByte = m_array [index] & (0xff << shift);
125 return (byte)((theByte >> shift) & 0xff);
128 void setByte (int byteIndex, byte value)
130 int index = byteIndex / 4;
131 int shift = (byteIndex % 4) * 8;
134 m_array [index] &= ~(0xff << shift);
135 // or in the new byte
136 m_array [index] |= value << shift;
141 void checkOperand (BitArray operand)
144 throw new ArgumentNullException ();
145 if (operand.m_length != m_length)
146 throw new ArgumentException ();
151 get { return m_length; }
154 public bool IsReadOnly {
155 get { return false; }
158 public bool IsSynchronized {
159 get { return false; }
162 public bool this [int index] {
163 get { return Get (index); }
164 set { Set (index, value); }
168 get { return m_length; }
171 throw new ArgumentOutOfRangeException ();
174 if (m_length != newLen) {
175 int numints = (newLen + 31) / 32;
176 int [] newArr = new int [numints];
177 int copylen = (numints > m_array.Length) ? m_array.Length : numints;
178 Array.Copy (m_array, newArr, copylen);
180 // set the internal state
188 public object SyncRoot {
192 public object Clone ()
194 // LAMESPEC: docs say shallow, MS makes deep.
195 return new BitArray (this);
198 public void CopyTo (Array array, int index)
201 throw new ArgumentNullException ("array");
203 throw new ArgumentOutOfRangeException ("index");
206 throw new ArgumentException ("array", "Array rank must be 1");
208 if (index >= array.Length)
209 throw new ArgumentException ("index", "index is greater than array.Length");
211 // in each case, check to make sure enough space in array
213 if (array is bool []) {
214 if (array.Length - index < m_length)
215 throw new ArgumentException ();
217 bool [] barray = (bool []) array;
219 // Copy the bits into the array
220 for (int i = 0; i < m_length; i++)
221 barray[index + i] = this [i];
223 } else if (array is byte []) {
224 int numbytes = (m_length + 7) / 8;
226 if ((array.Length - index) < numbytes)
227 throw new ArgumentException ();
229 byte [] barray = (byte []) array;
230 // Copy the bytes into the array
231 for (int i = 0; i < numbytes; i++)
232 barray [index + i] = getByte (i);
234 } else if (array is int []) {
236 Array.Copy (m_array, 0, array, index, (m_length + 31) / 32);
239 throw new ArgumentException ("array", "Unsupported type");
243 public BitArray Not ()
245 int ints = (m_length + 31) / 32;
246 for (int i = 0; i < ints; i++)
247 m_array [i] = ~m_array [i];
253 public BitArray And (BitArray value)
255 checkOperand (value);
257 int ints = (m_length + 31) / 32;
258 for (int i = 0; i < ints; i++)
259 m_array [i] &= value.m_array [i];
265 public BitArray Or (BitArray value)
267 checkOperand (value);
269 int ints = (m_length + 31) / 32;
270 for (int i = 0; i < ints; i++)
271 m_array [i] |= value.m_array [i];
277 public BitArray Xor (BitArray value)
279 checkOperand (value);
281 int ints = (m_length + 31) / 32;
282 for (int i = 0; i < ints; i++)
283 m_array [i] ^= value.m_array [i];
289 public bool Get (int index)
291 if (index < 0 || index >= m_length)
292 throw new ArgumentOutOfRangeException ();
294 return (m_array [index / 32] & (1 << (index % 32))) != 0;
297 public void Set (int index, bool value)
299 if (index < 0 || index >= m_length)
300 throw new ArgumentOutOfRangeException ();
303 m_array [index / 32] |= (1 << (index % 32));
305 m_array [index / 32] &= ~(1 << (index % 32));
310 public void SetAll (bool value)
313 for (int i = 0; i < m_array.Length; i++)
317 Array.Clear (m_array, 0, m_array.Length);
322 public IEnumerator GetEnumerator ()
324 return new BitArrayEnumerator (this);
328 class BitArrayEnumerator : IEnumerator, ICloneable {
331 int _index, _max, _version;
333 public object Clone () {
334 return MemberwiseClone ();
337 public BitArrayEnumerator (BitArray ba)
342 _version = ba._version;
345 public object Current {
348 throw new InvalidOperationException ("Enum not started");
349 if (_index >= _bitArray.Count)
350 throw new InvalidOperationException ("Enum Ended");
356 public bool MoveNext ()
360 if (_index < (_bitArray.Count - 1)) {
361 _current = _bitArray [++_index];
365 _index = _bitArray.Count;
378 if (_version != _bitArray._version)
379 throw new InvalidOperationException ();