我正在尝试使用Node.JS读取二进制SWF文件。正如specification底部提到的the 17th page,有些整数使用可变长度位字段进行编码,根据定义,大多数整数都不是字节对齐的。
问题是Node.js的Buffer只提供读取字节对齐整数的函数。所以我试着写一个可以一点一点读取的包装器对象。然而,它似乎真的很hacky。下面是我写的对象原型:
/*jslint node:true, bitwise:true */
'use strict';
var util = require('util');
var maxBits = 32;
function BitBuffer() {
Buffer.apply(this, arguments);
this.cursor = 0;
this.bitCursor = 0;
}
util.inherits(BitBuffer, Buffer);
module.exports = BitBuffer;
function padBits(bits, length, bit) {
var leftPad = '', repeatLength, i;
bits = bits.toString(2);
length = length || 8;
bit = bit || '0';
if (bits.length >= length) {
return bits;
} else {
repeatLength = length - bits.length;
for (i = 0; i < repeatLength; i += 1) {
leftPad += bit;
}
return leftPad + bits;
}
}
BitBuffer.prototype.move = function (bits) {
var bytes = Math.floor((this.bitCursor + bits) / 8);
this.bitCursor += bits;
if (this.bitCursor > 8) {
this.cursor += bytes;
this.bitCursor -= bytes * 8;
}
if (this.cursor >= this.length) {
this.rewind();
return false;
}
return true;
};
BitBuffer.prototype.align = function () {
if (this.bitCursor > 0) {
this.bitCursor = 0;
this.cursor += 1;
}
};
BitBuffer.prototype.rewind = function () {
this.cursor = this.bitCursor = 0;
};
BitBuffer.prototype.readBits = function (bits) {
var bytes = Math.ceil((this.bitCursor + bits) / 8), result = 0,
length, buffer, i;
if (bits > maxBits) {
throw new RangeError('Cannot read more than ' + maxBits + ' bits');
}
buffer = this.slice(this.cursor, this.cursor + bytes);
result = padBits(buffer[0]).substr(this.bitCursor);
length = buffer.length;
for (i = 1; i < length; i += 1) {
result += padBits(buffer[i]);
}
result = result.substr(0, bits);
return (this.move(bits)) ? parseInt(result, 2) : false;
};
BitBuffer.prototype.readUB = BitBuffer.prototype.readBits;
BitBuffer.prototype.readSB = function (bits) {
var readBits = this.readBits(bits),
stringBits = readBits.toString(2);
if (readBits === false) {
return false;
}
// add automatically removed zeros
if (stringBits.length < bits) {
stringBits = padBits(stringBits, bits);
}
// negative, pad to 32 bits then invert bits
if (stringBits[0] === '1') {
return -~parseInt(padBits(stringBits, maxBits, '1'), 2) - 1;
} else {
return readBits;
}
};
BitBuffer.prototype.readFB = function (bits) {
var highBits, lowBits, result;
if (bits < 17) {
throw new RangeError('Should be at least 17 bits long');
}
highBits = this.readSB(bits - 16);
lowBits = this.readUB(16);
lowBits *= Math.pow(10, -lowBits.toString(10).length);
return (highBits >= 0) ?
highBits + lowBits : highBits - lowBits;
};
// wrap read functions
(function () {
var nativeReadFunctions = {
'readInt8': 8,
'readInt16LE': 16,
'readInt16BE': 16,
'readInt32LE': 32,
'readInt32BE': 32,
'readUInt8': 8,
'readUInt16LE': 16,
'readUInt16BE': 16,
'readUInt32LE': 32,
'readUInt32BE': 32,
'readDoubleLE': 64,
'readDoubleBE': 64,
'readFloatLE': 32,
'readFloatBE': 32
}, method;
function wrapNativeRead(method, length) {
return function (noAssert) {
var cursor;
this.align();
cursor = this.cursor;
this.move(length);
return Buffer.prototype[method].call(
this,
this.cursor,
noAssert
);
};
}
for (method in nativeReadFunctions) {
if (nativeReadFunctions.hasOwnProperty(method)) {
BitBuffer.prototype[method] =
wrapNativeRead(method, nativeReadFunctions[method]);
}
}
}());
写自己的对象是好方法吗?
答案 0 :(得分:0)
除了您的实施非常好,您应该了解在您的实施this.buffer === this
中,您应该更改以下行:
// inside BitBuffer prototype constructor
this.buffer = new Buffer(param1, param2);
// change to
Buffer.call(this, param1, param2); // The right way to call the super constructor
和
// inside BitBuffer.prototype.readBits
buffer = this.buffer.slice(this.cursor, this.cursor + bytes);
// change to
buffer = this.slice(this.cursor, this.cursor + bytes);