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++)
117 #region Utility Methods
119 byte getByte (int byteIndex)
121 int index = byteIndex / 4;
122 int shift = (byteIndex % 4) * 8;
124 int theByte = m_array [index] & (0xff << shift);
126 return (byte)((theByte >> shift) & 0xff);
129 void setByte (int byteIndex, byte value)
131 int index = byteIndex / 4;
132 int shift = (byteIndex % 4) * 8;
135 m_array [index] &= ~(0xff << shift);
136 // or in the new byte
137 m_array [index] |= value << shift;
142 void checkOperand (BitArray operand)
145 throw new ArgumentNullException ();
146 if (operand.m_length != m_length)
147 throw new ArgumentException ();
152 get { return m_length; }
155 public bool IsReadOnly {
156 get { return false; }
159 public bool IsSynchronized {
160 get { return false; }
163 public bool this [int index] {
164 get { return Get (index); }
165 set { Set (index, value); }
169 get { return m_length; }
171 if (m_length == value)
175 throw new ArgumentOutOfRangeException ();
177 // Currently we never shrink the array
178 if (value > m_length) {
179 int numints = (value + 31) / 32;
180 int old_numints = (m_length + 31) / 32;
181 if (numints > m_array.Length) {
182 int [] newArr = new int [numints];
183 Array.Copy (m_array, newArr, m_array.Length);
186 Array.Clear(m_array, old_numints, numints - old_numints);
189 int mask = m_length % 32;
191 m_array [old_numints - 1] &= (1 << mask) - 1;
194 // set the internal state
200 public object SyncRoot {
204 public object Clone ()
206 // LAMESPEC: docs say shallow, MS makes deep.
207 return new BitArray (this);
210 public void CopyTo (Array array, int index)
213 throw new ArgumentNullException ("array");
215 throw new ArgumentOutOfRangeException ("index");
218 throw new ArgumentException ("array", "Array rank must be 1");
220 if (index >= array.Length && m_length > 0)
221 throw new ArgumentException ("index", "index is greater than array.Length");
223 // in each case, check to make sure enough space in array
225 if (array is bool []) {
226 if (array.Length - index < m_length)
227 throw new ArgumentException ();
229 bool [] barray = (bool []) array;
231 // Copy the bits into the array
232 for (int i = 0; i < m_length; i++)
233 barray[index + i] = this [i];
235 } else if (array is byte []) {
236 int numbytes = (m_length + 7) / 8;
238 if ((array.Length - index) < numbytes)
239 throw new ArgumentException ();
241 byte [] barray = (byte []) array;
242 // Copy the bytes into the array
243 for (int i = 0; i < numbytes; i++)
244 barray [index + i] = getByte (i);
246 } else if (array is int []) {
248 Array.Copy (m_array, 0, array, index, (m_length + 31) / 32);
251 throw new ArgumentException ("array", "Unsupported type");
255 public BitArray Not ()
257 int ints = (m_length + 31) / 32;
258 for (int i = 0; i < ints; i++)
259 m_array [i] = ~m_array [i];
265 public BitArray And (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 Or (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 BitArray Xor (BitArray value)
291 checkOperand (value);
293 int ints = (m_length + 31) / 32;
294 for (int i = 0; i < ints; i++)
295 m_array [i] ^= value.m_array [i];
301 public bool Get (int index)
303 if (index < 0 || index >= m_length)
304 throw new ArgumentOutOfRangeException ();
306 return (m_array [index >> 5] & (1 << (index & 31))) != 0;
309 public void Set (int index, bool value)
311 if (index < 0 || index >= m_length)
312 throw new ArgumentOutOfRangeException ();
315 m_array [index >> 5] |= (1 << (index & 31));
317 m_array [index >> 5] &= ~(1 << (index & 31));
322 public void SetAll (bool value)
325 for (int i = 0; i < m_array.Length; i++)
329 Array.Clear (m_array, 0, m_array.Length);
334 public IEnumerator GetEnumerator ()
336 return new BitArrayEnumerator (this);
340 class BitArrayEnumerator : IEnumerator, ICloneable {
343 int _index, _version;
345 public object Clone () {
346 return MemberwiseClone ();
349 public BitArrayEnumerator (BitArray ba)
353 _version = ba._version;
356 public object Current {
359 throw new InvalidOperationException ("Enum not started");
360 if (_index >= _bitArray.Count)
361 throw new InvalidOperationException ("Enum Ended");
367 public bool MoveNext ()
371 if (_index < (_bitArray.Count - 1)) {
372 _current = _bitArray [++_index];
376 _index = _bitArray.Count;
388 if (_version != _bitArray._version)
389 throw new InvalidOperationException ();