aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--src/lstrlib.js38
-rw-r--r--tests/lstrlib.js43
3 files changed, 77 insertions, 6 deletions
diff --git a/README.md b/README.md
index 05daa08..617fd40 100644
--- a/README.md
+++ b/README.md
@@ -213,13 +213,13 @@
- [x] Math
- [x] utf8
- [ ] String
+ - [x] string.byte
- [x] string.char
- [x] string.len
- [x] string.lower
- [x] string.rep
- [x] string.reverse
- [x] string.upper
- - [ ] string.byte
- [ ] string.dump
- [ ] string.find
- [ ] string.format
diff --git a/src/lstrlib.js b/src/lstrlib.js
index 3db3e5e..376d379 100644
--- a/src/lstrlib.js
+++ b/src/lstrlib.js
@@ -6,6 +6,13 @@ const lua = require('./lua.js');
const lapi = require('./lapi.js');
const lauxlib = require('./lauxlib.js');
+/* translate a relative string position: negative means back from end */
+const posrelat = function(pos, len) {
+ if (pos >= 0) return pos;
+ else if (0 - pos > len) return 0;
+ else return len + pos + 1;
+};
+
const str_len = function(L) {
lapi.lua_pushinteger(L, lauxlib.luaL_checkstring(L, 1).length);
return 1;
@@ -47,13 +54,34 @@ const str_rep = function(L) {
return 1;
};
+const str_byte = function(L) {
+ let s = lauxlib.luaL_checkstring(L, 1);
+ s = L.stack[lapi.index2addr_(L, 1)].value;
+ let l = s.length;
+ let posi = posrelat(lauxlib.luaL_optinteger(L, 2, 1), l);
+ let pose = posrelat(lauxlib.luaL_optinteger(L, 3, posi), l);
+
+ if (posi < 1) posi = 1;
+ if (pose > l) pose = l;
+ if (posi > pose) return 0; /* empty interval; return no values */
+ if (pose - posi >= Number.MAX_SAFE_INTEGER) /* arithmetic overflow? */
+ return lauxlib.luaL_error(L, "string slice too long");
+
+ let n = (pose - posi) + 1;
+ lauxlib.luaL_checkstack(L, n, "string slice too long");
+ for (let i = 0; i < n; i++)
+ lapi.lua_pushinteger(L, s[posi + i - 1]);
+ return n;
+};
+
const strlib = {
- "char": str_char,
- "len": str_len,
- "lower": str_lower,
- "rep": str_rep,
+ "byte": str_byte,
+ "char": str_char,
+ "len": str_len,
+ "lower": str_lower,
+ "rep": str_rep,
"reverse": str_reverse,
- "upper": str_upper
+ "upper": str_upper
};
const createmetatable = function(L) {
diff --git a/tests/lstrlib.js b/tests/lstrlib.js
index d4e8493..b15eecf 100644
--- a/tests/lstrlib.js
+++ b/tests/lstrlib.js
@@ -177,4 +177,47 @@ test('string.reverse', function (t) {
"hello",
"Correct element(s) on the stack"
);
+});
+
+
+test('string.byte', function (t) {
+ let luaCode = `
+ return string.byte("hello", 2, 4)
+ `, L;
+
+ t.plan(5);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -3),
+ 101,
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -2),
+ 108,
+ "Correct element(s) on the stack"
+ );
+
+ t.strictEqual(
+ lapi.lua_tointeger(L, -1),
+ 108,
+ "Correct element(s) on the stack"
+ );
}); \ No newline at end of file