|
|
const FLOAT_EOF = 0xf;
|
|
|
const FLOAT_LOOKUP = [
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
|
'8', '9', '.', 'E', 'E-', null, '-'
|
|
|
];
|
|
|
|
|
|
const FLOAT_ENCODE_LOOKUP = {
|
|
|
'.': 10,
|
|
|
'E': 11,
|
|
|
'E-': 12,
|
|
|
'-': 14
|
|
|
};
|
|
|
|
|
|
export default class CFFOperand {
|
|
|
static decode(stream, value) {
|
|
|
if (32 <= value && value <= 246) {
|
|
|
return value - 139;
|
|
|
}
|
|
|
|
|
|
if (247 <= value && value <= 250) {
|
|
|
return (value - 247) * 256 + stream.readUInt8() + 108;
|
|
|
}
|
|
|
|
|
|
if (251 <= value && value <= 254) {
|
|
|
return -(value - 251) * 256 - stream.readUInt8() - 108;
|
|
|
}
|
|
|
|
|
|
if (value === 28) {
|
|
|
return stream.readInt16BE();
|
|
|
}
|
|
|
|
|
|
if (value === 29) {
|
|
|
return stream.readInt32BE();
|
|
|
}
|
|
|
|
|
|
if (value === 30) {
|
|
|
let str = '';
|
|
|
while (true) {
|
|
|
let b = stream.readUInt8();
|
|
|
|
|
|
let n1 = b >> 4;
|
|
|
if (n1 === FLOAT_EOF) { break; }
|
|
|
str += FLOAT_LOOKUP[n1];
|
|
|
|
|
|
let n2 = b & 15;
|
|
|
if (n2 === FLOAT_EOF) { break; }
|
|
|
str += FLOAT_LOOKUP[n2];
|
|
|
}
|
|
|
|
|
|
return parseFloat(str);
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
static size(value) {
|
|
|
// if the value needs to be forced to the largest size (32 bit)
|
|
|
// e.g. for unknown pointers, set to 32768
|
|
|
if (value.forceLarge) {
|
|
|
value = 32768;
|
|
|
}
|
|
|
|
|
|
if ((value | 0) !== value) { // floating point
|
|
|
let str = '' + value;
|
|
|
return 1 + Math.ceil((str.length + 1) / 2);
|
|
|
|
|
|
} else if (-107 <= value && value <= 107) {
|
|
|
return 1;
|
|
|
|
|
|
} else if (108 <= value && value <= 1131 || -1131 <= value && value <= -108) {
|
|
|
return 2;
|
|
|
|
|
|
} else if (-32768 <= value && value <= 32767) {
|
|
|
return 3;
|
|
|
|
|
|
} else {
|
|
|
return 5;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static encode(stream, value) {
|
|
|
// if the value needs to be forced to the largest size (32 bit)
|
|
|
// e.g. for unknown pointers, save the old value and set to 32768
|
|
|
let val = Number(value);
|
|
|
|
|
|
if (value.forceLarge) {
|
|
|
stream.writeUInt8(29);
|
|
|
return stream.writeInt32BE(val);
|
|
|
|
|
|
} else if ((val | 0) !== val) { // floating point
|
|
|
stream.writeUInt8(30);
|
|
|
|
|
|
let str = '' + val;
|
|
|
for (let i = 0; i < str.length; i += 2) {
|
|
|
let c1 = str[i];
|
|
|
let n1 = FLOAT_ENCODE_LOOKUP[c1] || +c1;
|
|
|
|
|
|
if (i === str.length - 1) {
|
|
|
var n2 = FLOAT_EOF;
|
|
|
} else {
|
|
|
let c2 = str[i + 1];
|
|
|
var n2 = FLOAT_ENCODE_LOOKUP[c2] || +c2;
|
|
|
}
|
|
|
|
|
|
stream.writeUInt8((n1 << 4) | (n2 & 15));
|
|
|
}
|
|
|
|
|
|
if (n2 !== FLOAT_EOF) {
|
|
|
return stream.writeUInt8((FLOAT_EOF << 4));
|
|
|
}
|
|
|
|
|
|
} else if (-107 <= val && val <= 107) {
|
|
|
return stream.writeUInt8(val + 139);
|
|
|
|
|
|
} else if (108 <= val && val <= 1131) {
|
|
|
val -= 108;
|
|
|
stream.writeUInt8((val >> 8) + 247);
|
|
|
return stream.writeUInt8(val & 0xff);
|
|
|
|
|
|
} else if (-1131 <= val && val <= -108) {
|
|
|
val = -val - 108;
|
|
|
stream.writeUInt8((val >> 8) + 251);
|
|
|
return stream.writeUInt8(val & 0xff);
|
|
|
|
|
|
} else if (-32768 <= val && val <= 32767) {
|
|
|
stream.writeUInt8(28);
|
|
|
return stream.writeInt16BE(val);
|
|
|
|
|
|
} else {
|
|
|
stream.writeUInt8(29);
|
|
|
return stream.writeInt32BE(val);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|