Skip to main content

luaur_vm/functions/
extendstrbuf.rs

1//! Node: `cxx:Function:Luau.VM:VM/src/laux.cpp:449:extendstrbuf`
2//!
3//! Grow a `luaL_Strbuf` past its inline buffer: allocate a GC string of the next
4//! size, copy the used prefix, box it on the stack at `boxloc` (inserting a slot
5//! the first time it spills off the inline buffer), and repoint p/end/storage.
6
7use crate::functions::getnextbuffersize::getnextbuffersize;
8use crate::functions::lua_insert::lua_insert;
9use crate::functions::lua_pushnil::lua_pushnil;
10use crate::functions::lua_s_bufstart::lua_s_bufstart;
11use crate::macros::setsvalue::setsvalue;
12use crate::macros::tsvalue::tsvalue;
13use crate::records::lua_l_strbuf::LuaLStrbuf;
14use core::ffi::{c_char, c_int};
15use luaur_common::LUAU_ASSERT;
16
17pub fn extendstrbuf(B: *mut LuaLStrbuf, additionalsize: usize, boxloc: c_int) -> *mut c_char {
18    unsafe {
19        let L = (*B).L;
20
21        if !(*B).storage.is_null() {
22            LUAU_ASSERT!((*B).storage.cast_const() == tsvalue!((*L).top.offset(boxloc as isize)));
23        }
24
25        let base: *mut c_char = if !(*B).storage.is_null() {
26            (*(*B).storage).data.as_mut_ptr()
27        } else {
28            (*B).buffer.as_mut_ptr()
29        };
30
31        let capacity = (*B).end.offset_from(base) as usize;
32        let nextsize = getnextbuffersize((*B).L, capacity, capacity + additionalsize);
33
34        let new_storage = lua_s_bufstart(L, nextsize);
35
36        let used = (*B).p.offset_from(base) as usize;
37        core::ptr::copy_nonoverlapping(base, (*new_storage).data.as_mut_ptr(), used);
38
39        // place the string storage at the expected position in the stack
40        if base == (*B).buffer.as_mut_ptr() {
41            lua_pushnil(L);
42            lua_insert(L, boxloc);
43        }
44
45        setsvalue!(L, (*L).top.offset(boxloc as isize), new_storage);
46
47        (*B).p = (*new_storage).data.as_mut_ptr().add(used);
48        (*B).end = (*new_storage).data.as_mut_ptr().add(nextsize);
49        (*B).storage = new_storage;
50
51        (*B).p
52    }
53}