You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

BitArray.cs 8.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * Copyright 2007 ZXing authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using System;
  17. namespace ZXing.Common
  18. {
  19. /// <summary>
  20. /// A simple, fast array of bits, represented compactly by an array of ints internally.
  21. /// </summary>
  22. /// <author>Sean Owen</author>
  23. public sealed class BitArray
  24. {
  25. private int[] bits;
  26. private int size;
  27. public int Size
  28. {
  29. get
  30. {
  31. return size;
  32. }
  33. }
  34. public int SizeInBytes
  35. {
  36. get
  37. {
  38. return (size + 7) >> 3;
  39. }
  40. }
  41. public bool this[int i]
  42. {
  43. get
  44. {
  45. return (bits[i >> 5] & (1 << (i & 0x1F))) != 0;
  46. }
  47. set
  48. {
  49. if (value)
  50. bits[i >> 5] |= 1 << (i & 0x1F);
  51. }
  52. }
  53. public BitArray()
  54. {
  55. this.size = 0;
  56. this.bits = new int[1];
  57. }
  58. public BitArray(int size)
  59. {
  60. if (size < 1)
  61. {
  62. throw new ArgumentException("size must be at least 1");
  63. }
  64. this.size = size;
  65. this.bits = makeArray(size);
  66. }
  67. // For testing only
  68. private BitArray(int[] bits, int size)
  69. {
  70. this.bits = bits;
  71. this.size = size;
  72. }
  73. private void ensureCapacity(int size)
  74. {
  75. if (size > bits.Length << 5)
  76. {
  77. int[] newBits = makeArray(size);
  78. System.Array.Copy(bits, 0, newBits, 0, bits.Length);
  79. bits = newBits;
  80. }
  81. }
  82. private static int numberOfTrailingZeros(int num)
  83. {
  84. var index = (-num & num)%37;
  85. if (index < 0)
  86. index *= -1;
  87. return _lookup[index];
  88. }
  89. private static readonly int[] _lookup =
  90. {
  91. 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17,
  92. 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18
  93. };
  94. /// <summary> Sets a block of 32 bits, starting at bit i.
  95. ///
  96. /// </summary>
  97. /// <param name="i">first bit to set
  98. /// </param>
  99. /// <param name="newBits">the new value of the next 32 bits. Note again that the least-significant bit
  100. /// corresponds to bit i, the next-least-significant to i+1, and so on.
  101. /// </param>
  102. public void setBulk(int i, int newBits)
  103. {
  104. bits[i >> 5] = newBits;
  105. }
  106. /// <summary> Clears all bits (sets to false).</summary>
  107. public void clear()
  108. {
  109. int max = bits.Length;
  110. for (int i = 0; i < max; i++)
  111. {
  112. bits[i] = 0;
  113. }
  114. }
  115. /// <summary>
  116. /// Appends the bit.
  117. /// </summary>
  118. /// <param name="bit">The bit.</param>
  119. public void appendBit(bool bit)
  120. {
  121. ensureCapacity(size + 1);
  122. if (bit)
  123. {
  124. bits[size >> 5] |= 1 << (size & 0x1F);
  125. }
  126. size++;
  127. }
  128. /// <returns> underlying array of ints. The first element holds the first 32 bits, and the least
  129. /// significant bit is bit 0.
  130. /// </returns>
  131. public int[] Array
  132. {
  133. get { return bits; }
  134. }
  135. /// <summary>
  136. /// Appends the least-significant bits, from value, in order from most-significant to
  137. /// least-significant. For example, appending 6 bits from 0x000001E will append the bits
  138. /// 0, 1, 1, 1, 1, 0 in that order.
  139. /// </summary>
  140. /// <param name="value">The value.</param>
  141. /// <param name="numBits">The num bits.</param>
  142. public void appendBits(int value, int numBits)
  143. {
  144. if (numBits < 0 || numBits > 32)
  145. {
  146. throw new ArgumentException("Num bits must be between 0 and 32");
  147. }
  148. ensureCapacity(size + numBits);
  149. for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--)
  150. {
  151. appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1);
  152. }
  153. }
  154. public void appendBitArray(BitArray other)
  155. {
  156. int otherSize = other.size;
  157. ensureCapacity(size + otherSize);
  158. for (int i = 0; i < otherSize; i++)
  159. {
  160. appendBit(other[i]);
  161. }
  162. }
  163. public void xor(BitArray other)
  164. {
  165. if (bits.Length != other.bits.Length)
  166. {
  167. throw new ArgumentException("Sizes don't match");
  168. }
  169. for (int i = 0; i < bits.Length; i++)
  170. {
  171. // The last byte could be incomplete (i.e. not have 8 bits in
  172. // it) but there is no problem since 0 XOR 0 == 0.
  173. bits[i] ^= other.bits[i];
  174. }
  175. }
  176. /// <summary>
  177. /// Toes the bytes.
  178. /// </summary>
  179. /// <param name="bitOffset">first bit to start writing</param>
  180. /// <param name="array">array to write into. Bytes are written most-significant byte first. This is the opposite
  181. /// of the internal representation, which is exposed by BitArray</param>
  182. /// <param name="offset">position in array to start writing</param>
  183. /// <param name="numBytes">how many bytes to write</param>
  184. public void toBytes(int bitOffset, byte[] array, int offset, int numBytes)
  185. {
  186. for (int i = 0; i < numBytes; i++)
  187. {
  188. int theByte = 0;
  189. for (int j = 0; j < 8; j++)
  190. {
  191. if (this[bitOffset])
  192. {
  193. theByte |= 1 << (7 - j);
  194. }
  195. bitOffset++;
  196. }
  197. array[offset + i] = (byte)theByte;
  198. }
  199. }
  200. private static int[] makeArray(int size)
  201. {
  202. return new int[(size + 31) >> 5];
  203. }
  204. /// <summary>
  205. /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
  206. /// </summary>
  207. /// <param name="o">The <see cref="System.Object"/> to compare with this instance.</param>
  208. /// <returns>
  209. /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
  210. /// </returns>
  211. public override bool Equals(Object o)
  212. {
  213. var other = o as BitArray;
  214. if (other == null)
  215. return false;
  216. if (size != other.size)
  217. return false;
  218. for (var index = 0; index < size; index++)
  219. {
  220. if (bits[index] != other.bits[index])
  221. return false;
  222. }
  223. return true;
  224. }
  225. /// <summary>
  226. /// Returns a hash code for this instance.
  227. /// </summary>
  228. /// <returns>
  229. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
  230. /// </returns>
  231. public override int GetHashCode()
  232. {
  233. var hash = size;
  234. foreach (var bit in bits)
  235. {
  236. hash = 31 * hash + bit.GetHashCode();
  237. }
  238. return hash;
  239. }
  240. /// <summary>
  241. /// Erstellt ein neues Objekt, das eine Kopie der aktuellen Instanz darstellt.
  242. /// </summary>
  243. /// <returns>
  244. /// Ein neues Objekt, das eine Kopie dieser Instanz darstellt.
  245. /// </returns>
  246. public object Clone()
  247. {
  248. return new BitArray((int[])bits.Clone(), size);
  249. }
  250. }
  251. }