luaur_vm/functions/
byteoffset.rs1use crate::functions::lua_l_checkinteger::lua_l_checkinteger;
2use crate::functions::lua_l_checklstring::lua_l_checklstring;
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::lua_pushnil::lua_pushnil;
7use crate::functions::u_posrelat::u_posrelat;
8use crate::macros::iscont::iscont;
9use crate::macros::lua_l_argcheck::luaL_argcheck;
10use crate::type_aliases::lua_state::lua_State;
11use core::ffi::c_int;
12
13#[no_mangle]
14pub unsafe fn byteoffset(L: *mut lua_State) -> c_int {
15 let mut len: usize = 0;
16 let s = lua_l_checklstring(L, 1, &mut len);
17 let mut n = lua_l_checkinteger(L, 2);
18 let mut posi = if n >= 0 { 1 } else { len as i32 + 1 };
19 posi = u_posrelat(lua_l_optinteger(L, 3, posi), len);
20 luaL_argcheck!(
21 L,
22 1 <= posi && posi <= len as i32 + 1,
23 3,
24 "position out of range"
25 );
26 posi -= 1;
27
28 if n == 0 {
29 while posi > 0 && iscont(s.add(posi as usize)) {
31 posi -= 1;
32 }
33 } else {
34 if iscont(s.add(posi as usize)) {
35 lua_l_error_l(
36 L,
37 c"initial position is a continuation byte".as_ptr(),
38 core::format_args!("initial position is a continuation byte"),
39 );
40 }
41 if n < 0 {
42 while n < 0 && posi > 0 {
43 loop {
45 posi -= 1;
47 if !(posi > 0 && iscont(s.add(posi as usize))) {
48 break;
49 }
50 }
51 n += 1;
52 }
53 } else {
54 n -= 1; while n > 0 && posi < len as i32 {
56 loop {
57 posi += 1;
59 if !iscont(s.add(posi as usize)) {
60 break;
61 }
62 } n -= 1;
64 }
65 }
66 }
67
68 if n == 0 {
69 lua_pushinteger(L, posi + 1);
71 } else {
72 lua_pushnil(L);
74 }
75 1
76}