View difference between Paste ID: mrjND8Wv and 11zFuSTc
SHOW: | | - or go back to the newest paste.
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
393+
	public static class Misc
394-
        {
394+
395-
                public static bool In<T>(this T v, IEnumerable<T> vList) { return vList.Contains(v); }
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); }
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)
397+
		public static void Swap<T>(ref T rw, ref T rh)
398-
                {
398+
399-
                        T t = rw;
399+
			T t = rw;
400-
                        rw = rh;
400+
			rw = rh;
401-
                        rh = t;
401+
			rh = t;
402-
                }
402+
403-
        }
403+
404
}