SHOW:
|
|
- or go back to the newest paste.
| 1 | - | using System; |
| 1 | + | namespace Utils |
| 2 | - | using System.Collections.Generic; |
| 2 | + | |
| 3 | - | using System.Linq; |
| 3 | + | using System; |
| 4 | - | using System.Text; |
| 4 | + | using System.Collections; |
| 5 | - | using System.Globalization; |
| 5 | + | using System.Collections.Generic; |
| 6 | - | using System.Diagnostics; |
| 6 | + | using System.Linq; |
| 7 | using System.Text; | |
| 8 | - | namespace CryptoClass |
| 8 | + | using System.Globalization; |
| 9 | using System.Threading; | |
| 10 | - | public class BitArray |
| 10 | + | |
| 11 | /// <summary> | |
| 12 | - | private readonly bool[] bits; |
| 12 | + | /// A replacement for BitArray |
| 13 | - | public BitArray(IEnumerable<bool> bits) |
| 13 | + | /// </summary> |
| 14 | public class BoolArray : IEnumerable, ICollection, ICloneable | |
| 15 | - | this.bits = bits.ToArray(); |
| 15 | + | |
| 16 | private UInt32[] bits = null; | |
| 17 | - | public BitArray(int length) |
| 17 | + | private int _length = 0; |
| 18 | private static UInt32 ONE = (UInt32)1 << 31; | |
| 19 | - | this.bits = new bool[length]; |
| 19 | + | private object _syncRoot; |
| 20 | private static Func<byte[], byte[]> EndianFixer = null; | |
| 21 | ||
| 22 | - | public int Length { get { return bits.Length; } }
|
| 22 | + | #region Constructors |
| 23 | ||
| 24 | - | public static BitArray ParseHex(string hex) |
| 24 | + | static BoolArray() |
| 25 | {
| |
| 26 | - | if (hex == null) return null; // or do something else, throw, ... |
| 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 | - | BitArray ba = new BitArray(bits.ToArray()); |
| 37 | + | this.InitializeFrom(srcBits.ToArray()); |
| 38 | } | |
| 39 | ||
| 40 | - | public static BitArray FromBytes(IEnumerable<byte> bytes) |
| 40 | + | public BoolArray(ICollection<byte> srcBits) |
| 41 | {
| |
| 42 | - | List<bool> bits = new List<bool>(bytes.Count() * 8); |
| 42 | + | InitializeFrom(srcBits); |
| 43 | - | foreach (byte b in bytes) |
| 43 | + | |
| 44 | ||
| 45 | - | byte v = b; |
| 45 | + | public BoolArray(ICollection<short> srcBits) |
| 46 | - | for (int i = 7; i >= 0; i--) |
| 46 | + | |
| 47 | ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList(); | |
| 48 | - | bits.Add((v & (1 << i)) != 0); |
| 48 | + | InitializeFrom(bytes); |
| 49 | } | |
| 50 | ||
| 51 | - | return new BitArray(bits); |
| 51 | + | public BoolArray(ICollection<ushort> srcBits) |
| 52 | {
| |
| 53 | - | public static BitArray operator +(BitArray a, BitArray b) |
| 53 | + | ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList(); |
| 54 | InitializeFrom(bytes); | |
| 55 | - | return a.Append(b); |
| 55 | + | |
| 56 | ||
| 57 | - | public static BitArray FromByte(byte b) |
| 57 | + | public BoolArray(ICollection<int> srcBits) |
| 58 | {
| |
| 59 | - | return BitArray.FromBytes(new byte[] { b });
|
| 59 | + | ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList(); |
| 60 | InitializeFrom(bytes); | |
| 61 | - | public static BitArray FromString(string s, Encoding encoding = null) |
| 61 | + | |
| 62 | ||
| 63 | - | if (encoding == null) encoding = Encoding.ASCII; |
| 63 | + | public BoolArray(ICollection<uint> srcBits) |
| 64 | - | return BitArray.FromBytes(encoding.GetBytes(s)); |
| 64 | + | |
| 65 | ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList(); | |
| 66 | InitializeFrom(bytes); | |
| 67 | - | public BitArray Append(BitArray bits) |
| 67 | + | |
| 68 | ||
| 69 | - | List<bool> obits = new List<bool>(this.ToArray()); |
| 69 | + | public BoolArray(ICollection<long> srcBits) |
| 70 | - | obits.AddRange(bits.ToArray()); |
| 70 | + | |
| 71 | - | return new BitArray(obits.ToArray()); |
| 71 | + | ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList(); |
| 72 | InitializeFrom(bytes); | |
| 73 | - | public BitArray Repeat(int numReps) |
| 73 | + | |
| 74 | ||
| 75 | - | BitArray dv = new BitArray(0); |
| 75 | + | public BoolArray(ICollection<ulong> srcBits) |
| 76 | {
| |
| 77 | ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList(); | |
| 78 | InitializeFrom(bytes); | |
| 79 | - | public BitArray GetBits(int startBit, int numBits = -1) |
| 79 | + | |
| 80 | ||
| 81 | public BoolArray(int capacity, bool defaultValue = false) | |
| 82 | - | return new BitArray(bits.Skip(startBit).Take(numBits).ToArray()); |
| 82 | + | |
| 83 | this.bits = new UInt32[RequiredSize(capacity)]; | |
| 84 | - | public BitArray SetBits(int startBit, BitArray setBits) |
| 84 | + | this._length = capacity; |
| 85 | ||
| 86 | - | bool[] obits = bits.ToArray(); |
| 86 | + | // Only need to do this if true, because default for all bits is false |
| 87 | - | bool[] nbits = setBits.ToArray(); |
| 87 | + | if (defaultValue) for (int i = 0; i < this._length; i++) this[i] = true; |
| 88 | - | nbits.CopyTo(obits, startBit); |
| 88 | + | |
| 89 | - | return new BitArray(obits); |
| 89 | + | |
| 90 | private void InitializeFrom(ICollection<byte> srcBits) | |
| 91 | - | public BitArray Increment(int v = 1) |
| 91 | + | |
| 92 | this._length = srcBits.Count * 8; | |
| 93 | - | byte[] bytes = ToBytes(); |
| 93 | + | this.bits = new UInt32[RequiredSize(this._length)]; |
| 94 | - | for (int i = bytes.Length - 1; i >= 0; i--) |
| 94 | + | for (int i = 0; i < srcBits.Count; i++) |
| 95 | {
| |
| 96 | - | int nv = (int)bytes[i] + v; |
| 96 | + | uint bv = srcBits.Skip(i).Take(1).Single(); |
| 97 | - | bytes[i] = (byte)(nv % 256); |
| 97 | + | for (int b = 0; b < 8; b++) |
| 98 | - | if (nv < 256) break; |
| 98 | + | |
| 99 | - | v = nv - 256; |
| 99 | + | bool bitVal = ((bv << b) & 0x0080) != 0; |
| 100 | int bi = 8 * i + b; | |
| 101 | this[bi] = bitVal; | |
| 102 | - | return BitArray.FromBytes(bytes); |
| 102 | + | |
| 103 | } | |
| 104 | - | public BitArray Left(int numBits) |
| 104 | + | |
| 105 | ||
| 106 | - | return new BitArray(bits.Take(numBits)); |
| 106 | + | private void InitializeFrom(ICollection<bool> srcBits) |
| 107 | {
| |
| 108 | - | public BitArray Xor(BitArray xor, int start = 0) |
| 108 | + | this._length = srcBits.Count; |
| 109 | this.bits = new UInt32[RequiredSize(this._length)]; | |
| 110 | - | bool[] allbits = this.ToArray(); |
| 110 | + | |
| 111 | - | bool[] xorbits = xor.ToArray(); |
| 111 | + | int index = 0; |
| 112 | - | for (int i = 0; i < xorbits.Length; i++) |
| 112 | + | foreach (var b in srcBits) this[index++] = b; |
| 113 | } | |
| 114 | - | if (start + i >= allbits.Length) break; |
| 114 | + | |
| 115 | private static int RequiredSize(int bitCapacity) | |
| 116 | - | allbits[start + i] = allbits[start + i] ^ xorbits[i]; |
| 116 | + | |
| 117 | return (bitCapacity + 31) >> 5; | |
| 118 | - | return new BitArray(allbits); |
| 118 | + | |
| 119 | ||
| 120 | - | public List<BitArray> Split(int numBits) |
| 120 | + | #endregion |
| 121 | ||
| 122 | ||
| 123 | - | List<BitArray> bitSplits = new List<BitArray>(); |
| 123 | + | public bool this[int index] |
| 124 | - | while (i < bits.Length) |
| 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 | - | public string ToAsciiString() |
| 132 | + | |
| 133 | set | |
| 134 | - | return Encoding.ASCII.GetString(ToBytes()); |
| 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 | - | for (int i = 1; i <= bits.Length; i++) |
| 141 | + | |
| 142 | } | |
| 143 | - | b = (b << 1) | (bits[i-1] ? 1 : 0); |
| 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 | - | |
| 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 | - | int ebits = bits.Length % 4; |
| 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 | - | return ToHexString(" ", " | ");
|
| 170 | + | |
| 171 | get { return false; }
| |
| 172 | } | |
| 173 | ||
| 174 | public object SyncRoot | |
| 175 | - | BitArray ba = GetBits(startBit, numBits); |
| 175 | + | |
| 176 | - | int nb = (numBits / 8) + (((numBits % 8) > 0) ? 1 : 0); |
| 176 | + | get |
| 177 | {
| |
| 178 | - | for (int i = 0; i < ba.Length; i++) |
| 178 | + | if (this._syncRoot == null) Interlocked.CompareExchange<object>(ref this._syncRoot, new object(), null); |
| 179 | return _syncRoot; | |
| 180 | - | if (!bits[i]) continue; |
| 180 | + | |
| 181 | } | |
| 182 | #endregion | |
| 183 | #region ICloneable | |
| 184 | public object Clone() | |
| 185 | {
| |
| 186 | return new BoolArray(this.ToArray()); | |
| 187 | } | |
| 188 | - | return bits.ToArray(); |
| 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 | } |