Skip to main content

luaur_vm/functions/
codepoint.rs

1use crate::functions::lua_l_checklstring::lua_l_checklstring;
2use crate::functions::lua_l_checkstack::lua_l_checkstack;
3use crate::functions::lua_l_error_l::lua_l_error_l;
4use crate::functions::lua_l_optinteger::lua_l_optinteger;
5use crate::functions::lua_pushinteger::lua_pushinteger;
6use crate::functions::u_posrelat::u_posrelat;
7use crate::functions::utf_8_decode::utf_8_decode;
8use crate::macros::lua_l_argcheck::luaL_argcheck;
9use crate::type_aliases::lua_state::lua_State;
10use core::ffi::c_int;
11
12#[no_mangle]
13pub unsafe fn codepoint(L: *mut lua_State) -> c_int {
14    let mut len: usize = 0;
15    let mut s = lua_l_checklstring(L, 1, &mut len);
16
17    let posi = u_posrelat(lua_l_optinteger(L, 2, 1), len);
18    let pose = u_posrelat(lua_l_optinteger(L, 3, posi), len);
19
20    luaL_argcheck!(L, posi >= 1, 2, "out of range");
21    luaL_argcheck!(L, pose <= len as i32, 3, "out of range");
22
23    if posi > pose {
24        return 0; // empty interval; return no values
25    }
26
27    if (pose - posi) >= c_int::MAX as i32 {
28        lua_l_error_l(
29            L,
30            c"string slice too long".as_ptr(),
31            core::format_args!("string slice too long"),
32        );
33    }
34
35    let n = (pose - posi) + 1;
36    lua_l_checkstack(L, n, "string slice too long");
37
38    let mut n = 0;
39    let se = s.add(pose as usize);
40    s = s.add((posi - 1) as usize);
41
42    while s < se {
43        let mut code: i32 = 0;
44        s = utf_8_decode(s, &mut code);
45        if s.is_null() {
46            lua_l_error_l(
47                L,
48                c"invalid UTF-8 code".as_ptr(),
49                core::format_args!("invalid UTF-8 code"),
50            );
51        }
52        lua_pushinteger(L, code);
53        n += 1;
54    }
55
56    n
57}