aboutsummaryrefslogtreecommitdiff
path: root/src/lobject.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lobject.js')
-rw-r--r--src/lobject.js133
1 files changed, 124 insertions, 9 deletions
diff --git a/src/lobject.js b/src/lobject.js
index 086af00..93e23c2 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -1,8 +1,11 @@
-/*jshint esversion: 6 */
+ /*jshint esversion: 6 */
"use strict";
-const CT = require('./lua.js').constant_types;
-const UpVal = require('./lfunc.js').UpVal;
+const assert = require('assert');
+
+const ljstype = require('./ljstype.js');
+const CT = require('./lua.js').constant_types;
+const UpVal = require('./lfunc.js').UpVal;
class TValue {
@@ -223,7 +226,7 @@ const luaO_chunkid = function(source, bufflen) {
let nli = source.indexOf('\n'); /* find first new line (if any) */
let nl = nli ? source.slice(nli) : null;
out = `${PRE}`; /* add prefix */
- bufflen -= PRE.length - RETS.length; - POS.length + 1; /* save space for prefix+suffix+'\0' */
+ bufflen -= PRE.length + RETS.length + POS.length + 1; /* save space for prefix+suffix+'\0' */
if (l < bufflen && nl === null) { /* small one-line source? */
out += `${source}`; /* keep it */
} else {
@@ -237,8 +240,120 @@ const luaO_chunkid = function(source, bufflen) {
return out;
};
-module.exports.LClosure = LClosure;
-module.exports.CClosure = CClosure;
-module.exports.TValue = TValue;
-module.exports.Table = Table;
-module.exports.luaO_chunkid = luaO_chunkid; \ No newline at end of file
+const luaO_hexavalue = function(c) {
+ if (ljstype.lisdigit(c)) return c.charCodeAt(0) - '0'.charCodeAt(0);
+ else return (c.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0)) + 10;
+};
+
+const UTF8BUFFSZ = 8;
+
+const luaO_utf8desc = function(buff, x) {
+ let n = 1; /* number of bytes put in buffer (backwards) */
+ assert(x <= 0x10FFFF);
+ if (x < 0x80) /* ascii? */
+ buff[UTF8BUFFSZ - 1] = String.fromCharCode(x);
+ else { /* need continuation bytes */
+ let mfb = 0x3f; /* maximum that fits in first byte */
+ do {
+ buff[UTF8BUFFSZ - (n++)] = String.fromCharCode(0x80 | (x & 0x3f));
+ x >>= 6; /* remove added bits */
+ mfb >>= 1; /* now there is one less bit available in first byte */
+ } while (x > mfb); /* still needs continuation byte? */
+ buff[UTF8BUFFSZ - n] = String.fromCharCode((~mfb << 1) | x); /* add first byte */
+ }
+ return n;
+};
+
+const l_str2dloc = function(s, result, mode) {
+ result[0] = mode === 'x' ? parseInt(s, '16') : parseInt(s);
+ if (isNaN(result[0])) return null; /* nothing recognized? */
+ while (ljstype.lisspace(result[0])) result[0] = result[0].slice(1); /* skip trailing spaces */
+ return result[0] === '\0' ? result : null; /* OK if no trailing characters */
+};
+
+const l_str2d = function(s) {
+ let result = [null, null];
+ let pidx = /[.xXnN]/g.exec(s).index;
+ let pmode = pidx ? s.slice(pidx) : null;
+ let mode = pmode ? pmode.toLowerCase() : 0;
+ if (mode === 'n') /* reject 'inf' and 'nan' */
+ return null;
+ let end = l_str2dloc(s, result, mode)[0]; /* try to convert */
+ if (end === null) { /* failed? may be a different locale */
+ throw new Error("Locale not available to handle number"); // TODO
+ }
+ return [end, result[1]];
+};
+
+const MAXBY10 = Number.MAX_SAFE_INTEGER / 10;
+const MAXLASTD = Number.MAX_SAFE_INTEGER % 10;
+
+const l_str2int = function(s) {
+ let result = [null, null];
+ let a = 0;
+ let empty = true;
+ let neg;
+
+ while (ljstype.lisspace(s.charAt(0))) s = s.slice(1); /* skip initial spaces */
+ neg = s.charAt(0) === '-';
+
+ if (neg || s.charAt(0) === '+')
+ s = s.slice(1);
+
+ if (s[0] === '0' && (s[1] === 'x' || s[1] === 'X')) { /* hex? */
+ s = s.slice(2); /* skip '0x' */
+
+ for (; ljstype.lisxdigit(s); s = s.slice(1)) {
+ a = a * 16 + luaO_hexavalue(s);
+ empty = false;
+ }
+ } else { /* decimal */
+ for (; ljstype.lisdigit(s); s = s.slice(1)) {
+ let d = parseInt(s.charAt(0));
+ if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
+ return null; /* do not accept it (as integer) */
+ a = a * 10 + d;
+ empty = false;
+ }
+ }
+
+ while (ljstype.lisspace(s.charAt(0))) s = s.slice(1); /* skip trailing spaces */
+
+ if (empty || s.charAt(0) !== "") return null; /* something wrong in the numeral */
+ else {
+ result[1] = neg ? -a : a;
+ result[0] = s;
+ return result;
+ }
+};
+
+const luaO_str2num = function(s) {
+ let s2i = l_str2int(s);
+ let e = s2i[0];
+ let i = s2i[1];
+
+ let o;
+ if (e !== null) /* try as an integer */
+ o = new TValue(CT.LUA_TNUMINT, i);
+ else { /* else try as a float */
+ s2i = l_str2d(s);
+ e = s2i[0];
+ i = s2i[1];
+
+ if (e !== null) {
+ o = new TValue(CT.LUA_TNUMFLT, i);
+ } else
+ return false; /* conversion failed */
+ return (e - s) + 1; // TODO: wrong
+ }
+};
+
+module.exports.CClosure = CClosure;
+module.exports.LClosure = LClosure;
+module.exports.TValue = TValue;
+module.exports.Table = Table;
+module.exports.UTF8BUFFSZ = UTF8BUFFSZ;
+module.exports.luaO_chunkid = luaO_chunkid;
+module.exports.luaO_hexavalue = luaO_hexavalue;
+module.exports.luaO_str2num = luaO_str2num;
+module.exports.luaO_utf8desc = luaO_utf8desc; \ No newline at end of file