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.

483 lines
11 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package bits
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "math"
  7. mrand "math/rand"
  8. "regexp"
  9. "strings"
  10. "sync"
  11. tmmath "github.com/tendermint/tendermint/libs/math"
  12. tmrand "github.com/tendermint/tendermint/libs/rand"
  13. tmprotobits "github.com/tendermint/tendermint/proto/tendermint/libs/bits"
  14. )
  15. // BitArray is a thread-safe implementation of a bit array.
  16. type BitArray struct {
  17. mtx sync.Mutex
  18. Bits int `json:"bits"` // NOTE: persisted via reflect, must be exported
  19. Elems []uint64 `json:"elems"` // NOTE: persisted via reflect, must be exported
  20. }
  21. // NewBitArray returns a new bit array.
  22. // It returns nil if the number of bits is zero.
  23. func NewBitArray(bits int) *BitArray {
  24. // Reseed non-deterministically.
  25. tmrand.Reseed()
  26. if bits <= 0 {
  27. return nil
  28. }
  29. bA := &BitArray{}
  30. bA.reset(bits)
  31. return bA
  32. }
  33. // reset changes size of BitArray to `bits` and re-allocates (zeroed) data buffer
  34. func (bA *BitArray) reset(bits int) {
  35. bA.mtx.Lock()
  36. defer bA.mtx.Unlock()
  37. bA.Bits = bits
  38. if bits == 0 {
  39. bA.Elems = nil
  40. } else {
  41. bA.Elems = make([]uint64, numElems(bits))
  42. }
  43. }
  44. // Size returns the number of bits in the bitarray
  45. func (bA *BitArray) Size() int {
  46. if bA == nil {
  47. return 0
  48. }
  49. return bA.Bits
  50. }
  51. // GetIndex returns the bit at index i within the bit array.
  52. // The behavior is undefined if i >= bA.Bits
  53. func (bA *BitArray) GetIndex(i int) bool {
  54. if bA == nil {
  55. return false
  56. }
  57. bA.mtx.Lock()
  58. defer bA.mtx.Unlock()
  59. return bA.getIndex(i)
  60. }
  61. func (bA *BitArray) getIndex(i int) bool {
  62. if i >= bA.Bits {
  63. return false
  64. }
  65. return bA.Elems[i/64]&(uint64(1)<<uint(i%64)) > 0
  66. }
  67. // SetIndex sets the bit at index i within the bit array.
  68. // The behavior is undefined if i >= bA.Bits
  69. func (bA *BitArray) SetIndex(i int, v bool) bool {
  70. if bA == nil {
  71. return false
  72. }
  73. bA.mtx.Lock()
  74. defer bA.mtx.Unlock()
  75. return bA.setIndex(i, v)
  76. }
  77. func (bA *BitArray) setIndex(i int, v bool) bool {
  78. if i >= bA.Bits {
  79. return false
  80. }
  81. if v {
  82. bA.Elems[i/64] |= (uint64(1) << uint(i%64))
  83. } else {
  84. bA.Elems[i/64] &= ^(uint64(1) << uint(i%64))
  85. }
  86. return true
  87. }
  88. // Copy returns a copy of the provided bit array.
  89. func (bA *BitArray) Copy() *BitArray {
  90. if bA == nil {
  91. return nil
  92. }
  93. bA.mtx.Lock()
  94. defer bA.mtx.Unlock()
  95. return bA.copy()
  96. }
  97. func (bA *BitArray) copy() *BitArray {
  98. c := make([]uint64, len(bA.Elems))
  99. copy(c, bA.Elems)
  100. return &BitArray{
  101. Bits: bA.Bits,
  102. Elems: c,
  103. }
  104. }
  105. func (bA *BitArray) copyBits(bits int) *BitArray {
  106. c := make([]uint64, numElems(bits))
  107. copy(c, bA.Elems)
  108. return &BitArray{
  109. Bits: bits,
  110. Elems: c,
  111. }
  112. }
  113. // Or returns a bit array resulting from a bitwise OR of the two bit arrays.
  114. // If the two bit-arrys have different lengths, Or right-pads the smaller of the two bit-arrays with zeroes.
  115. // Thus the size of the return value is the maximum of the two provided bit arrays.
  116. func (bA *BitArray) Or(o *BitArray) *BitArray {
  117. if bA == nil && o == nil {
  118. return nil
  119. }
  120. if bA == nil && o != nil {
  121. return o.Copy()
  122. }
  123. if o == nil {
  124. return bA.Copy()
  125. }
  126. bA.mtx.Lock()
  127. o.mtx.Lock()
  128. c := bA.copyBits(tmmath.MaxInt(bA.Bits, o.Bits))
  129. smaller := tmmath.MinInt(len(bA.Elems), len(o.Elems))
  130. for i := 0; i < smaller; i++ {
  131. c.Elems[i] |= o.Elems[i]
  132. }
  133. bA.mtx.Unlock()
  134. o.mtx.Unlock()
  135. return c
  136. }
  137. // And returns a bit array resulting from a bitwise AND of the two bit arrays.
  138. // If the two bit-arrys have different lengths, this truncates the larger of the two bit-arrays from the right.
  139. // Thus the size of the return value is the minimum of the two provided bit arrays.
  140. func (bA *BitArray) And(o *BitArray) *BitArray {
  141. if bA == nil || o == nil {
  142. return nil
  143. }
  144. bA.mtx.Lock()
  145. o.mtx.Lock()
  146. defer func() {
  147. bA.mtx.Unlock()
  148. o.mtx.Unlock()
  149. }()
  150. return bA.and(o)
  151. }
  152. func (bA *BitArray) and(o *BitArray) *BitArray {
  153. c := bA.copyBits(tmmath.MinInt(bA.Bits, o.Bits))
  154. for i := 0; i < len(c.Elems); i++ {
  155. c.Elems[i] &= o.Elems[i]
  156. }
  157. return c
  158. }
  159. // Not returns a bit array resulting from a bitwise Not of the provided bit array.
  160. func (bA *BitArray) Not() *BitArray {
  161. if bA == nil {
  162. return nil // Degenerate
  163. }
  164. bA.mtx.Lock()
  165. defer bA.mtx.Unlock()
  166. return bA.not()
  167. }
  168. func (bA *BitArray) not() *BitArray {
  169. c := bA.copy()
  170. for i := 0; i < len(c.Elems); i++ {
  171. c.Elems[i] = ^c.Elems[i]
  172. }
  173. return c
  174. }
  175. // Sub subtracts the two bit-arrays bitwise, without carrying the bits.
  176. // Note that carryless subtraction of a - b is (a and not b).
  177. // The output is the same as bA, regardless of o's size.
  178. // If bA is longer than o, o is right padded with zeroes
  179. func (bA *BitArray) Sub(o *BitArray) *BitArray {
  180. if bA == nil || o == nil {
  181. // TODO: Decide if we should do 1's complement here?
  182. return nil
  183. }
  184. bA.mtx.Lock()
  185. o.mtx.Lock()
  186. // output is the same size as bA
  187. c := bA.copyBits(bA.Bits)
  188. // Only iterate to the minimum size between the two.
  189. // If o is longer, those bits are ignored.
  190. // If bA is longer, then skipping those iterations is equivalent
  191. // to right padding with 0's
  192. smaller := tmmath.MinInt(len(bA.Elems), len(o.Elems))
  193. for i := 0; i < smaller; i++ {
  194. // &^ is and not in golang
  195. c.Elems[i] &^= o.Elems[i]
  196. }
  197. bA.mtx.Unlock()
  198. o.mtx.Unlock()
  199. return c
  200. }
  201. // IsEmpty returns true iff all bits in the bit array are 0
  202. func (bA *BitArray) IsEmpty() bool {
  203. if bA == nil {
  204. return true // should this be opposite?
  205. }
  206. bA.mtx.Lock()
  207. defer bA.mtx.Unlock()
  208. for _, e := range bA.Elems {
  209. if e > 0 {
  210. return false
  211. }
  212. }
  213. return true
  214. }
  215. // IsFull returns true iff all bits in the bit array are 1.
  216. func (bA *BitArray) IsFull() bool {
  217. if bA == nil {
  218. return true
  219. }
  220. bA.mtx.Lock()
  221. defer bA.mtx.Unlock()
  222. // Check all elements except the last
  223. for _, elem := range bA.Elems[:len(bA.Elems)-1] {
  224. if (^elem) != 0 {
  225. return false
  226. }
  227. }
  228. // Check that the last element has (lastElemBits) 1's
  229. lastElemBits := (bA.Bits+63)%64 + 1
  230. lastElem := bA.Elems[len(bA.Elems)-1]
  231. return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
  232. }
  233. // PickRandom returns a random index for a set bit in the bit array.
  234. // If there is no such value, it returns 0, false.
  235. // It uses math/rand's global randomness Source to get this index.
  236. func (bA *BitArray) PickRandom() (int, bool) {
  237. if bA == nil {
  238. return 0, false
  239. }
  240. bA.mtx.Lock()
  241. trueIndices := bA.getTrueIndices()
  242. bA.mtx.Unlock()
  243. if len(trueIndices) == 0 { // no bits set to true
  244. return 0, false
  245. }
  246. // nolint:gosec // G404: Use of weak random number generator
  247. return trueIndices[mrand.Intn(len(trueIndices))], true
  248. }
  249. func (bA *BitArray) getTrueIndices() []int {
  250. trueIndices := make([]int, 0, bA.Bits)
  251. curBit := 0
  252. numElems := len(bA.Elems)
  253. // set all true indices
  254. for i := 0; i < numElems-1; i++ {
  255. elem := bA.Elems[i]
  256. if elem == 0 {
  257. curBit += 64
  258. continue
  259. }
  260. for j := 0; j < 64; j++ {
  261. if (elem & (uint64(1) << uint64(j))) > 0 {
  262. trueIndices = append(trueIndices, curBit)
  263. }
  264. curBit++
  265. }
  266. }
  267. // handle last element
  268. lastElem := bA.Elems[numElems-1]
  269. numFinalBits := bA.Bits - curBit
  270. for i := 0; i < numFinalBits; i++ {
  271. if (lastElem & (uint64(1) << uint64(i))) > 0 {
  272. trueIndices = append(trueIndices, curBit)
  273. }
  274. curBit++
  275. }
  276. return trueIndices
  277. }
  278. // String returns a string representation of BitArray: BA{<bit-string>},
  279. // where <bit-string> is a sequence of 'x' (1) and '_' (0).
  280. // The <bit-string> includes spaces and newlines to help people.
  281. // For a simple sequence of 'x' and '_' characters with no spaces or newlines,
  282. // see the MarshalJSON() method.
  283. // Example: "BA{_x_}" or "nil-BitArray" for nil.
  284. func (bA *BitArray) String() string {
  285. return bA.StringIndented("")
  286. }
  287. // StringIndented returns the same thing as String(), but applies the indent
  288. // at every 10th bit, and twice at every 50th bit.
  289. func (bA *BitArray) StringIndented(indent string) string {
  290. if bA == nil {
  291. return "nil-BitArray"
  292. }
  293. bA.mtx.Lock()
  294. defer bA.mtx.Unlock()
  295. return bA.stringIndented(indent)
  296. }
  297. func (bA *BitArray) stringIndented(indent string) string {
  298. lines := []string{}
  299. bits := ""
  300. for i := 0; i < bA.Bits; i++ {
  301. if bA.getIndex(i) {
  302. bits += "x"
  303. } else {
  304. bits += "_"
  305. }
  306. if i%100 == 99 {
  307. lines = append(lines, bits)
  308. bits = ""
  309. }
  310. if i%10 == 9 {
  311. bits += indent
  312. }
  313. if i%50 == 49 {
  314. bits += indent
  315. }
  316. }
  317. if len(bits) > 0 {
  318. lines = append(lines, bits)
  319. }
  320. return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
  321. }
  322. // Bytes returns the byte representation of the bits within the bitarray.
  323. func (bA *BitArray) Bytes() []byte {
  324. bA.mtx.Lock()
  325. defer bA.mtx.Unlock()
  326. numBytes := (bA.Bits + 7) / 8
  327. bytes := make([]byte, numBytes)
  328. for i := 0; i < len(bA.Elems); i++ {
  329. elemBytes := [8]byte{}
  330. binary.LittleEndian.PutUint64(elemBytes[:], bA.Elems[i])
  331. copy(bytes[i*8:], elemBytes[:])
  332. }
  333. return bytes
  334. }
  335. // Update sets the bA's bits to be that of the other bit array.
  336. // The copying begins from the begin of both bit arrays.
  337. func (bA *BitArray) Update(o *BitArray) {
  338. if bA == nil || o == nil {
  339. return
  340. }
  341. bA.mtx.Lock()
  342. o.mtx.Lock()
  343. copy(bA.Elems, o.Elems)
  344. o.mtx.Unlock()
  345. bA.mtx.Unlock()
  346. }
  347. // MarshalJSON implements json.Marshaler interface by marshaling bit array
  348. // using a custom format: a string of '-' or 'x' where 'x' denotes the 1 bit.
  349. func (bA *BitArray) MarshalJSON() ([]byte, error) {
  350. if bA == nil {
  351. return []byte("null"), nil
  352. }
  353. bA.mtx.Lock()
  354. defer bA.mtx.Unlock()
  355. bits := `"`
  356. for i := 0; i < bA.Bits; i++ {
  357. if bA.getIndex(i) {
  358. bits += `x`
  359. } else {
  360. bits += `_`
  361. }
  362. }
  363. bits += `"`
  364. return []byte(bits), nil
  365. }
  366. var bitArrayJSONRegexp = regexp.MustCompile(`\A"([_x]*)"\z`)
  367. // UnmarshalJSON implements json.Unmarshaler interface by unmarshaling a custom
  368. // JSON description.
  369. func (bA *BitArray) UnmarshalJSON(bz []byte) error {
  370. b := string(bz)
  371. if b == "null" {
  372. // This is required e.g. for encoding/json when decoding
  373. // into a pointer with pre-allocated BitArray.
  374. bA.reset(0)
  375. return nil
  376. }
  377. // Validate 'b'.
  378. match := bitArrayJSONRegexp.FindStringSubmatch(b)
  379. if match == nil {
  380. return fmt.Errorf("bitArray in JSON should be a string of format %q but got %s", bitArrayJSONRegexp.String(), b)
  381. }
  382. bits := match[1]
  383. numBits := len(bits)
  384. bA.reset(numBits)
  385. for i := 0; i < numBits; i++ {
  386. if bits[i] == 'x' {
  387. bA.SetIndex(i, true)
  388. }
  389. }
  390. return nil
  391. }
  392. // ToProto converts BitArray to protobuf. It returns nil if BitArray is
  393. // nil/empty.
  394. func (bA *BitArray) ToProto() *tmprotobits.BitArray {
  395. if bA == nil ||
  396. (len(bA.Elems) == 0 && bA.Bits == 0) { // empty
  397. return nil
  398. }
  399. bA.mtx.Lock()
  400. defer bA.mtx.Unlock()
  401. bc := bA.copy()
  402. return &tmprotobits.BitArray{Bits: int64(bc.Bits), Elems: bc.Elems}
  403. }
  404. // FromProto sets BitArray to the given protoBitArray. It returns an error if
  405. // protoBitArray is invalid.
  406. func (bA *BitArray) FromProto(protoBitArray *tmprotobits.BitArray) error {
  407. if protoBitArray == nil {
  408. return nil
  409. }
  410. // Validate protoBitArray.
  411. if protoBitArray.Bits < 0 {
  412. return errors.New("negative Bits")
  413. }
  414. // #[32bit]
  415. if protoBitArray.Bits > math.MaxInt32 { // prevent overflow on 32bit systems
  416. return errors.New("too many Bits")
  417. }
  418. if got, exp := len(protoBitArray.Elems), numElems(int(protoBitArray.Bits)); got != exp {
  419. return fmt.Errorf("invalid number of Elems: got %d, but exp %d", got, exp)
  420. }
  421. bA.mtx.Lock()
  422. defer bA.mtx.Unlock()
  423. ec := make([]uint64, len(protoBitArray.Elems))
  424. copy(ec, protoBitArray.Elems)
  425. bA.Bits = int(protoBitArray.Bits)
  426. bA.Elems = ec
  427. return nil
  428. }
  429. func numElems(bits int) int {
  430. return (bits + 63) / 64
  431. }