From eb9ad22e7538a25ef565e93c842eef48dba2469e Mon Sep 17 00:00:00 2001
From: Benoit Giannangeli <benoit.giannangeli@boursorama.fr>
Date: Wed, 22 Feb 2017 14:19:19 +0100
Subject: lua_rawlen, rawlen

---
 README.md         |  4 ++--
 src/lapi.js       | 16 ++++++++++++++++
 src/lbaselib.js   |  8 ++++++++
 tests/lbaselib.js | 34 ++++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 689d71c..7322f61 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,7 @@
     - [x] lua_rotate
     - [x] lua_insert
     - [x] lua_stringtonumber
+    - [x] lua_rawlen
     - [ ] lua_arith
     - [ ] lua_close
     - [ ] lua_compare
@@ -117,7 +118,6 @@
     - [ ] lua_pushthread
     - [ ] lua_pushvfstring
     - [ ] lua_rawgetp
-    - [ ] lua_rawlen
     - [ ] lua_rawseti
     - [ ] lua_rawsetp
     - [ ] lua_register
@@ -216,9 +216,9 @@
         - [x] select
         - [x] tonumber
         - [x] assert
+        - [x] rawlen
         - [ ] next
         - [ ] pairs
-        - [ ] rawlen
         - [ ] dofile
         - [ ] loadfile
         - [ ] load
diff --git a/src/lapi.js b/src/lapi.js
index 19e3090..76dee1b 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -464,6 +464,21 @@ const lua_tolstring = function(L, idx) {
 
 const lua_tostring =  lua_tolstring;
 
+const lua_rawlen = function(L, idx) {
+    let o = index2addr(L, idx);
+    switch (o.ttype()) {
+        case CT.LUA_TSHRSTR:
+        case CT.LUA_TLNGSTR:
+            return o.value.length;
+        case CT.LUA_TUSERDATA:
+            return o.len;
+        case CT.LUA_TTABLE:
+            return o.luaH_getn();
+        default:
+            return 0;
+    }
+};
+
 const lua_tointeger = function(L, idx) {
     return lvm.tointeger(index2addr(L, idx))
 };
@@ -694,6 +709,7 @@ module.exports.lua_absindex        = lua_absindex;
 module.exports.index2addr          = index2addr;
 module.exports.lua_rawget          = lua_rawget;
 module.exports.lua_rawset          = lua_rawset;
+module.exports.lua_rawlen          = lua_rawlen;
 module.exports.lua_isstring        = lua_isstring;
 module.exports.lua_rotate          = lua_rotate;
 module.exports.lua_remove          = lua_remove;
diff --git a/src/lbaselib.js b/src/lbaselib.js
index fa0349b..2eacaaf 100644
--- a/src/lbaselib.js
+++ b/src/lbaselib.js
@@ -65,6 +65,13 @@ const luaB_rawequal = function(L) {
     return 1;
 };
 
+const luaB_rawlen = function(L) {
+    let t = lapi.lua_type(L, 1);
+    lauxlib.luaL_argcheck(L, t === CT.LUA_TTABLE || t === CT.LUA_TSTRING, 1, "table or string expected");
+    lapi.lua_pushinteger(L, lapi.lua_rawlen(L, 1));
+    return 1;
+};
+
 const luaB_rawget = function(L) {
     lauxlib.luaL_checktype(L, 1, CT.LUA_TTABLE);
     lauxlib.luaL_checkany(L, 2);
@@ -241,6 +248,7 @@ const base_funcs = {
     "select":         luaB_select,
     "setmetatable":   luaB_setmetatable,
     "rawequal":       luaB_rawequal,
+    "rawlen":         luaB_rawlen,
     "rawset":         luaB_rawset,
     "rawget":         luaB_rawget,
     "type":           luaB_type,
diff --git a/tests/lbaselib.js b/tests/lbaselib.js
index a7b14d9..21d18aa 100644
--- a/tests/lbaselib.js
+++ b/tests/lbaselib.js
@@ -517,5 +517,39 @@ test('assert', function (t) {
         lapi.lua_tostring(L, -1).endsWith("this doesn't makes sense"),
         "Error is on the stack"
     );
+});
+
+
+test('rawlen', function (t) {
+    let luaCode = `
+        return rawlen({1, 2, 3}), rawlen('hello')
+    `, L;
+    
+    t.plan(3);
+
+    t.doesNotThrow(function () {
+
+        let bc = toByteCode(luaCode).dataView;
+
+        L = lauxlib.luaL_newstate();
+
+        linit.luaL_openlibs(L);
 
+        lapi.lua_load(L, bc, "test-rawlen");
+
+        lapi.lua_call(L, 0, -1);
+
+    }, "JS Lua program ran without error");
+
+    t.strictEqual(
+        lapi.lua_tonumber(L, -2),
+        3,
+        "Correct element(s) on the stack"
+    );
+
+    t.strictEqual(
+        lapi.lua_tonumber(L, -1),
+        5,
+        "Correct element(s) on the stack"
+    );
 });
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2