lmttablibext.c /size: 2800 b    last modification: 2025-02-21 11:03
1/*
2    See license.txt in the root of this project.
3*/
4
5# include "luametatex.h"
6
7static int tablib_keys(lua_State *L)
8{
9    int category = 0; // 0=unknown 1=string 2=number 3=mixed
10    lua_settop(L, 1);
11    lua_createtable(L, 0, 0);
12    if (lua_type(L, 1) == LUA_TTABLE) {
13        int index = 0;
14        lua_pushnil(L);
15        while (lua_next(L, -3)) {
16            int tkey = lua_type(L, -2); /* key at -2, value at -1 */
17            if (category != 3) {
18                if (category == 1) {
19                    if (tkey != LUA_TSTRING) {
20                        category = 3;
21                    }
22                } else if (category == 2) {
23                    if (tkey != LUA_TNUMBER) {
24                        category = 3;
25                    }
26                } else {
27                    if (tkey == LUA_TSTRING) {
28                        category = 1;
29                    } else if (tkey == LUA_TNUMBER) {
30                        category = 2;
31                    } else {
32                        category = 3;
33                    }
34                }
35            }
36            lua_pushvalue(L, -2);
37            lua_rawseti(L, 2, ++index);
38            lua_pop(L, 1); /* key kept for next iteration */
39        }
40    }
41    lua_pushinteger(L, category);
42    return 2; 
43}
44
45/* 
46
47local function get(t,n)
48    local min  = 1
49    local max = #t
50    while min <= max do
51        local mid = min + (max - min) // 2
52        if t[mid] == n then
53            return mid
54        elseif t[mid] < n then
55            min = mid + 1
56        else
57            max = mid - 1
58        end
59    end
60    return nil
61end
62
63*/
64
65static int tablib_binsearch(lua_State *L)
66{
67    if (lua_type(L, 1) == LUA_TTABLE) {
68        lua_Integer val = lua_tointeger(L, 2);
69        lua_Unsigned min  = 1;
70        lua_Unsigned max = lua_rawlen(L, 1);
71        while (min <= max) {
72            lua_Unsigned mid = min + (max - min) / 2;
73            if (lua_rawgeti(L, 1, mid) == LUA_TNUMBER) {
74                lua_Integer tmp = lua_tointeger(L, -1); 
75                lua_pop(L, 1);
76                if (tmp == val) {
77                    lua_pushinteger(L, mid);
78                    return 1;
79                } else if (tmp < val) {
80                    min = mid + 1;
81                } else {
82                    max = mid - 1;
83                }
84            }
85        }
86    }
87    lua_pushnil(L);
88    return 1;
89}
90
91static const luaL_Reg tablib_function_list[] = {
92    { "getkeys",   tablib_keys      },
93    { "binsearch", tablib_binsearch },
94    { NULL,        NULL             },
95};
96
97int luaextend_table(lua_State * L)
98{
99    lua_getglobal(L, "table");
100    for (const luaL_Reg *lib = tablib_function_list; lib->name; lib++) {
101        lua_pushcfunction(L, lib->func);
102        lua_setfield(L, -2, lib->name);
103    }
104    lua_pop(L, 1);
105    return 1;
106}
107