index.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. var pager = require('memory-pager')
  2. module.exports = Bitfield
  3. function Bitfield (opts) {
  4. if (!(this instanceof Bitfield)) return new Bitfield(opts)
  5. if (!opts) opts = {}
  6. if (Buffer.isBuffer(opts)) opts = {buffer: opts}
  7. this.pageOffset = opts.pageOffset || 0
  8. this.pageSize = opts.pageSize || 1024
  9. this.pages = opts.pages || pager(this.pageSize)
  10. this.byteLength = this.pages.length * this.pageSize
  11. this.length = 8 * this.byteLength
  12. if (!powerOfTwo(this.pageSize)) throw new Error('The page size should be a power of two')
  13. this._trackUpdates = !!opts.trackUpdates
  14. this._pageMask = this.pageSize - 1
  15. if (opts.buffer) {
  16. for (var i = 0; i < opts.buffer.length; i += this.pageSize) {
  17. this.pages.set(i / this.pageSize, opts.buffer.slice(i, i + this.pageSize))
  18. }
  19. this.byteLength = opts.buffer.length
  20. this.length = 8 * this.byteLength
  21. }
  22. }
  23. Bitfield.prototype.get = function (i) {
  24. var o = i & 7
  25. var j = (i - o) / 8
  26. return !!(this.getByte(j) & (128 >> o))
  27. }
  28. Bitfield.prototype.getByte = function (i) {
  29. var o = i & this._pageMask
  30. var j = (i - o) / this.pageSize
  31. var page = this.pages.get(j, true)
  32. return page ? page.buffer[o + this.pageOffset] : 0
  33. }
  34. Bitfield.prototype.set = function (i, v) {
  35. var o = i & 7
  36. var j = (i - o) / 8
  37. var b = this.getByte(j)
  38. return this.setByte(j, v ? b | (128 >> o) : b & (255 ^ (128 >> o)))
  39. }
  40. Bitfield.prototype.toBuffer = function () {
  41. var all = alloc(this.pages.length * this.pageSize)
  42. for (var i = 0; i < this.pages.length; i++) {
  43. var next = this.pages.get(i, true)
  44. var allOffset = i * this.pageSize
  45. if (next) next.buffer.copy(all, allOffset, this.pageOffset, this.pageOffset + this.pageSize)
  46. }
  47. return all
  48. }
  49. Bitfield.prototype.setByte = function (i, b) {
  50. var o = i & this._pageMask
  51. var j = (i - o) / this.pageSize
  52. var page = this.pages.get(j, false)
  53. o += this.pageOffset
  54. if (page.buffer[o] === b) return false
  55. page.buffer[o] = b
  56. if (i >= this.byteLength) {
  57. this.byteLength = i + 1
  58. this.length = this.byteLength * 8
  59. }
  60. if (this._trackUpdates) this.pages.updated(page)
  61. return true
  62. }
  63. function alloc (n) {
  64. if (Buffer.alloc) return Buffer.alloc(n)
  65. var b = new Buffer(n)
  66. b.fill(0)
  67. return b
  68. }
  69. function powerOfTwo (x) {
  70. return !(x & (x - 1))
  71. }