From 52fa5f8a97fd5322fcb110298c4ce14328074818 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Sun, 12 Mar 2017 10:23:11 +0100 Subject: [Strings] lvm.js --- src/ldo.js | 2 +- src/lobject.js | 11 ++++++----- src/lundump.js | 35 +++++++++++++++++++++++++++-------- src/lvm.js | 43 ++++++++++++++++++++++++++++++------------- tests/tests.js | 3 +-- 5 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/ldo.js b/src/ldo.js index 6773278..cde2755 100644 --- a/src/ldo.js +++ b/src/ldo.js @@ -532,7 +532,7 @@ const f_parser = function(L, p) { let c = p.z.getc(); /* read first character */ if (String.fromCharCode(c) === lua.LUA_SIGNATURE.charAt(0)) { checkmode(L, p.mode, "binary"); - cl = new BytecodeParser(p.z.buffer).luaU_undump(L); + cl = new BytecodeParser(L, p.z.buffer); } else { checkmode(L, p.mode, "text"); cl = lparser.luaY_parser(L, p.z, p.buff, p.dyd, p.name, c); diff --git a/src/lobject.js b/src/lobject.js index 3d9edb0..92dd560 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -124,14 +124,15 @@ class Table extends TValue { static keyValue(key) { // Those lua values are used by value, others by reference - if (key instanceof TValue - && [CT.LUA_TNIL, + if (key instanceof TValue) { + if ([CT.LUA_TNIL, CT.LUA_TBOOLEAN, CT.LUA_TSTRING, - CT.LUA_TSHRSTR, - CT.LUA_TLNGSTR, CT.LUA_TNUMINT].indexOf(key.type) > -1) { - key = key.value; + key = key.value; + } else if ([CT.LUA_TSHRSTR, CT.LUA_TLNGSTR].indexOf(key.type) > -1) { + key = key.value.map(e => `${e}|`).join(''); + } } return key; diff --git a/src/lundump.js b/src/lundump.js index aa66584..d215c60 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -15,7 +15,8 @@ const LUAI_MAXSHORTLEN = 40; class BytecodeParser { - constructor(dataView) { + constructor(L, dataView) { + this.L = L; this.intSize = 4; this.size_tSize = 8; this.instructionSize = 4; @@ -69,7 +70,7 @@ class BytecodeParser { return number; } - readString(n) { + read8bitString(n) { let size = typeof n !== 'undefined' ? n : this.readByte() - 1; if (size === 0xFF) // TODO: test @@ -79,7 +80,7 @@ class BytecodeParser { return null; } - let string = new Uint8Array(); + let string = [];//new Uint8Array(); for (let i = 0; i < size; i++) string.push(this.readByte()); @@ -87,6 +88,24 @@ class BytecodeParser { return string; } + readString(n) { + let size = typeof n !== 'undefined' ? n : this.readByte() - 1; + + if (size === 0xFF) // TODO: test + this.offset += this.size_tSize; + + if (size === 0) { + return null; + } + + let string = ""; + + for (let i = 0; i < size; i++) + string += String.fromCharCode(this.readByte()); + + return string; + } + /* creates a mask with 'n' 1 bits at position 'p' */ static MASK1(n, p) { return ((~((~0)<<(n)))<<(p)); @@ -158,7 +177,7 @@ class BytecodeParser { break; case constant_types.LUA_TSHRSTR: case constant_types.LUA_TLNGSTR: - f.k.push(new TValue(constant_types.LUA_TLNGSTR, this.readString())); + f.k.push(this.L.l_G.intern(this.read8bitString())); break; default: throw new Error(`unrecognized constant '${t}'`); @@ -238,13 +257,13 @@ class BytecodeParser { } - luaU_undump(L) { + luaU_undump() { this.checkHeader(); - let cl = new LClosure(L, this.readByte()); + let cl = new LClosure(this.L, this.readByte()); - L.stack[L.top] = cl; - L.top++; + this.L.stack[this.L.top] = cl; + this.L.top++; cl.p = new Proto(); diff --git a/src/lvm.js b/src/lvm.js index 54d34e3..3cf3fb6 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -768,9 +768,22 @@ const luaV_equalobj = function(L, t1, t2) { case CT.LUA_TNUMFLT: case CT.LUA_TBOOLEAN: case CT.LUA_TLCF: - case CT.LUA_TSHRSTR: - case CT.LUA_TLNGSTR: return t1.value === t2.value ? 1 : 0; + case CT.LUA_TSHRSTR: + case CT.LUA_TLNGSTR: { + let l1 = t1.value.length; + let l2 = t2.value.length; + + if (l1 !== l2) return 0; + + let i; + for (i = 0; i < l1; i++) { + if (t1.value[i] !== t2.value[i]) + return 0; + } + + return 1; + } case CT.LUA_TLIGHTUSERDATA: case CT.LUA_TUSERDATA: case CT.LUA_TTABLE: @@ -843,7 +856,8 @@ const luaV_tointeger = function(obj, mode) { } else if (obj.ttisinteger()) { return obj.value|0; } else if (obj.ttisstring()) { - return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(obj.value)), mode); // TODO: luaO_str2num + let str = String.fromCharCode(...obj.value); + return luaV_tointeger(new TValue(CT.LUA_TNUMFLT, parseFloat(str)), mode); // TODO: luaO_str2num } return false; @@ -872,7 +886,7 @@ const LTnum = function(l, r) { } else { if (r.ttisfloat()) return l.value < r.value ? 1 : 0; - else if (isNan(l.value)) + else if (isNaN(l.value)) return 0; else return !LEintfloat(r.value, l.value); @@ -888,7 +902,7 @@ const LEnum = function(l, r) { } else { if (r.ttisfloat()) return l.value <= r.value ? 1 : 0; - else if (isNan(l.value)) + else if (isNaN(l.value)) return false; else return !LTintfloat(r.value, l.value); @@ -907,7 +921,9 @@ const LTintfloat = function(l, r) { const l_strcmp = function(ls, rs) { // TODO: lvm.c:248 static int l_strcmp (const TString *ls, const TString *rs) - return ls.value === rs.value ? 0 : (ls.value < rs.value ? -1 : 1); + ls = String.fromCharCode(...ls.value); + rs = String.fromCharCode(...rs.value); + return ls === rs ? 0 : (ls < rs ? -1 : 1); }; /* @@ -924,7 +940,7 @@ const luaV_objlen = function(L, ra, rb) { } case CT.LUA_TSHRSTR: case CT.LUA_TLNGSTR: - L.stack[ra] = new TValue(CT.LUA_TNUMINT, rb.value.length); // TODO: 8-byte clean string + L.stack[ra] = new TValue(CT.LUA_TNUMINT, rb.value.length); return; default: { tm = ltm.luaT_gettmbyobj(L, rb, ltm.TMS.TM_LEN); @@ -940,9 +956,10 @@ const luaV_objlen = function(L, ra, rb) { const tostring = function(L, i) { let o = L.stack[i]; let str = `${o.value}`; + str = lua.to_luastring(str, str.length); if (o.ttisstring() || (o.ttisnumber() && !isNaN(str))) { - L.stack[i] = new TValue(CT.LUA_TLNGSTR, str); + L.stack[i] = L.l_G.intern(str); return true; } @@ -964,7 +981,7 @@ const luaV_concat = function(L, total) { if (!(v.ttisstring() || v.ttisnumber()) || !tostring(L, top - 2)) // TODO: tostring ltm.luaT_trybinTM(L, v, v2, top-2, ltm.TMS.TM_CONCAT); else if (v2.ttisstring() && v2.value.length === 0) - tostring(L, top - 2) + tostring(L, top - 2); else if (v.ttisstring() && v.value.length === 0) L.stack[top - 2] = L.stack[top - 1]; else { @@ -977,12 +994,12 @@ const luaV_concat = function(L, total) { tl += l; } - let ts = new TValue(CT.LUA_TLNGSTR, ""); + let ts = []; for (let i = n; i > 0; i--) { - ts.value = `${ts.value}${L.stack[top - i].value}`; + ts = ts.concat(L.stack[top - i].value); } - L.stack[top - n] = ts; + L.stack[top - n] = L.l_G.intern(ts); } total -= n - 1; /* got 'n' strings to create 1 new */ L.top -= n - 1; /* popped 'n' strings and pushed one */ @@ -1074,7 +1091,7 @@ const luaV_finishset = function(L, t, key, val, slot, recur) { } settable(L, tm, key, val, recur + 1); -} +}; module.exports.LEintfloat = LEintfloat; diff --git a/tests/tests.js b/tests/tests.js index d4173c3..32f6563 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -35,8 +35,7 @@ const getState = function(luaCode) { let L = lauxlib.luaL_newstate(); - let p = new BytecodeParser(dv); - let cl = p.luaU_undump(L); + let p = new BytecodeParser(L, dv).luaU_undump(); return L; }; -- cgit v1.2.3-54-g00ecf