Advertisement
flmbray

BoolArray replacement for BitArray - not fully tested!

Dec 30th, 2012
302
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. namespace Utils
  2. {
  3.     using System;
  4.     using System.Collections;
  5.     using System.Collections.Generic;
  6.     using System.Linq;
  7.     using System.Text;
  8.     using System.Globalization;
  9.     using System.Threading;
  10.  
  11.     /// <summary>
  12.     /// A replacement for BitArray
  13.     /// </summary>
  14.     public class BoolArray : IEnumerable, ICollection,  ICloneable
  15.     {
  16.         private UInt32[] bits = null;
  17.         private int _length = 0;
  18.         private static UInt32 ONE = (UInt32)1 << 31;
  19.         private object _syncRoot;
  20.         private static Func<byte[], byte[]> EndianFixer = null;
  21.  
  22.         #region Constructors
  23.  
  24.         static BoolArray()
  25.         {
  26.             if (BitConverter.IsLittleEndian) EndianFixer = (a) => a.Reverse().ToArray();
  27.             else EndianFixer = (a) => a;
  28.         }
  29.  
  30.         public BoolArray(BoolArray srcBits)
  31.         {
  32.             this.InitializeFrom(srcBits.ToArray());
  33.         }
  34.  
  35.         public BoolArray(ICollection<bool> srcBits)
  36.         {
  37.             this.InitializeFrom(srcBits.ToArray());
  38.         }
  39.  
  40.         public BoolArray(ICollection<byte> srcBits)
  41.         {
  42.             InitializeFrom(srcBits);
  43.         }
  44.  
  45.         public BoolArray(ICollection<short> srcBits)
  46.         {
  47.             ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
  48.             InitializeFrom(bytes);
  49.         }
  50.  
  51.         public BoolArray(ICollection<ushort> srcBits)
  52.         {
  53.             ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
  54.             InitializeFrom(bytes);
  55.         }
  56.  
  57.         public BoolArray(ICollection<int> srcBits)
  58.         {
  59.             ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
  60.             InitializeFrom(bytes);
  61.         }
  62.  
  63.         public BoolArray(ICollection<uint> srcBits)
  64.         {
  65.             ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
  66.             InitializeFrom(bytes);
  67.         }
  68.  
  69.         public BoolArray(ICollection<long> srcBits)
  70.         {
  71.             ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
  72.             InitializeFrom(bytes);
  73.         }
  74.  
  75.         public BoolArray(ICollection<ulong> srcBits)
  76.         {
  77.             ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
  78.             InitializeFrom(bytes);
  79.         }
  80.  
  81.         public BoolArray(int capacity, bool defaultValue = false)
  82.         {
  83.             this.bits = new UInt32[RequiredSize(capacity)];
  84.             this._length = capacity;
  85.  
  86.             // Only need to do this if true, because default for all bits is false
  87.             if (defaultValue) for (int i = 0; i < this._length; i++) this[i] = true;
  88.         }
  89.  
  90.         private void InitializeFrom(ICollection<byte> srcBits)
  91.         {
  92.             this._length = srcBits.Count * 8;
  93.             this.bits = new UInt32[RequiredSize(this._length)];
  94.             for (int i = 0; i < srcBits.Count; i++)
  95.             {
  96.                 uint bv = srcBits.Skip(i).Take(1).Single();
  97.                 for (int b = 0; b < 8; b++)
  98.                 {
  99.                     bool bitVal = ((bv << b) & 0x0080) != 0;
  100.                     int bi = 8 * i + b;
  101.                     this[bi] = bitVal;
  102.                 }
  103.             }
  104.         }
  105.  
  106.         private void InitializeFrom(ICollection<bool> srcBits)
  107.         {
  108.             this._length = srcBits.Count;
  109.             this.bits = new UInt32[RequiredSize(this._length)];
  110.  
  111.             int index = 0;
  112.             foreach (var b in srcBits) this[index++] = b;
  113.         }
  114.  
  115.         private static int RequiredSize(int bitCapacity)
  116.         {
  117.             return (bitCapacity + 31) >> 5;
  118.         }
  119.  
  120.         #endregion
  121.  
  122.  
  123.         public bool this[int index]
  124.         {
  125.             get
  126.             {
  127.                 if (index >= _length) throw new IndexOutOfRangeException();
  128.  
  129.                 int byteIndex = index >> 5;
  130.                 int bitIndex = index & 0x1f;
  131.                 return ((bits[byteIndex] << bitIndex) & ONE) != 0;
  132.             }
  133.             set
  134.             {
  135.                 if (index >= _length) throw new IndexOutOfRangeException();
  136.  
  137.                 int byteIndex = index >> 5;
  138.                 int bitIndex = index & 0x1f;
  139.                 if (value) bits[byteIndex] |= (ONE >> bitIndex);
  140.                 else bits[byteIndex] &= ~(ONE >> bitIndex);
  141.             }
  142.         }
  143.  
  144.         #region IEnumerable
  145.         public IEnumerator GetEnumerator()
  146.         {
  147.             //for (int i = 0; i < _length; i++) yield return this[i];
  148.             return this.ToArray().GetEnumerator();
  149.         }
  150.         #endregion
  151.         #region ICollection
  152.         public void CopyTo(Array array, int index)
  153.         {
  154.             throw new NotImplementedException();
  155.  
  156.             if (array == null) throw new ArgumentNullException("array");
  157.             if (index < 0) throw new ArgumentOutOfRangeException("index");
  158.             if (array.Rank != 1) throw new ArgumentException("Multidimentional array not supported");
  159.             //if (array is UInt32[]) Array.Copy((Array)this.m_array, 0, array, index, BitArray.GetArrayLength(this.m_length, 32));
  160.             //else if (array is byte[])
  161.             //else if (array is bool[])
  162.         }
  163.  
  164.         public int Count
  165.         {
  166.             get { return this._length; }
  167.         }
  168.  
  169.         public bool IsSynchronized
  170.         {
  171.             get { return false; }
  172.         }
  173.  
  174.         public object SyncRoot
  175.         {
  176.             get
  177.             {
  178.                 if (this._syncRoot == null) Interlocked.CompareExchange<object>(ref this._syncRoot, new object(), null);
  179.                 return _syncRoot;
  180.             }
  181.         }
  182.         #endregion
  183.         #region ICloneable
  184.         public object Clone()
  185.         {
  186.             return new BoolArray(this.ToArray());
  187.         }
  188.         #endregion
  189.  
  190.         public bool[] ToArray()
  191.         {
  192.             bool[] vbits = new bool[this._length];
  193.             for (int i = 0; i < _length; i++) vbits[i] = this[i];
  194.             return vbits;
  195.         }
  196.  
  197.         public BoolArray Append(ICollection<bool> addBits)
  198.         {
  199.             int startPos = this._length;
  200.             Extend(addBits.Count);
  201.             bool[] bitArray = addBits.ToArray();
  202.             for (int i = 0; i < bitArray.Length; i++) this[i + startPos] = bitArray[i];
  203.             return this;
  204.         }
  205.  
  206.         public BoolArray Append(BoolArray addBits)
  207.         {
  208.             return this.Append(addBits.ToArray());
  209.         }
  210.  
  211.         public void Extend(int numBits)
  212.         {
  213.             numBits += this._length;
  214.             int reqBytes = RequiredSize(numBits);
  215.             if (reqBytes > this.bits.Length)
  216.             {
  217.                 UInt32[] newBits = new UInt32[reqBytes];
  218.                 this.bits.CopyTo(newBits, 0);
  219.                 this.bits = newBits;
  220.             }
  221.             this._length = numBits;
  222.         }
  223.  
  224.         public BoolArray Reverse()
  225.         {
  226.             this.InitializeFrom(this.ToArray().Reverse().ToList());
  227.             return this;
  228.         }
  229.  
  230.         public static BoolArray operator +(BoolArray a, BoolArray b)
  231.         {
  232.             return new BoolArray(a).Append(b);
  233.         }
  234.  
  235.         public static BoolArray FromHexString(string hex)
  236.         {
  237.             if (hex == null) throw new ArgumentNullException("hex");
  238.  
  239.             List<bool> bits = new List<bool>();
  240.             for (int i = 0; i < hex.Length; i++)
  241.             {
  242.                 int b = byte.Parse(hex[i].ToString(), NumberStyles.HexNumber);
  243.                 bits.Add((b >> 3) == 1);
  244.                 bits.Add(((b & 0x7) >> 2) == 1);
  245.                 bits.Add(((b & 0x3) >> 1) == 1);
  246.                 bits.Add((b & 0x1) == 1);
  247.             }
  248.             BoolArray ba = new BoolArray(bits.ToArray());
  249.             return ba;
  250.         }
  251.  
  252.         public static BoolArray FromBinaryString(string bin, char[] trueChars = null)
  253.         {
  254.             if (trueChars == null) trueChars = new char[] { '1', 'Y', 'y', 'T', 't' };
  255.             if (bin == null) throw new ArgumentNullException("bin");
  256.             BoolArray ba = new BoolArray(bin.Length);
  257.             for (int i = 0; i < bin.Length; i++) ba[i] = bin[i].In(trueChars);
  258.             return ba;
  259.         }
  260.  
  261.         public BoolArray Repeat(int numReps)
  262.         {
  263.             BoolArray dv = new BoolArray(0);
  264.             while (--numReps >= 0) dv = dv.Append(this);
  265.             return dv;
  266.         }
  267.  
  268.         public BoolArray GetBits(int startBit = 0, int numBits = -1)
  269.         {
  270.             if (numBits == -1) numBits = bits.Length;
  271.             return new BoolArray(this.ToArray().Skip(startBit).Take(numBits).ToArray());
  272.         }
  273.  
  274.         public BoolArray SetBits(int startBit, BoolArray setBits)
  275.         {
  276.             int diffSize = startBit + setBits.Count - this.Count;
  277.             if (diffSize > 0) Extend(diffSize);
  278.             for (int i = 0; i < setBits.Count; i++) this[startBit + i] = setBits[i];
  279.             return this;
  280.         }
  281.  
  282.         public List<BoolArray> SplitEvery(int numBits)
  283.         {
  284.             int i = 0;
  285.             List<BoolArray> bitSplits = new List<BoolArray>();
  286.             while (i < this.Count)
  287.             {
  288.                 bitSplits.Add(this.GetBits(i, numBits));
  289.                 i += numBits;
  290.             }
  291.             return bitSplits;
  292.         }
  293.  
  294.         #region Logical Bitwise Operations
  295.         public static BoolArray BinaryBitwiseOp(Func<bool, bool, bool> op, BoolArray left, BoolArray right, int start = 0)
  296.         {
  297.             bool[] leftbits = left.ToArray();
  298.             bool[] rightbits = right.ToArray();
  299.             for (int i = 0; i < rightbits.Length; i++)
  300.             {
  301.                 if (start + i >= leftbits.Length) break;
  302.                 leftbits[start + i] = op(leftbits[start + i], rightbits[i]);
  303.             }
  304.             return new BoolArray(leftbits);
  305.         }
  306.  
  307.         public BoolArray Xor(BoolArray xor, int start = 0)
  308.         {
  309.             return BinaryBitwiseOp((a, b) => (a ^ b), this, xor, start);
  310.         }
  311.  
  312.         public BoolArray And(BoolArray and, int start = 0)
  313.         {
  314.             return BinaryBitwiseOp((a, b) => (a & b), this, and, start);
  315.         }
  316.  
  317.         public BoolArray Or(BoolArray or, int start = 0)
  318.         {
  319.             return BinaryBitwiseOp((a, b) => (a | b), this, or, start);
  320.         }
  321.  
  322.         public BoolArray Not(int start = 0, int len = -1)
  323.         {
  324.             BoolArray b = (BoolArray)this.Clone();
  325.             for (int i = start; i < b.Count; i++)
  326.             {
  327.                 if (--len == -1) break;
  328.                 b[i] = !b[i];
  329.             }
  330.             return b;
  331.         }
  332.         #endregion
  333.  
  334.         public string ToHexString(string bitSep8 = null, string bitSep128 = null)
  335.         {
  336.             string s = string.Empty;
  337.             int b = 0;
  338.             bool[] bbits = this.ToArray();
  339.  
  340.             for (int i = 1; i <= bbits.Length; i++)
  341.             {
  342.                 b = (b << 1) | (bbits[i - 1] ? 1 : 0);
  343.                 if (i % 4 == 0)
  344.                 {
  345.                     s = s + string.Format("{0:x}", b);
  346.                     b = 0;
  347.                 }
  348.  
  349.                 if (i % (8 * 16) == 0)
  350.                 {
  351.                     s = s + bitSep128;
  352.                 }
  353.                 else if (i % 8 == 0)
  354.                 {
  355.                     s = s + bitSep8;
  356.                 }
  357.             }
  358.             int ebits = bbits.Length % 4;
  359.             if (ebits != 0)
  360.             {
  361.                 b = b << (4 - ebits);
  362.                 s = s + string.Format("{0:x}", b);
  363.             }
  364.             return s;
  365.         }
  366.  
  367.         public string ToBinaryString(char setChar = '1', char unsetChar = '0')
  368.         {
  369.             return new string(this.ToArray().Select(v => v ? setChar : unsetChar).ToArray());
  370.         }
  371.  
  372.         public byte[] ToBytes(int startBit = 0, int numBits = -1)
  373.         {
  374.             if (numBits == -1) numBits = bits.Length - startBit;
  375.             BoolArray ba = GetBits(startBit, numBits);
  376.             int nb = (numBits + 7) / 8;
  377.             byte[] bb = new byte[nb];
  378.             for (int i = 0; i < ba.Count; i++)
  379.             {
  380.                 if (!ba[i]) continue;
  381.                 int bp = 7 - (i % 8);
  382.                 bb[i / 8] = (byte)((int)bb[i / 8] | (1 << bp));
  383.             }
  384.             return bb;
  385.         }
  386.  
  387.         public override string ToString()
  388.         {
  389.             return ToHexString(" ", " ■ ");
  390.         }
  391.     }
  392.  
  393.     public static class Misc
  394.     {
  395.         public static bool In<T>(this T v, IEnumerable<T> vList) { return vList.Contains(v); }
  396.         public static bool In<T>(this T v, params T[] vList) { return vList.Contains(v); }
  397.         public static void Swap<T>(ref T rw, ref T rh)
  398.         {
  399.             T t = rw;
  400.             rw = rh;
  401.             rh = t;
  402.         }
  403.     }
  404. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement