我正在查看规范,并且想知道如何将他们所说的内容转换为实际代码。这些integers和reals的编码方式(更多相关信息here)。
var encodings = {
// each encoding should return an array of 8-bit values.
number: function(value){
if (parseInt(value) !== value) return encodings.real(value)
if (integer >= -107 && integer <= 107) return encodings.integer1(value)
if (integer >= 108 && integer <= 1131) return encodings.integer2a(value)
if (integer >= -1131 && integer <= -108) return encodings.integer2b(value)
if (integer >= -32768 && integer <= 32767) return encodings.integer3(value)
return encodings.integer5(value)
},
// 1 32 to 246 -107 to +107 b0 – 139
// 0 8b
// 100 ef
// -100 27
integer1: function(integer){
},
// 2 247 to 250 +108 to +1131 (b0 – 247) * 256 + b1 + 108
integer2a: function(integer){
},
// 2 251 to 254 -1131 to -108 -(b0 – 251) * 256 – b1 – 108
integer2b: function(integer){
},
// 3 28 -32768 to +32767 b1 << 8 | b2
integer3: function(integer){
},
// 5 29 -(2^31) to +(2^31 – 1) b1 << 24 | b2 << 16 | b3 << 8 | b4
integer5: function(integer){
},
// 0 to 9 0 to 9
// a . (decimal point)
// b E
// c E–
// d <reserved>
// e – (minus)
// f end of number
real: function(real){
}
}
console.log(encodings.number(0))
console.log(encodings.number(100))
console.log(encodings.number(-100))
console.log(encodings.number(1000))
console.log(encodings.number(10000))
console.log(encodings.number(-10000))
console.log(encodings.number(100000))
console.log(encodings.number(-100000))
// 1000 fa 7c
// 10000 1c 27 10
// -10000 1c d8 f0
// 100000 1d 00 01 86 a0
// -100000 1d ff fe 79 60
在阅读规范后,我想像这样编码第一个:
integer1: function(integer){
return integer - 139
}
但是,根据他们的示例,这将导致错误的输出。所以我不太了解如何编码它们。想知道是否可以快速了解如何实现它们/如果实现不明显则实现的含义,或者实现是如何从规范中衍生出来的。
这是我用来计算编码值的实际代码的片段:
var api = {
type: {
NUMBER: {
make: function(v) {
if (v >= -107 && v <= 107) {
return [v - 139];
} else if (v >= 108 && v <= 1131) {
v = v - 108;
return [(v >> 8), v & 0xFF];
} else if (v >= -1131 && v <= -108) {
v = -v - 108;
return [(v >> 8), v & 0xFF];
} else if (v >= -32768 && v <= 32767) {
return api.type.NUMBER16.make(v);
} else {
return api.type.NUMBER32.make(v);
}
}
},
NUMBER16: {
make: function(v) {
return [28, (v >> 8) & 0xFF, v & 0xFF];
}
},
NUMBER32: {
make: function(v) {
return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
}
},
REAL: {
make: function(v) {
let value = v.toString();
// Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
// This code converts it back to a number without the epsilon.
var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
if (m) {
var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
value = (Math.round(v * epsilon) / epsilon).toString();
}
let nibbles = '';
for (let i = 0, ii = value.length; i < ii; i += 1) {
var c = value[i];
if (c === 'e') {
nibbles += value[++i] === '-' ? 'c' : 'b';
} else if (c === '.') {
nibbles += 'a';
} else if (c === '-') {
nibbles += 'e';
} else {
nibbles += c;
}
}
nibbles += (nibbles.length & 1) ? 'f' : 'ff';
var out = [30];
for (let i = 0, ii = nibbles.length; i < ii; i += 2) {
out.push(parseInt(nibbles.substr(i, 2), 16));
}
return out;
}
},
DICT: {
make: function(m) {
let d = [];
var keys = Object.keys(m);
var length = keys.length;
for (let i = 0; i < length; i += 1) {
// Object.keys() return string keys, but our keys are always numeric.
var k = keys[i]
var v = m[k];
var op = v.op
// Value comes before the key.
d = d.concat(api.type.OPERAND.make(v.value, v.type));
d = d.concat(api.type.OPERATOR.make(op));
}
return d;
}
},
OPERATOR: {
make: function(v) {
if (v < 1200) {
return [v];
} else {
return [12, v - 1200];
}
}
},
OPERAND: {
make: function(v, type) {
let d = [];
if (Array.isArray(type)) {
for (let i = 0; i < type.length; i += 1) {
d = d.concat(api.type.OPERAND.make(v[i], type[i]))
}
} else {
if (type === 'SID') {
d = d.concat(api.type.NUMBER.make(v))
} else if (type === 'offset') {
d = d.concat(api.type.NUMBER32.make(v))
} else if (type === 'number') {
d = d.concat(api.type.NUMBER.make(v))
} else if (type === 'real') {
d = d.concat(api.type.REAL.make(v))
} else if (type === 'DELTA') {
d = d.concat(api.type.DELTA.make(v))
} else {
throw new Error('Unknown operand type ' + type)
}
}
return d;
}
}
}
}
按照规范,我尝试将Number实现更改为看起来更合理,但输出值错误:
NUMBER: {
make: function(v) {
if (v >= -107 && v <= 107) {
return [v - 139];
} else if (v >= 108 && v <= 1131) {
// v = v - 108;
var b0 = v & 0xFF
var b1 = (v >> 8) & 0xFF
var v = (b0 - 247) * 256 + (b1 + 108)
return [(v >> 8), v & 0xFF];
} else if (v >= -1131 && v <= -108) {
// v = -v - 108;
var b0 = v & 0xFF
var b1 = (v >> 8) & 0xFF
v = -(b0 - 251) * 256 - b1 - 108
return [(v >> 8), v & 0xFF];
} else if (v >= -32768 && v <= 32767) {
return api.type.NUMBER16.make(v);
} else {
return api.type.NUMBER32.make(v);
}
}
},
NUMBER16: {
make: function(v) {
var b0 = v & 0xFF
var b1 = (v >> 8) & 0xFF
var b2 = (v >> 16) & 0xFF
v = b1 << 8 | b2
return [28, (v >> 8) & 0xFF, v & 0xFF];
}
},
NUMBER32: {
make: function(v) {
var b0 = v & 0xFF
var b1 = (v >> 8) & 0xFF
var b2 = (v >> 16) & 0xFF
var b3 = (v >> 24) & 0xFF
var b4 = (v >> 32) & 0xFF
v = b1 << 24 | b2 << 16 | b3 << 8 | b4
return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
}
}
所以我不确定如何实际计算值。如果事实证明我提供的示例代码中的原始形式是正确的,则您不介意解释如何从规范中获得有用的信息,因为我看不到连接。