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.

BitSource.cs 4.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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> <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the
  20. /// number of bits read is not often a multiple of 8.</p>
  21. ///
  22. /// <p>This class is thread-safe but not reentrant. Unless the caller modifies the bytes array
  23. /// it passed in, in which case all bets are off.</p>
  24. ///
  25. /// </summary>
  26. /// <author> Sean Owen
  27. /// </author>
  28. /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
  29. /// </author>
  30. public sealed class BitSource
  31. {
  32. private readonly byte[] bytes;
  33. private int byteOffset;
  34. private int bitOffset;
  35. /// <param name="bytes">bytes from which this will read bits. Bits will be read from the first byte first.
  36. /// Bits are read within a byte from most-significant to least-significant bit.
  37. /// </param>
  38. public BitSource(byte[] bytes)
  39. {
  40. this.bytes = bytes;
  41. }
  42. /// <summary>
  43. /// index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.
  44. /// </summary>
  45. public int BitOffset
  46. {
  47. get { return bitOffset; }
  48. }
  49. /// <summary>
  50. /// index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.
  51. /// </summary>
  52. public int ByteOffset
  53. {
  54. get { return byteOffset; }
  55. }
  56. /// <param name="numBits">number of bits to read
  57. /// </param>
  58. /// <returns> int representing the bits read. The bits will appear as the least-significant
  59. /// bits of the int
  60. /// </returns>
  61. /// <exception cref="ArgumentException">if numBits isn't in [1,32] or more than is available</exception>
  62. public int readBits(int numBits)
  63. {
  64. if (numBits < 1 || numBits > 32 || numBits > available())
  65. {
  66. throw new ArgumentException(numBits.ToString(), "numBits");
  67. }
  68. int result = 0;
  69. // First, read remainder from current byte
  70. if (bitOffset > 0)
  71. {
  72. int bitsLeft = 8 - bitOffset;
  73. int toRead = numBits < bitsLeft ? numBits : bitsLeft;
  74. int bitsToNotRead = bitsLeft - toRead;
  75. int mask = (0xFF >> (8 - toRead)) << bitsToNotRead;
  76. result = (bytes[byteOffset] & mask) >> bitsToNotRead;
  77. numBits -= toRead;
  78. bitOffset += toRead;
  79. if (bitOffset == 8)
  80. {
  81. bitOffset = 0;
  82. byteOffset++;
  83. }
  84. }
  85. // Next read whole bytes
  86. if (numBits > 0)
  87. {
  88. while (numBits >= 8)
  89. {
  90. result = (result << 8) | (bytes[byteOffset] & 0xFF);
  91. byteOffset++;
  92. numBits -= 8;
  93. }
  94. // Finally read a partial byte
  95. if (numBits > 0)
  96. {
  97. int bitsToNotRead = 8 - numBits;
  98. int mask = (0xFF >> bitsToNotRead) << bitsToNotRead;
  99. result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);
  100. bitOffset += numBits;
  101. }
  102. }
  103. return result;
  104. }
  105. /// <returns> number of bits that can be read successfully
  106. /// </returns>
  107. public int available()
  108. {
  109. return 8 * (bytes.Length - byteOffset) - bitOffset;
  110. }
  111. }
  112. }