Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add table.slice & table.countvalues #958

Merged
merged 2 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/ltablib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,10 +820,73 @@ static int tkeys (lua_State *L) {
}


static int tcountvalues (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);

lua_newtable(L);
lua_pushnil(L);
while (lua_next(L, 1)) { /* og, result, key */
if (!lua_isnoneornil(L, 4)) { /* if the value isn't nil */
lua_pushvalue(L, 4); /* push the key, prepare for result[value] */
lua_gettable(L, 2); /* push result[value] */
const lua_Integer i = luaL_optinteger(L, -1, 0) + 1; /* start or update count */
lua_pushvalue(L, 4); /* push the key again */
lua_pushinteger(L, i); /* push updated count */
lua_settable(L, 2); /* update result */
}

lua_settop(L, 3); /* reset stack to og, result, key */
}

return 1;
}


static int tslice (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);

lua_Integer idx_start = luaL_checkinteger(L, 2);
lua_Integer idx_end = luaL_checkinteger(L, 3);
const lua_Integer l = luaL_len(L, 1);

if (idx_start < 0) {
idx_start = l + idx_start + 1;
}

if (idx_end < 0) {
idx_end = l + idx_end + 1;
}
else if (idx_end > l) {
idx_end = l;
}

lua_newtable(L);
lua_Integer idx_result = 1;
for (lua_Integer i = idx_start; i <= idx_end; ++i) {
lua_pushinteger(L, i);
lua_gettable(L, 1);
if (!lua_isnoneornil(L, -1)) {
lua_pushinteger(L, idx_result++);
lua_pushvalue(L, -2);
lua_settable(L, 4);
}
else {
lua_pop(L, 1);
}
}

lua_settop(L, 4);

return 1;
}


/* }====================================================== */


static const luaL_Reg tab_funcs[] = {
{"slice", tslice},
{"countvalues", tcountvalues},
{"keys", tkeys},
{"modget", modget},
{"modset", modset},
Expand Down
71 changes: 71 additions & 0 deletions testes/pluto/basic.pluto
Original file line number Diff line number Diff line change
Expand Up @@ -1952,6 +1952,77 @@ do
assert(keys:contains("b"))
assert(keys:contains("c"))
end
do
local test_table_1 = {1, 2, 2, 3, 1}
local counts_1 = test_table_1:countvalues()
assert(counts_1[1] == 2)
assert(counts_1[2] == 2)
assert(counts_1[3] == 1)

local test_table_2 = {1, 2, nil, 3, 1, nil}
local counts_2 = test_table_2:countvalues()
assert(counts_2[1] == 2)
assert(counts_2[2] == 1)
assert(counts_2[3] == 1)

local test_table_3 = {1, 2, 3, 4, 5}
local counts_3 = test_table_3:countvalues()
assert(counts_3[1] == 1)
assert(counts_3[2] == 1)
assert(counts_3[3] == 1)
assert(counts_3[4] == 1)
assert(counts_3[5] == 1)

local test_table_4 = {1, "hello", 1, "world", "hello"}
local counts_4 = test_table_4:countvalues()
assert(counts_4[1] == 2)
assert(counts_4["hello"] == 2)
assert(counts_4["world"] == 1)

local test_table_5 = {}
local counts_5 = test_table_5:countvalues()
assert(next(counts_5) == nil)

local test_table_6 = {1, {2}, 1, {2}, 3}
local counts_6 = test_table_6:countvalues()
for key, value in counts_6 do
if type(key) == "table" then
assert(value == 1)
continue
elseif key == 1 then
assert(value == 2)
continue
elseif key == 3 then
assert(value == 1)
continue
end
error()
end

local test_table_7 = { 1, 2, 3, 2, 3, 3, 4, test_table_6, nil, test_table_6 }:countvalues()
assert(test_table_7[1] == 1)
assert(test_table_7[2] == 2)
assert(test_table_7[3] == 3)
assert(test_table_7[4] == 1)
assert(test_table_7[test_table_6] == 2)
end
do
local t = {1, 2, 3, 4, 5}

assert(table.slice(t, 1, 3)[1] == 1)
assert(table.slice(t, 1, 3)[2] == 2)
assert(table.slice(t, 1, 3)[3] == 3)
assert(#table.slice(t, 1, 3) == 3)

assert(table.slice(t, -3, -1)[1] == 3)
assert(table.slice(t, -3, -1)[2] == 4)
assert(table.slice(t, -3, -1)[3] == 5)
assert(#table.slice(t, -3, -1) == 3)

assert(#table.slice(t, 6, 10) == 0)
assert(#table.slice(t, 2, 10) == 4)
assert(#table.slice(t, 0, 10) == #t)
end
do
assert(compareversions("0.1.0", "0.1.0") == 0)
assert(compareversions("0.1.0", "0.2.0") ~= 0)
Expand Down