struffer
Version:
Struct + Buffer = Struffer
199 lines • 5.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const os_1 = require("os");
var MemberEndianness;
(function (MemberEndianness) {
MemberEndianness[MemberEndianness["LittleEndian"] = 0] = "LittleEndian";
MemberEndianness[MemberEndianness["BigEndian"] = 1] = "BigEndian";
})(MemberEndianness = exports.MemberEndianness || (exports.MemberEndianness = {}));
var MemberSignature;
(function (MemberSignature) {
MemberSignature[MemberSignature["Signed"] = 0] = "Signed";
MemberSignature[MemberSignature["Unsigned"] = 1] = "Unsigned";
})(MemberSignature = exports.MemberSignature || (exports.MemberSignature = {}));
function totalBits(num) {
return num.toString(2).length;
}
exports.totalBits = totalBits;
function splitIntoBits(num, includeSign = false) {
const bitCount = totalBits(num);
let res = [];
if (num < 0) {
/*
* two's complement is how to represent negatives
* in binary. the following is true:
* -x = tc(x)
* x = tc(-x)
* normally two's complement is:
* tc(x) = ~x + 1
* but two's complement also works oppositely.
* i.e. the following yields the same results:
* tc(x) = ~(x - 1)
* so we'll use the second method since it's easier
* for us here. first, invert the number (e.g. -5 -> 5).
* then, subtract 1 (e.g. 5 -> 4). next, split it
* into bits (e.g. 4 -> [1, 0, 0]). finally, invert the
* bits (e.g. [1, 0, 0] -> [0, 1, 1]).
*/
res = splitIntoBits((num * -1) - 1, false).map(i => (i === 0) ? 1 : 0);
if (includeSign) {
res.unshift(1);
}
}
else {
for (let i = 0; i < bitCount; i++) {
res.unshift((num & (1 << i)) ? 1 : 0);
}
if (includeSign) {
res.unshift(0);
}
}
return res;
}
exports.splitIntoBits = splitIntoBits;
function unsignedSplit(n, bitCount = totalBits(n)) {
const bits = [];
for (let i = 0; i < bitCount; i++) {
bits.unshift((n & (1 << i)) ? 1 : 0);
}
return bits;
}
exports.unsignedSplit = unsignedSplit;
function joinBits(bits) {
let res = 0;
let j = bits.length - 1;
for (let i = 0; i < bits.length; i++) {
if (bits[i])
res |= 1 << j;
j--;
}
return res;
}
exports.joinBits = joinBits;
function joinSignedBits(_bits) {
let bits = _bits;
/*
* sign bit is always MSB (most significant bit)
* thus, first bit on LE, last bit on BE
*/
// we tell istanbul to ignore the tenary because endianness is hardware dependent
/* istanbul ignore next */
const negative = !!((os_1.endianness() === 'LE') ? bits.shift() : bits.pop());
let res = 0;
if (negative) {
bits = bits.map(i => (i === 0) ? 1 : 0);
}
let j = bits.length - 1;
for (let i = 0; i < bits.length; i++) {
if (bits[i])
res |= 1 << j;
j--;
}
if (negative) {
res = (res + 1) * -1;
}
return res;
}
exports.joinSignedBits = joinSignedBits;
function parseType(_type) {
let type = _type.toLowerCase();
const { BigEndian, LittleEndian } = MemberEndianness;
const { Signed, Unsigned } = MemberSignature;
const info = {
endianness: LittleEndian,
signature: Signed,
bitSize: 0,
};
const unwantedCharacter = /[^A-Za-z0-9]/;
const numberCharacter = /[0-9]/;
let signModifierFound = false;
let lookingForModifiers = true;
let shortsFound = 0;
let longsFound = 0;
const removeUnwantedCharacters = () => {
while (unwantedCharacter.test(type[0]))
type = type.slice(1);
};
const remove = (len) => { type = type.slice(len); };
const is = (str) => type.startsWith(str);
while (lookingForModifiers) {
removeUnwantedCharacters();
if (is('unsigned')) {
if (!signModifierFound) {
signModifierFound = true;
info.signature = Unsigned;
}
remove(8);
continue;
}
if (is('signed')) {
if (!signModifierFound) {
signModifierFound = true;
info.signature = Signed;
}
remove(6);
continue;
}
if (is('short')) {
shortsFound++;
remove(5);
continue;
}
if (is('long')) {
longsFound++;
remove(4);
continue;
}
lookingForModifiers = false;
}
removeUnwantedCharacters();
if (is('int')) {
info.bitSize = 32;
remove(3);
}
else if (is('uint')) {
if (!signModifierFound)
info.signature = Unsigned;
info.bitSize = 32;
remove(4);
}
else if (is('i')) {
info.bitSize = 32;
remove(1);
}
else if (is('u')) {
if (!signModifierFound)
info.signature = Unsigned;
info.bitSize = 32;
remove(1);
}
else if (is('byte') || is('char')) {
info.bitSize = 8;
remove(4);
}
removeUnwantedCharacters();
let sizePart = '';
while (numberCharacter.test(type[0])) {
sizePart += type[0];
type = type.slice(1).trim();
}
if (sizePart !== '') {
info.bitSize = Number(sizePart);
}
if (type.startsWith('be')) {
info.endianness = BigEndian;
}
const divide = (longsFound > shortsFound) ? false : true;
const times = (divide) ? (shortsFound - longsFound) : (longsFound - shortsFound);
for (let i = 0; i < times; i++) {
if (divide) {
info.bitSize = info.bitSize / 2;
}
else {
info.bitSize = info.bitSize * 2;
}
}
return info;
}
exports.parseType = parseType;
//# sourceMappingURL=common.js.map