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

274 lines
5.9 KiB

  1. // go-qrcode
  2. // Copyright 2014 Tom Harwood
  3. // Package bitset implements an append only bit array.
  4. //
  5. // To create a Bitset and append some bits:
  6. // // Bitset Contents
  7. // b := bitset.New() // {}
  8. // b.AppendBools(true, true, false) // {1, 1, 0}
  9. // b.AppendBools(true) // {1, 1, 0, 1}
  10. // b.AppendValue(0x02, 4) // {1, 1, 0, 1, 0, 0, 1, 0}
  11. //
  12. // To read values:
  13. //
  14. // len := b.Len() // 8
  15. // v := b.At(0) // 1
  16. // v = b.At(1) // 1
  17. // v = b.At(2) // 0
  18. // v = b.At(8) // 0
  19. package bitset
  20. import (
  21. "bytes"
  22. "fmt"
  23. "log"
  24. )
  25. const (
  26. b0 = false
  27. b1 = true
  28. )
  29. // Bitset stores an array of bits.
  30. type Bitset struct {
  31. // The number of bits stored.
  32. numBits int
  33. // Storage for individual bits.
  34. bits []byte
  35. }
  36. // New returns an initialised Bitset with optional initial bits v.
  37. func New(v ...bool) *Bitset {
  38. b := &Bitset{numBits: 0, bits: make([]byte, 0)}
  39. b.AppendBools(v...)
  40. return b
  41. }
  42. // Clone returns a copy.
  43. func Clone(from *Bitset) *Bitset {
  44. return &Bitset{numBits: from.numBits, bits: from.bits[:]}
  45. }
  46. // Substr returns a substring, consisting of the bits from indexes start to end.
  47. func (b *Bitset) Substr(start int, end int) *Bitset {
  48. if start > end || end > b.numBits {
  49. log.Panicf("Out of range start=%d end=%d numBits=%d", start, end, b.numBits)
  50. }
  51. result := New()
  52. result.ensureCapacity(end - start)
  53. for i := start; i < end; i++ {
  54. if b.At(i) {
  55. result.bits[result.numBits/8] |= 0x80 >> uint(result.numBits%8)
  56. }
  57. result.numBits++
  58. }
  59. return result
  60. }
  61. // NewFromBase2String constructs and returns a Bitset from a string. The string
  62. // consists of '1', '0' or ' ' characters, e.g. "1010 0101". The '1' and '0'
  63. // characters represent true/false bits respectively, and ' ' characters are
  64. // ignored.
  65. //
  66. // The function panics if the input string contains other characters.
  67. func NewFromBase2String(b2string string) *Bitset {
  68. b := &Bitset{numBits: 0, bits: make([]byte, 0)}
  69. for _, c := range b2string {
  70. switch c {
  71. case '1':
  72. b.AppendBools(true)
  73. case '0':
  74. b.AppendBools(false)
  75. case ' ':
  76. default:
  77. log.Panicf("Invalid char %c in NewFromBase2String", c)
  78. }
  79. }
  80. return b
  81. }
  82. // AppendBytes appends a list of whole bytes.
  83. func (b *Bitset) AppendBytes(data []byte) {
  84. for _, d := range data {
  85. b.AppendByte(d, 8)
  86. }
  87. }
  88. // AppendByte appends the numBits least significant bits from value.
  89. func (b *Bitset) AppendByte(value byte, numBits int) {
  90. b.ensureCapacity(numBits)
  91. if numBits > 8 {
  92. log.Panicf("numBits %d out of range 0-8", numBits)
  93. }
  94. for i := numBits - 1; i >= 0; i-- {
  95. if value&(1<<uint(i)) != 0 {
  96. b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
  97. }
  98. b.numBits++
  99. }
  100. }
  101. // AppendUint32 appends the numBits least significant bits from value.
  102. func (b *Bitset) AppendUint32(value uint32, numBits int) {
  103. b.ensureCapacity(numBits)
  104. if numBits > 32 {
  105. log.Panicf("numBits %d out of range 0-32", numBits)
  106. }
  107. for i := numBits - 1; i >= 0; i-- {
  108. if value&(1<<uint(i)) != 0 {
  109. b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
  110. }
  111. b.numBits++
  112. }
  113. }
  114. // ensureCapacity ensures the Bitset can store an additional |numBits|.
  115. //
  116. // The underlying array is expanded if necessary. To prevent frequent
  117. // reallocation, expanding the underlying array at least doubles its capacity.
  118. func (b *Bitset) ensureCapacity(numBits int) {
  119. numBits += b.numBits
  120. newNumBytes := numBits / 8
  121. if numBits%8 != 0 {
  122. newNumBytes++
  123. }
  124. if len(b.bits) >= newNumBytes {
  125. return
  126. }
  127. b.bits = append(b.bits, make([]byte, newNumBytes+2*len(b.bits))...)
  128. }
  129. // Append bits copied from |other|.
  130. //
  131. // The new length is b.Len() + other.Len().
  132. func (b *Bitset) Append(other *Bitset) {
  133. b.ensureCapacity(other.numBits)
  134. for i := 0; i < other.numBits; i++ {
  135. if other.At(i) {
  136. b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
  137. }
  138. b.numBits++
  139. }
  140. }
  141. // AppendBools appends bits to the Bitset.
  142. func (b *Bitset) AppendBools(bits ...bool) {
  143. b.ensureCapacity(len(bits))
  144. for _, v := range bits {
  145. if v {
  146. b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
  147. }
  148. b.numBits++
  149. }
  150. }
  151. // AppendNumBools appends num bits of value value.
  152. func (b *Bitset) AppendNumBools(num int, value bool) {
  153. for i := 0; i < num; i++ {
  154. b.AppendBools(value)
  155. }
  156. }
  157. // String returns a human readable representation of the Bitset's contents.
  158. func (b *Bitset) String() string {
  159. var bitString string
  160. for i := 0; i < b.numBits; i++ {
  161. if (i % 8) == 0 {
  162. bitString += " "
  163. }
  164. if (b.bits[i/8] & (0x80 >> byte(i%8))) != 0 {
  165. bitString += "1"
  166. } else {
  167. bitString += "0"
  168. }
  169. }
  170. return fmt.Sprintf("numBits=%d, bits=%s", b.numBits, bitString)
  171. }
  172. // Len returns the length of the Bitset in bits.
  173. func (b *Bitset) Len() int {
  174. return b.numBits
  175. }
  176. // Bits returns the contents of the Bitset.
  177. func (b *Bitset) Bits() []bool {
  178. result := make([]bool, b.numBits)
  179. var i int
  180. for i = 0; i < b.numBits; i++ {
  181. result[i] = (b.bits[i/8] & (0x80 >> byte(i%8))) != 0
  182. }
  183. return result
  184. }
  185. // At returns the value of the bit at |index|.
  186. func (b *Bitset) At(index int) bool {
  187. if index >= b.numBits {
  188. log.Panicf("Index %d out of range", index)
  189. }
  190. return (b.bits[index/8] & (0x80 >> byte(index%8))) != 0
  191. }
  192. // Equals returns true if the Bitset equals other.
  193. func (b *Bitset) Equals(other *Bitset) bool {
  194. if b.numBits != other.numBits {
  195. return false
  196. }
  197. if !bytes.Equal(b.bits[0:b.numBits/8], other.bits[0:b.numBits/8]) {
  198. return false
  199. }
  200. for i := 8 * (b.numBits / 8); i < b.numBits; i++ {
  201. a := (b.bits[i/8] & (0x80 >> byte(i%8)))
  202. b := (other.bits[i/8] & (0x80 >> byte(i%8)))
  203. if a != b {
  204. return false
  205. }
  206. }
  207. return true
  208. }
  209. // ByteAt returns a byte consisting of upto 8 bits starting at index.
  210. func (b *Bitset) ByteAt(index int) byte {
  211. if index < 0 || index >= b.numBits {
  212. log.Panicf("Index %d out of range", index)
  213. }
  214. var result byte
  215. for i := index; i < index+8 && i < b.numBits; i++ {
  216. result <<= 1
  217. if b.At(i) {
  218. result |= 1
  219. }
  220. }
  221. return result
  222. }