How to read SWF bit values?

37 Views Asked by At

I've a ByteArray for reading a Shockwave SWF file and need to read bit values for a TypeScript to SWF project which needs to read simple external SWFs for collecting ABCs. Here's what the SWF 19 spec says:

Bit values are variable-length bit fields that can represent three types of numbers:

  1. Unsigned integers
  2. Signed integers
  3. Signed 16.16 fixed-point values.

They're not variable-length integers; they're like fixed integers, but encoded in bits rather than bytes.

I've re-adapted a little function from a Node.js library, from another person, for my case, but I bet something is wrong. I was also thinking of rolling my own solution, but it looks confusing since a bit value can span into one or more bytes:

| byte   1 | byte 2   | byte 3   | byte 4   |
| bv1           | bv2     |  bv3      |
| 10000000 | 10010100 | 10000001 | 10000000 |

I'm not really after a clean solution right now, but here's what I got as I said:

class BitsReader {
    constructor(private bytes: ByteArray) {
        this.start();
    }

    public ub(length: number): number {
        return this.b(length, false);
    }

    public sb(length: number): number {
        return this.b(length, true);
    }

    public b(length: number, signed: boolean = false): number {
        let {current} = this;
        let n = 0, r = 0;
        let sign = signed && ++n && ((current >> (8 - this.bytes.position++)) & 1) ? -1 : 1;
        while (n++ < length) {
            if (this.bytes.position > 8) {
                this.start();
                ({current} = this);
            }
            r = (r << 1) + ((current >> (8 - this.bytes.position++)) & 1);
        }
        return sign * r;
    }

    private get current(): number {
        return this.bytes.at(this.bytes.position - 1);
    }

    private start() {
        assert(this.bytes.hasBytesAvailable, 'SWF is invalid.');
        this.bytes.position = 1;
    }
}

I've not played with this yet, but it looks wrong because it goes back to the beginning of the stream, which doesn't make sense, and also seems to not read the current byte correctly (just keeps advancing position without considering the next byte).

0

There are 0 best solutions below