mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-22 17:39:19 +00:00
Fix issues with expressions not completing
Moved NumberBaseConverter into its own file
This commit is contained in:
@@ -20,96 +20,10 @@ const xpath = require('xpath');
|
|||||||
const { ADBClient } = require('./adbclient');
|
const { ADBClient } = require('./adbclient');
|
||||||
const { Debugger } = require('./debugger');
|
const { Debugger } = require('./debugger');
|
||||||
const $ = require('./jq-promise');
|
const $ = require('./jq-promise');
|
||||||
|
const NumberBaseConverter = require('./nbc');
|
||||||
const { D, isEmptyObject } = require('./util');
|
const { D, isEmptyObject } = require('./util');
|
||||||
const ws_proxy = require('./wsproxy').proxy.Server(6037, 5037);
|
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
|
// some commonly used Java types in debugger-compatible format
|
||||||
const JTYPES = {
|
const JTYPES = {
|
||||||
byte: {name:'int',signature:'B'},
|
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 };
|
local = { vtype:'literal',name:'',hasnullvalue:true,type:JTYPES.null,value:nullvalue,valid:true };
|
||||||
break;
|
break;
|
||||||
case 'ident':
|
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);
|
local = locals.find(l => l.name === expr.root_term);
|
||||||
break;
|
break;
|
||||||
case 'number':
|
case 'number':
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ var Deferred = exports.Deferred = function(p, parent) {
|
|||||||
var res = this.fn.apply(this.def._context,a);
|
var res = this.fn.apply(this.def._context,a);
|
||||||
if (res === undefined)
|
if (res === undefined)
|
||||||
return a;
|
return a;
|
||||||
|
if (res && res._isdeferred)
|
||||||
|
return res._promise;
|
||||||
return res;
|
return res;
|
||||||
}.bind({def:faildef,fn:fn}));
|
}.bind({def:faildef,fn:fn}));
|
||||||
faildef._promise = faildef._original = p;
|
faildef._promise = faildef._original = p;
|
||||||
|
|||||||
89
src/nbc.js
Normal file
89
src/nbc.js
Normal 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);
|
||||||
Reference in New Issue
Block a user