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.

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