首页 > 解决方案 > 您如何将这个 8 位位缓冲区实现调整为 32 位?

问题描述

我从GitHub得到这个。

function LittleEndianView(size) {
  Object.defineProperty(this, 'native', {
    value: new Uint8Array(size)
  })
}

LittleEndianView.prototype.get = function(bits, offset) {
  let available = (this.native.length * 8 - offset)

  if (bits > available) {
    throw new Error('Range error')
  }

  let value = 0
  let i = 0
  // why loop through like this?
  while (i < bits) {
    // remaining bits
    const remaining = bits - i
    const bitOffset = offset & 7
    const currentByte = this.native[offset >> 3]

    const read = Math.min(remaining, 8 - bitOffset)

    const a = 0xFF << read
    mask = ~a
    const b = currentByte >> bitOffset
    readBits = b & mask

    const c = readBits << i

    value = value | c
    offset += read
    i += read
  }

  return value >>> 0
}

LittleEndianView.prototype.set = function(bits, offset) {
  const available = (this.native.length * 8 - offset)

  if (bits > available) {
    throw new Error('Range error')
  }

  let i = 0
  while (i < bits) {
    const remaining = bits - i
    const bitOffset = offset & 7
    const byteOffset = offset >> 3
    const finished = Math.min(remaining, 8 - bitOffset)

    const mask = ~(0xFF << finished)
    const writeBits = value & mask
    const value >>= finished

    const destMask = ~(mask << bitOffset)
    const byte = this.view[byteOffset]

    this.native[byteOffset] = (byte & destMask) | (writeBits << bitOffset)

    offset += finished
    i += finished
  }
}

研究了几个小时后,我意识到offset & 7它只保留了偏移量的前 3 位,即 1 个字节。这offset >> 3只是将偏移量除以 8 以从位到字节。就是在0xFF << read左边得到一堆 1 like 11111000。然后否定它让他们在右边。我几乎理解其中的大部分内容。但我不明白他们是如何想出如何使用这些技术来实现这个解决方案的(而且我没有完全掌握整个解决方案——它是如何工作的或者为什么工作——在这几天之后)。

所以这让我想到了这个问题,我需要将同样的读/写功能应用于Uint32ArrayJavaScript 中的 a (而不是Uint8Array像上面的代码那样使用)。我需要在此读取和写入任意位(不是字节)Uint32Array。为了适应这种情况,现有算法get和算法需要进行哪些更改?set

似乎offset & 7可能会变得不同,但我不知道如何让它成为 32 位表示。并且offset >> 3可能会除以 32 或类似的东西。但我不确定。这可能主要是它。

标签: javascriptbit-manipulation

解决方案


推荐阅读