Fix issues with expressions not completing

Moved NumberBaseConverter into its own file
This commit is contained in:
adelphes
2017-01-28 14:12:11 +00:00
parent 1b7fb3d60a
commit 6463558034
3 changed files with 93 additions and 88 deletions

View File

@@ -20,96 +20,10 @@ const xpath = require('xpath');
const { ADBClient } = require('./adbclient');
const { Debugger } = require('./debugger');
const $ = require('./jq-promise');
const NumberBaseConverter = require('./nbc');
const { D, isEmptyObject } = require('./util');
const ws_proxy = require('./wsproxy').proxy.Server(6037, 5037);
// arbitrary precision helper class for 64 bit numbers
const NumberBaseConverter = {
// Adds two arrays for the given base (10 or 16), returning the result.
add(x, y, base) {
var z = [], n = Math.max(x.length, y.length), carry = 0, i = 0;
while (i < n || carry) {
var xi = i < x.length ? x[i] : 0;
var yi = i < y.length ? y[i] : 0;
var zi = carry + xi + yi;
z.push(zi % base);
carry = Math.floor(zi / base);
i++;
}
return z;
},
// Returns a*x, where x is an array of decimal digits and a is an ordinary
// JavaScript number. base is the number base of the array x.
multiplyByNumber(num, x, base) {
if (num < 0) return null;
if (num == 0) return [];
var result = [], power = x;
for(;;) {
if (num & 1) {
result = this.add(result, power, base);
}
num = num >> 1;
if (num === 0) return result;
power = this.add(power, power, base);
}
},
twosComplement(str, base) {
const invdigits = str.split('').map(c => 15 - parseInt(c,base)).reverse();
const negdigits = this.add(invdigits, [1], base).slice(0,str.length);
return negdigits.reverse().map(d => d.toString(base)).join('');
},
convertBase(str, fromBase, toBase) {
if (fromBase === 10 && /[eE]/.test(str)) {
// convert exponents to a string of zeros
var s = str.split(/[eE]/);
str = s[0] + '0'.repeat(parseInt(s[1],10)); // works for 0/+ve exponent,-ve throws
}
var digits = str.split('').map(d => parseInt(d,fromBase)).reverse();
var outArray = [], power = [1];
for (var i = 0; i < digits.length; i++) {
if (digits[i]) {
outArray = this.add(outArray, this.multiplyByNumber(digits[i], power, toBase), toBase);
}
power = this.multiplyByNumber(fromBase, power, toBase);
}
return outArray.reverse().map(d => d.toString(toBase)).join('');
},
decToHex(decstr, minlen) {
var res, isneg = decstr[0] === '-';
if (isneg) decstr = decstr.slice(1)
decstr = decstr.match(/^0*(.+)$/)[1]; // strip leading zeros
if (decstr.length < 16 && !/[eE]/.test(decstr)) { // 16 = Math.pow(2,52).toString().length
// less than 52 bits - just use parseInt
res = parseInt(decstr, 10).toString(16);
} else {
res = NumberBaseConverter.convertBase(decstr, 10, 16);
}
if (isneg) {
res = NumberBaseConverter.twosComplement(res, 16);
if (/^[0-7]/.test(res)) res = 'f'+res; //msb must be set for -ve numbers
} else if (/^[^0-7]/.test(res))
res = '0' + res; // msb must not be set for +ve numbers
if (minlen && res.length < minlen) {
res = (isneg?'f':'0').repeat(minlen - res.length) + res;
}
return res;
},
hexToDec(hexstr, signed) {
var res, isneg = /^[^0-7]/.test(hexstr);
if (hexstr.match(/^0*(.+)$/)[1].length*4 < 52) {
// less than 52 bits - just use parseInt
res = parseInt(hexstr, 16);
if (signed && isneg) res = -res;
return res.toString(10);
}
if (isneg) {
hexstr = NumberBaseConverter.twosComplement(hexstr, 16);
}
res = (isneg ? '-' : '') + NumberBaseConverter.convertBase(hexstr, 16, 10);
return res;
},
};
// some commonly used Java types in debugger-compatible format
const JTYPES = {
byte: {name:'int',signature:'B'},
@@ -1440,7 +1354,7 @@ class AndroidDebugSession extends DebugSession {
local = { vtype:'literal',name:'',hasnullvalue:true,type:JTYPES.null,value:nullvalue,valid:true };
break;
case 'ident':
if (!locals) reject_evaluation(`Cannot find variable: ${expr.root_term}`);
if (!locals) return reject_evaluation(`Cannot find variable: ${expr.root_term}`);
local = locals.find(l => l.name === expr.root_term);
break;
case 'number':

View File

@@ -50,6 +50,8 @@ var Deferred = exports.Deferred = function(p, parent) {
var res = this.fn.apply(this.def._context,a);
if (res === undefined)
return a;
if (res && res._isdeferred)
return res._promise;
return res;
}.bind({def:faildef,fn:fn}));
faildef._promise = faildef._original = p;

89
src/nbc.js Normal file
View File

@@ -0,0 +1,89 @@
// arbitrary precision helper class for 64 bit numbers
const NumberBaseConverter = {
// Adds two arrays for the given base (10 or 16), returning the result.
add(x, y, base) {
var z = [], n = Math.max(x.length, y.length), carry = 0, i = 0;
while (i < n || carry) {
var xi = i < x.length ? x[i] : 0;
var yi = i < y.length ? y[i] : 0;
var zi = carry + xi + yi;
z.push(zi % base);
carry = Math.floor(zi / base);
i++;
}
return z;
},
// Returns a*x, where x is an array of decimal digits and a is an ordinary
// JavaScript number. base is the number base of the array x.
multiplyByNumber(num, x, base) {
if (num < 0) return null;
if (num == 0) return [];
var result = [], power = x;
for(;;) {
if (num & 1) {
result = this.add(result, power, base);
}
num = num >> 1;
if (num === 0) return result;
power = this.add(power, power, base);
}
},
twosComplement(str, base) {
const invdigits = str.split('').map(c => base - 1 - parseInt(c,base)).reverse();
const negdigits = this.add(invdigits, [1], base).slice(0,str.length);
return negdigits.reverse().map(d => d.toString(base)).join('');
},
convertBase(str, fromBase, toBase) {
if (fromBase === 10 && /[eE]/.test(str)) {
// convert exponents to a string of zeros
var s = str.split(/[eE]/);
str = s[0] + '0'.repeat(parseInt(s[1],10)); // works for 0/+ve exponent,-ve throws
}
var digits = str.split('').map(d => parseInt(d,fromBase)).reverse();
var outArray = [], power = [1];
for (var i = 0; i < digits.length; i++) {
if (digits[i]) {
outArray = this.add(outArray, this.multiplyByNumber(digits[i], power, toBase), toBase);
}
power = this.multiplyByNumber(fromBase, power, toBase);
}
return outArray.reverse().map(d => d.toString(toBase)).join('');
},
decToHex(decstr, minlen) {
var res, isneg = decstr[0] === '-';
if (isneg) decstr = decstr.slice(1)
decstr = decstr.match(/^0*(.+)$/)[1]; // strip leading zeros
if (decstr.length < 16 && !/[eE]/.test(decstr)) { // 16 = Math.pow(2,52).toString(10).length
// less than 52 bits - just use parseInt
res = parseInt(decstr, 10).toString(16);
} else {
res = NumberBaseConverter.convertBase(decstr, 10, 16);
}
if (isneg) {
res = NumberBaseConverter.twosComplement(res, 16);
if (/^[0-7]/.test(res)) res = 'f'+res; //msb must be set for -ve numbers
} else if (/^[^0-7]/.test(res))
res = '0' + res; // msb must not be set for +ve numbers
if (minlen && res.length < minlen) {
res = (isneg?'f':'0').repeat(minlen - res.length) + res;
}
return res;
},
hexToDec(hexstr, signed) {
var res, isneg = /^[^0-7]/.test(hexstr);
if (hexstr.match(/^0*(.+)$/)[1].length*4 < 52) {
// less than 52 bits - just use parseInt
res = parseInt(hexstr, 16);
if (signed && isneg) res = -res;
return res.toString(10);
}
if (isneg) {
hexstr = NumberBaseConverter.twosComplement(hexstr, 16);
}
res = (isneg ? '-' : '') + NumberBaseConverter.convertBase(hexstr, 16, 10);
return res;
},
};
Object.assign(exports, NumberBaseConverter);