luaur_vm/functions/
str_format.rs1use crate::functions::add_int_64_format::add_int_64_format;
10use crate::functions::addquoted::addquoted;
11use crate::functions::lua_gettop::lua_gettop;
12use crate::functions::lua_l_addchar::lua_l_addchar;
13use crate::functions::lua_l_addlstring::lua_l_addlstring;
14use crate::functions::lua_l_addvalueany::lua_l_addvalueany;
15use crate::functions::lua_l_buffinit::lua_l_buffinit;
16use crate::functions::lua_l_checkinteger_64::lua_l_checkinteger_64;
17use crate::functions::lua_l_checklstring::lua_l_checklstring;
18use crate::functions::lua_l_checknumber::lua_l_checknumber;
19use crate::functions::lua_l_pushresult::lua_l_pushresult;
20use crate::functions::scanformat::scanformat;
21use crate::macros::l_esc::L_ESC;
22use crate::macros::lua_isinteger_64::lua_isinteger_64;
23use crate::macros::lua_l_error::luaL_error;
24use crate::macros::max_format::MAX_FORMAT;
25use crate::macros::max_item::MAX_ITEM;
26use crate::records::lua_l_strbuf::LuaLStrbuf;
27use crate::type_aliases::lua_state::lua_State;
28use core::ffi::{c_char, c_int};
29
30extern "C" {
31 fn snprintf(s: *mut c_char, n: usize, format: *const c_char, ...) -> c_int;
32 fn strchr(s: *const c_char, c: c_int) -> *mut c_char;
33}
34
35pub unsafe fn str_format(L: *mut lua_State) -> c_int {
36 let top = lua_gettop(L);
37 let mut arg: c_int = 1;
38 let mut sfl: usize = 0;
39 let mut strfrmt = lua_l_checklstring(L, arg, &mut sfl);
40 let strfrmt_end = strfrmt.add(sfl);
41
42 let mut b: LuaLStrbuf = LuaLStrbuf {
43 p: core::ptr::null_mut(),
44 end: core::ptr::null_mut(),
45 L: core::ptr::null_mut(),
46 storage: core::ptr::null_mut(),
47 buffer: [0; 512],
48 };
49 lua_l_buffinit(L, &mut b);
50
51 while strfrmt < strfrmt_end {
52 if *strfrmt != L_ESC {
53 lua_l_addchar(&mut b, *strfrmt);
54 strfrmt = strfrmt.add(1);
55 } else {
56 strfrmt = strfrmt.add(1); if *strfrmt == L_ESC {
58 lua_l_addchar(&mut b, *strfrmt);
59 strfrmt = strfrmt.add(1); } else if *strfrmt == b'*' as c_char {
61 strfrmt = strfrmt.add(1);
62 arg += 1;
63 if arg > top {
64 luaL_error!(L, "missing argument #{}", arg);
65 }
66 lua_l_addvalueany(&mut b, arg);
67 } else {
68 let mut form: [c_char; MAX_FORMAT as usize] = [0; MAX_FORMAT as usize];
70 let mut buff: [c_char; MAX_ITEM] = [0; MAX_ITEM];
71 arg += 1;
72 if arg > top {
73 luaL_error!(L, "missing argument #{}", arg);
74 }
75 let mut format_item_size: usize = 0;
76 strfrmt = scanformat(L, strfrmt, form.as_mut_ptr(), &mut format_item_size);
77 let format_indicator = *strfrmt;
78 strfrmt = strfrmt.add(1);
79 match format_indicator as u8 {
80 b'c' => {
81 let count = snprintf(
82 buff.as_mut_ptr(),
83 buff.len(),
84 form.as_ptr(),
85 lua_l_checknumber(L, arg) as c_int,
86 );
87 lua_l_addlstring(&mut b, buff.as_ptr(), count as usize);
88 continue; }
90 b'd' | b'i' => {
91 let value: i64 = if lua_isinteger_64!(L, arg) {
92 lua_l_checkinteger_64(L, arg)
93 } else {
94 lua_l_checknumber(L, arg) as i64
95 };
96 add_int_64_format(&mut form, format_indicator, format_item_size);
97 snprintf(buff.as_mut_ptr(), buff.len(), form.as_ptr(), value);
98 }
99 b'o' | b'u' | b'x' | b'X' => {
100 let v: u64 = if lua_isinteger_64!(L, arg) {
101 lua_l_checkinteger_64(L, arg) as u64
102 } else {
103 let arg_value = lua_l_checknumber(L, arg);
104 if arg_value < 0.0 {
105 (arg_value as i64) as u64
106 } else {
107 arg_value as u64
108 }
109 };
110 add_int_64_format(&mut form, format_indicator, format_item_size);
111 snprintf(buff.as_mut_ptr(), buff.len(), form.as_ptr(), v);
112 }
113 b'e' | b'E' | b'f' | b'g' | b'G' => {
114 snprintf(
115 buff.as_mut_ptr(),
116 buff.len(),
117 form.as_ptr(),
118 lua_l_checknumber(L, arg),
119 );
120 }
121 b'q' => {
122 addquoted(L, &mut b, arg);
123 continue; }
125 b's' => {
126 let mut l: usize = 0;
127 let s = lua_l_checklstring(L, arg, &mut l);
128 if form[2] == 0
130 || (strchr(form.as_ptr(), b'.' as c_int).is_null() && l >= 100)
131 {
132 lua_l_addlstring(&mut b, s, l);
133 continue; } else {
135 snprintf(buff.as_mut_ptr(), buff.len(), form.as_ptr(), s);
136 }
137 }
138 b'*' => {
139 luaL_error!(L, "'%*' does not take a form");
141 }
142 _ => {
143 luaL_error!(
145 L,
146 "invalid option '%{}' to 'format'",
147 *(strfrmt.offset(-1)) as u8 as char
148 );
149 }
150 }
151 let blen = core::ffi::CStr::from_ptr(buff.as_ptr()).to_bytes().len();
152 lua_l_addlstring(&mut b, buff.as_ptr(), blen);
153 }
154 }
155 }
156
157 lua_l_pushresult(&mut b);
158 1
159}