replace Bytearray with FFI implementation
This commit is contained in:
parent
794aa5b9cd
commit
303e861fbb
@ -118,20 +118,22 @@ local bytearray_mt = {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local utf8tostring = utf8.tostring
|
|
||||||
|
|
||||||
function utf8.tostring(bytes)
|
|
||||||
local type = _type(bytes)
|
|
||||||
if type == "cdata" then
|
|
||||||
return FFI.string(bytes.bytes, bytes.size)
|
|
||||||
else
|
|
||||||
return utf8tostring(bytes)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local bytearray_type = FFI.metatype("bytearray_t", bytearray_mt)
|
local bytearray_type = FFI.metatype("bytearray_t", bytearray_mt)
|
||||||
|
|
||||||
return function (n)
|
local function FFIBytearray (n)
|
||||||
|
local t = type(n)
|
||||||
|
if t == "string" then
|
||||||
|
local buffer = malloc(#n)
|
||||||
|
FFI.copy(buffer, n, #n)
|
||||||
|
return bytearray_type(buffer, #n, #n)
|
||||||
|
elseif t == "table" then
|
||||||
|
local capacity = math.max(#n, MIN_CAPACITY)
|
||||||
|
local buffer = malloc(capacity)
|
||||||
|
for i=1,#n do
|
||||||
|
buffer[i - 1] = n[i]
|
||||||
|
end
|
||||||
|
return bytearray_type(buffer, #n, capacity)
|
||||||
|
end
|
||||||
n = n or 0
|
n = n or 0
|
||||||
if n < MIN_CAPACITY then
|
if n < MIN_CAPACITY then
|
||||||
return bytearray_type(malloc(MIN_CAPACITY), n, MIN_CAPACITY)
|
return bytearray_type(malloc(MIN_CAPACITY), n, MIN_CAPACITY)
|
||||||
@ -139,3 +141,23 @@ return function (n)
|
|||||||
return bytearray_type(malloc(n), n, n)
|
return bytearray_type(malloc(n), n, n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function FFIBytearray_as_string(bytes)
|
||||||
|
local t = type(bytes)
|
||||||
|
if t == "cdata" then
|
||||||
|
return FFI.string(bytes.bytes, bytes.size)
|
||||||
|
elseif t == "table" then
|
||||||
|
local buffer = FFI.new("unsigned char[?]", #bytes)
|
||||||
|
for i=1, #bytes do
|
||||||
|
buffer[i - 1] = bytes[i]
|
||||||
|
end
|
||||||
|
return FFI.string(buffer, #bytes)
|
||||||
|
else
|
||||||
|
error("Bytearray expected, got "..type(bytes))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
FFIBytearray = FFIBytearray,
|
||||||
|
FFIBytearray_as_string = FFIBytearray_as_string
|
||||||
|
}
|
||||||
|
|||||||
@ -263,7 +263,9 @@ entities.get_all = function(uids)
|
|||||||
return stdcomp.get_all(uids)
|
return stdcomp.get_all(uids)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
FFIBytearray = require "core:internal/bytearray"
|
local bytearray = require "core:internal/bytearray"
|
||||||
|
Bytearray = bytearray.FFIBytearray
|
||||||
|
Bytearray_as_string = bytearray.FFIBytearray_as_string
|
||||||
ffi = nil
|
ffi = nil
|
||||||
|
|
||||||
math.randomseed(time.uptime() * 1536227939)
|
math.randomseed(time.uptime() * 1536227939)
|
||||||
|
|||||||
@ -16,14 +16,14 @@ static int l_encode(lua::State* L) {
|
|||||||
return lua::pushstring(L, util::base64_encode(
|
return lua::pushstring(L, util::base64_encode(
|
||||||
reinterpret_cast<const ubyte*>(buffer.data()), buffer.size()
|
reinterpret_cast<const ubyte*>(buffer.data()), buffer.size()
|
||||||
));
|
));
|
||||||
} else if (auto bytes = lua::touserdata<lua::LuaBytearray>(L, 1)) {
|
} else {
|
||||||
return lua::pushstring(
|
auto string = lua::bytearray_as_string(L, 1);
|
||||||
L,
|
auto out = util::base64_encode(
|
||||||
util::base64_encode(
|
reinterpret_cast<const ubyte*>(string.data()),
|
||||||
bytes->data().data(),
|
string.size()
|
||||||
bytes->data().size()
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
lua::pop(L);
|
||||||
|
return lua::pushstring(L, std::move(out));
|
||||||
}
|
}
|
||||||
throw std::runtime_error("array or ByteArray expected");
|
throw std::runtime_error("array or ByteArray expected");
|
||||||
}
|
}
|
||||||
@ -36,13 +36,10 @@ static int l_decode(lua::State* L) {
|
|||||||
lua::pushinteger(L, buffer[i] & 0xFF);
|
lua::pushinteger(L, buffer[i] & 0xFF);
|
||||||
lua::rawseti(L, i+1);
|
lua::rawseti(L, i+1);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
lua::newuserdata<lua::LuaBytearray>(L, buffer.size());
|
|
||||||
auto bytearray = lua::touserdata<lua::LuaBytearray>(L, -1);
|
|
||||||
bytearray->data().reserve(buffer.size());
|
|
||||||
std::memcpy(bytearray->data().data(), buffer.data(), buffer.size());
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
return lua::create_bytearray(L, buffer.data(), buffer.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg base64lib[] = {
|
const luaL_Reg base64lib[] = {
|
||||||
|
|||||||
@ -9,9 +9,7 @@ static int l_tobytes(lua::State* L) {
|
|||||||
if (lua::gettop(L) >= 2) {
|
if (lua::gettop(L) >= 2) {
|
||||||
compress = lua::toboolean(L, 2);
|
compress = lua::toboolean(L, 2);
|
||||||
}
|
}
|
||||||
return lua::newuserdata<lua::LuaBytearray>(
|
return lua::create_bytearray(L, json::to_binary(value, compress));
|
||||||
L, json::to_binary(value, compress)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_frombytes(lua::State* L) {
|
static int l_frombytes(lua::State* L) {
|
||||||
@ -24,17 +22,18 @@ static int l_frombytes(lua::State* L) {
|
|||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
return lua::pushvalue(L, json::from_binary(buffer.data(), len));
|
return lua::pushvalue(L, json::from_binary(buffer.data(), len));
|
||||||
} else if (auto bytes = lua::touserdata<lua::LuaBytearray>(L, -1)) {
|
|
||||||
const auto& buffer = bytes->data();
|
|
||||||
return lua::pushvalue(
|
|
||||||
L, json::from_binary(buffer.data(), buffer.size())
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("table or Bytearray expected");
|
auto string = lua::bytearray_as_string(L, 1);
|
||||||
|
auto out = json::from_binary(
|
||||||
|
reinterpret_cast<const ubyte*>(string.data()), string.size()
|
||||||
|
);
|
||||||
|
lua::pop(L);
|
||||||
|
return lua::pushvalue(L, std::move(out));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg bjsonlib[] = {
|
const luaL_Reg bjsonlib[] = {
|
||||||
{"tobytes", lua::wrap<l_tobytes>},
|
{"tobytes", lua::wrap<l_tobytes>},
|
||||||
{"frombytes", lua::wrap<l_frombytes>},
|
{"frombytes", lua::wrap<l_frombytes>},
|
||||||
{NULL, NULL}};
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|||||||
@ -99,7 +99,7 @@ static int pack(lua::State* L, const char* format, bool usetable) {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return lua::newuserdata<lua::LuaBytearray>(L, builder.build());
|
return lua::create_bytearray(L, builder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,8 +130,8 @@ static int count_elements(const char* format) {
|
|||||||
static int l_unpack(lua::State* L) {
|
static int l_unpack(lua::State* L) {
|
||||||
const char* format = lua::require_string(L, 1);
|
const char* format = lua::require_string(L, 1);
|
||||||
int count = count_elements(format);
|
int count = count_elements(format);
|
||||||
auto bytes = lua::require_bytearray(L, 2);
|
auto bytes = lua::bytearray_as_string(L, 2);
|
||||||
ByteReader reader(bytes);
|
ByteReader reader(reinterpret_cast<const ubyte*>(bytes.data()), bytes.size());
|
||||||
bool bigEndian = false;
|
bool bigEndian = false;
|
||||||
|
|
||||||
for (size_t i = 0; format[i]; i++) {
|
for (size_t i = 0; format[i]; i++) {
|
||||||
|
|||||||
@ -248,12 +248,14 @@ static int l_load_texture(lua::State* L) {
|
|||||||
}
|
}
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
load_texture(buffer.data(), buffer.size(), lua::require_string(L, 2));
|
load_texture(buffer.data(), buffer.size(), lua::require_string(L, 2));
|
||||||
} else if (auto bytes = lua::touserdata<lua::LuaBytearray>(L, 1)) {
|
} else {
|
||||||
|
auto string = lua::bytearray_as_string(L, 1);
|
||||||
load_texture(
|
load_texture(
|
||||||
bytes->data().data(),
|
reinterpret_cast<const ubyte*>(string.data()),
|
||||||
bytes->data().size(),
|
string.size(),
|
||||||
lua::require_string(L, 2)
|
lua::require_string(L, 2)
|
||||||
);
|
);
|
||||||
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,7 @@ static int l_read_bytes(lua::State* L) {
|
|||||||
auto bytes = io::read_bytes(path);
|
auto bytes = io::read_bytes(path);
|
||||||
|
|
||||||
if (lua::gettop(L) < 2 || !lua::toboolean(L, 2)) {
|
if (lua::gettop(L) < 2 || !lua::toboolean(L, 2)) {
|
||||||
lua::newuserdata<lua::LuaBytearray>(L, std::move(bytes));
|
lua::create_bytearray(L, std::move(bytes));
|
||||||
} else {
|
} else {
|
||||||
lua::createtable(L, length, 0);
|
lua::createtable(L, length, 0);
|
||||||
int newTable = lua::gettop(L);
|
int newTable = lua::gettop(L);
|
||||||
@ -148,18 +148,12 @@ static int l_read_bytes(lua::State* L) {
|
|||||||
static int l_write_bytes(lua::State* L) {
|
static int l_write_bytes(lua::State* L) {
|
||||||
io::path path = get_writeable_path(L);
|
io::path path = get_writeable_path(L);
|
||||||
|
|
||||||
if (auto bytearray = lua::touserdata<lua::LuaBytearray>(L, 2)) {
|
auto string = lua::bytearray_as_string(L, 2);
|
||||||
auto& bytes = bytearray->data();
|
bool res = io::write_bytes(
|
||||||
return lua::pushboolean(
|
path, reinterpret_cast<const ubyte*>(string.data()), string.size()
|
||||||
L, io::write_bytes(path, bytes.data(), bytes.size())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ubyte> bytes;
|
|
||||||
lua::read_bytes_from_table(L, 2, bytes);
|
|
||||||
return lua::pushboolean(
|
|
||||||
L, io::write_bytes(path, bytes.data(), bytes.size())
|
|
||||||
);
|
);
|
||||||
|
lua::pop(L);
|
||||||
|
return lua::pushboolean(L, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_list_all_res(lua::State* L, const std::string& path) {
|
static int l_list_all_res(lua::State* L, const std::string& path) {
|
||||||
|
|||||||
@ -109,13 +109,13 @@ static int l_send(lua::State* L, network::Network& network) {
|
|||||||
}
|
}
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
connection->send(buffer.data(), size);
|
connection->send(buffer.data(), size);
|
||||||
} else if (auto bytes = lua::touserdata<lua::LuaBytearray>(L, 2)) {
|
|
||||||
connection->send(
|
|
||||||
reinterpret_cast<char*>(bytes->data().data()), bytes->data().size()
|
|
||||||
);
|
|
||||||
} else if (lua::isstring(L, 2)) {
|
} else if (lua::isstring(L, 2)) {
|
||||||
auto string = lua::tolstring(L, 2);
|
auto string = lua::tolstring(L, 2);
|
||||||
connection->send(string.data(), string.length());
|
connection->send(string.data(), string.length());
|
||||||
|
} else {
|
||||||
|
auto string = lua::bytearray_as_string(L, 2);
|
||||||
|
connection->send(string.data(), string.length());
|
||||||
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -140,13 +140,10 @@ static int l_recv(lua::State* L, network::Network& network) {
|
|||||||
lua::pushinteger(L, buffer[i] & 0xFF);
|
lua::pushinteger(L, buffer[i] & 0xFF);
|
||||||
lua::rawseti(L, i+1);
|
lua::rawseti(L, i+1);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
lua::newuserdata<lua::LuaBytearray>(L, size);
|
|
||||||
auto bytearray = lua::touserdata<lua::LuaBytearray>(L, -1);
|
|
||||||
bytearray->data().reserve(size);
|
|
||||||
std::memcpy(bytearray->data().data(), buffer.data(), size);
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
return lua::create_bytearray(L, buffer.data(), size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_available(lua::State* L, network::Network& network) {
|
static int l_available(lua::State* L, network::Network& network) {
|
||||||
|
|||||||
@ -14,13 +14,10 @@ static int l_tobytes(lua::State* L) {
|
|||||||
lua::pushinteger(L, string[i] & 0xFF);
|
lua::pushinteger(L, string[i] & 0xFF);
|
||||||
lua::rawseti(L, i+1);
|
lua::rawseti(L, i+1);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
lua::newuserdata<lua::LuaBytearray>(L, string.length());
|
|
||||||
auto bytearray = lua::touserdata<lua::LuaBytearray>(L, -1);
|
|
||||||
bytearray->data().reserve(string.length());
|
|
||||||
std::memcpy(bytearray->data().data(), string.data(), string.length());
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
return lua::create_bytearray(L, string.data(), string.length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_tostring(lua::State* L) {
|
static int l_tostring(lua::State* L) {
|
||||||
@ -35,16 +32,10 @@ static int l_tostring(lua::State* L) {
|
|||||||
}
|
}
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
return lua::pushlstring(L, buffer.data(), size);
|
return lua::pushlstring(L, buffer.data(), size);
|
||||||
} else if (auto bytes = lua::touserdata<lua::LuaBytearray>(L, 1)) {
|
} else {
|
||||||
return lua::pushstring(
|
lua::bytearray_as_string(L, 1);
|
||||||
L,
|
|
||||||
std::string(
|
|
||||||
reinterpret_cast<char*>(bytes->data().data()),
|
|
||||||
bytes->data().size()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_length(lua::State* L) {
|
static int l_length(lua::State* L) {
|
||||||
|
|||||||
@ -144,7 +144,7 @@ static int l_get_chunk_data(lua::State* L) {
|
|||||||
} else {
|
} else {
|
||||||
chunkData = compressed_chunks::encode(*chunk);
|
chunkData = compressed_chunks::encode(*chunk);
|
||||||
}
|
}
|
||||||
return lua::newuserdata<lua::LuaBytearray>(L, std::move(chunkData));
|
return lua::create_bytearray(L, std::move(chunkData));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void integrate_chunk_client(Chunk& chunk) {
|
static void integrate_chunk_client(Chunk& chunk) {
|
||||||
@ -175,14 +175,17 @@ static int l_set_chunk_data(lua::State* L) {
|
|||||||
|
|
||||||
int x = static_cast<int>(lua::tointeger(L, 1));
|
int x = static_cast<int>(lua::tointeger(L, 1));
|
||||||
int z = static_cast<int>(lua::tointeger(L, 2));
|
int z = static_cast<int>(lua::tointeger(L, 2));
|
||||||
auto buffer = lua::require_bytearray(L, 3);
|
auto buffer = lua::bytearray_as_string(L, 3);
|
||||||
|
|
||||||
auto chunk = level->chunks->getChunk(x, z);
|
auto chunk = level->chunks->getChunk(x, z);
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
return lua::pushboolean(L, false);
|
return lua::pushboolean(L, false);
|
||||||
}
|
}
|
||||||
compressed_chunks::decode(
|
compressed_chunks::decode(
|
||||||
*chunk, buffer.data(), buffer.size(), *content->getIndices()
|
*chunk,
|
||||||
|
reinterpret_cast<const ubyte*>(buffer.data()),
|
||||||
|
buffer.size(),
|
||||||
|
*content->getIndices()
|
||||||
);
|
);
|
||||||
if (controller->getChunksController()->lighting == nullptr) {
|
if (controller->getChunksController()->lighting == nullptr) {
|
||||||
return lua::pushboolean(L, true);
|
return lua::pushboolean(L, true);
|
||||||
@ -198,10 +201,16 @@ static int l_save_chunk_data(lua::State* L) {
|
|||||||
|
|
||||||
int x = static_cast<int>(lua::tointeger(L, 1));
|
int x = static_cast<int>(lua::tointeger(L, 1));
|
||||||
int z = static_cast<int>(lua::tointeger(L, 2));
|
int z = static_cast<int>(lua::tointeger(L, 2));
|
||||||
auto buffer = lua::require_bytearray(L, 3);
|
auto buffer = lua::bytearray_as_string(L, 3);
|
||||||
|
|
||||||
compressed_chunks::save(
|
compressed_chunks::save(
|
||||||
x, z, std::move(buffer), level->getWorld()->wfile->getRegions()
|
x,
|
||||||
|
z,
|
||||||
|
std::vector(
|
||||||
|
reinterpret_cast<const ubyte*>(buffer.data()),
|
||||||
|
reinterpret_cast<const ubyte*>(buffer.data()) + buffer.size()
|
||||||
|
),
|
||||||
|
level->getWorld()->wfile->getRegions()
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,26 +18,6 @@ namespace lua {
|
|||||||
virtual const std::string& getTypeName() const = 0;
|
virtual const std::string& getTypeName() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LuaBytearray : public Userdata {
|
|
||||||
std::vector<ubyte> buffer;
|
|
||||||
public:
|
|
||||||
LuaBytearray(size_t capacity);
|
|
||||||
LuaBytearray(std::vector<ubyte> buffer);
|
|
||||||
LuaBytearray(const ubyte* data, size_t size);
|
|
||||||
virtual ~LuaBytearray();
|
|
||||||
|
|
||||||
const std::string& getTypeName() const override {
|
|
||||||
return TYPENAME;
|
|
||||||
}
|
|
||||||
inline std::vector<ubyte>& data() {
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int createMetatable(lua::State*);
|
|
||||||
inline static std::string TYPENAME = "Bytearray";
|
|
||||||
};
|
|
||||||
static_assert(!std::is_abstract<LuaBytearray>());
|
|
||||||
|
|
||||||
class LuaHeightmap : public Userdata {
|
class LuaHeightmap : public Userdata {
|
||||||
std::shared_ptr<Heightmap> map;
|
std::shared_ptr<Heightmap> map;
|
||||||
std::unique_ptr<fnl_state> noise;
|
std::unique_ptr<fnl_state> noise;
|
||||||
|
|||||||
@ -117,7 +117,6 @@ void lua::init_state(State* L, StateType stateType) {
|
|||||||
|
|
||||||
initialize_libs_extends(L);
|
initialize_libs_extends(L);
|
||||||
|
|
||||||
newusertype<LuaBytearray>(L);
|
|
||||||
newusertype<LuaHeightmap>(L);
|
newusertype<LuaHeightmap>(L);
|
||||||
newusertype<LuaVoxelFragment>(L);
|
newusertype<LuaVoxelFragment>(L);
|
||||||
newusertype<LuaCanvas>(L);
|
newusertype<LuaCanvas>(L);
|
||||||
|
|||||||
@ -39,14 +39,16 @@ int l_crc32(lua::State* L) {
|
|||||||
string.length()
|
string.length()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else if (auto bytearray = lua::touserdata<lua::LuaBytearray>(L, 1)) {
|
|
||||||
auto& bytes = bytearray->data();
|
|
||||||
return lua::pushinteger(L, crc32(value, bytes.data(), bytes.size()));
|
|
||||||
} else if (lua::istable(L, 1)) {
|
} else if (lua::istable(L, 1)) {
|
||||||
std::vector<ubyte> bytes;
|
std::vector<ubyte> bytes;
|
||||||
lua::read_bytes_from_table(L, 1, bytes);
|
lua::read_bytes_from_table(L, 1, bytes);
|
||||||
return lua::pushinteger(L, crc32(value, bytes.data(), bytes.size()));
|
return lua::pushinteger(L, crc32(value, bytes.data(), bytes.size()));
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("invalid argument 1");
|
auto string = lua::bytearray_as_string(L, 1);
|
||||||
|
auto res = crc32(
|
||||||
|
value, reinterpret_cast<const ubyte*>(string.data()), string.size()
|
||||||
|
);
|
||||||
|
lua::pop(L);
|
||||||
|
return lua::pushinteger(L, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ int lua::pushvalue(State* L, const dv::value& value) {
|
|||||||
break;
|
break;
|
||||||
case value_type::bytes: {
|
case value_type::bytes: {
|
||||||
const auto& bytes = value.asBytes();
|
const auto& bytes = value.asBytes();
|
||||||
newuserdata<LuaBytearray>(L, bytes.data(), bytes.size());
|
create_bytearray(L, bytes.data(), bytes.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,18 +128,14 @@ dv::value lua::tovalue(State* L, int idx) {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case LUA_TUSERDATA: {
|
default: {
|
||||||
if (auto bytes = touserdata<LuaBytearray>(L, idx)) {
|
auto data = bytearray_as_string(L, idx);
|
||||||
const auto& data = bytes->data();
|
auto bytes = std::make_shared<dv::objects::Bytes>(
|
||||||
return std::make_shared<dv::objects::Bytes>(data.data(), data.size());
|
reinterpret_cast<const ubyte*>(data.data()), data.size()
|
||||||
}
|
|
||||||
[[fallthrough]];
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw std::runtime_error(
|
|
||||||
"lua type " + std::string(lua_typename(L, type)) +
|
|
||||||
" is not supported"
|
|
||||||
);
|
);
|
||||||
|
pop(L);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -746,14 +746,22 @@ namespace lua {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::vector<ubyte> require_bytearray(lua::State* L, int idx) {
|
inline int create_bytearray(lua::State* L, const void* bytes, size_t size) {
|
||||||
if (auto* bytearray = lua::touserdata<LuaBytearray>(L, idx)) {
|
lua::requireglobal(L, "Bytearray");
|
||||||
return bytearray->data();
|
lua::pushlstring(
|
||||||
} else if (lua::istable(L, idx)) {
|
L, std::string_view(reinterpret_cast<const char*>(bytes), size)
|
||||||
std::vector<ubyte> bytes;
|
);
|
||||||
read_bytes_from_table(L, idx, bytes);
|
return lua::call(L, 1, 1);
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
throw std::runtime_error("bytearray expected");
|
|
||||||
|
inline int create_bytearray(lua::State* L, const std::vector<ubyte>& bytes) {
|
||||||
|
return create_bytearray(L, bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string_view bytearray_as_string(lua::State* L, int idx) {
|
||||||
|
lua::requireglobal(L, "Bytearray_as_string");
|
||||||
|
lua::pushvalue(L, idx);
|
||||||
|
lua::call(L, 1, 1);
|
||||||
|
return lua::tolstring(L, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,206 +0,0 @@
|
|||||||
#include "../lua_custom_types.hpp"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "util/listutil.hpp"
|
|
||||||
#include "../lua_util.hpp"
|
|
||||||
|
|
||||||
using namespace lua;
|
|
||||||
|
|
||||||
LuaBytearray::LuaBytearray(size_t capacity) : buffer(capacity) {
|
|
||||||
buffer.resize(capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
LuaBytearray::LuaBytearray(std::vector<ubyte> buffer) : buffer(std::move(buffer)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
LuaBytearray::LuaBytearray(const ubyte* data, size_t size) : buffer(data, data + size) {
|
|
||||||
}
|
|
||||||
|
|
||||||
LuaBytearray::~LuaBytearray() {
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_append(lua::State* L) {
|
|
||||||
if (auto buffer = touserdata<LuaBytearray>(L, 1)) {
|
|
||||||
if (lua::isnumber(L, 2)) {
|
|
||||||
auto value = tointeger(L, 2);
|
|
||||||
buffer->data().push_back(static_cast<ubyte>(value));
|
|
||||||
} else if (lua::istable(L, 2)) {
|
|
||||||
lua::read_bytes_from_table(L, 2, buffer->data());
|
|
||||||
} else if (auto extension = lua::touserdata<LuaBytearray>(L, 2)) {
|
|
||||||
util::concat(buffer->data(), extension->data());
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("integer/table/Bytearray expected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_insert(lua::State* L) {
|
|
||||||
auto buffer = touserdata<LuaBytearray>(L, 1);
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto& data = buffer->data();
|
|
||||||
auto index = tointeger(L, 2) - 1;
|
|
||||||
if (static_cast<size_t>(index) > data.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (lua::isnumber(L, 3)) {
|
|
||||||
auto value = tointeger(L, 3);
|
|
||||||
data.insert(data.begin() + index, static_cast<ubyte>(value));
|
|
||||||
} else if (lua::istable(L, 3)) {
|
|
||||||
std::vector<ubyte> temp;
|
|
||||||
lua::read_bytes_from_table(L, 3, temp);
|
|
||||||
data.insert(data.begin() + index, temp.begin(), temp.end());
|
|
||||||
} else if (auto extension = lua::touserdata<LuaBytearray>(L, 3)) {
|
|
||||||
const std::vector<ubyte>& src = extension->data();
|
|
||||||
data.insert(data.begin() + index, src.begin(), src.end());
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("integer/table/Bytearray expected");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_remove(lua::State* L) {
|
|
||||||
auto buffer = touserdata<LuaBytearray>(L, 1);
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto& data = buffer->data();
|
|
||||||
auto index = tointeger(L, 2) - 1;
|
|
||||||
if (static_cast<size_t>(index) > data.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
data.erase(data.begin() + index);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unordered_map<std::string, lua_CFunction> methods {
|
|
||||||
{"append", lua::wrap<l_append>},
|
|
||||||
{"insert", lua::wrap<l_insert>},
|
|
||||||
{"remove", lua::wrap<l_remove>},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int l_meta_meta_call(lua::State* L) {
|
|
||||||
if (lua_istable(L, 2)) {
|
|
||||||
size_t len = objlen(L, 2);
|
|
||||||
std::vector<ubyte> buffer(len);
|
|
||||||
buffer.resize(len);
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
rawgeti(L, i + 1);
|
|
||||||
buffer[i] = static_cast<ubyte>(tointeger(L, -1));
|
|
||||||
pop(L);
|
|
||||||
}
|
|
||||||
return newuserdata<LuaBytearray>(L, std::move(buffer));
|
|
||||||
}
|
|
||||||
auto size = tointeger(L, 2);
|
|
||||||
if (size < 0) {
|
|
||||||
throw std::runtime_error("size can not be less than 0");
|
|
||||||
}
|
|
||||||
return newuserdata<LuaBytearray>(L, static_cast<size_t>(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_meta_index(lua::State* L) {
|
|
||||||
auto buffer = touserdata<LuaBytearray>(L, 1);
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto& data = buffer->data();
|
|
||||||
if (isstring(L, 2)) {
|
|
||||||
auto found = methods.find(tostring(L, 2));
|
|
||||||
if (found != methods.end()) {
|
|
||||||
return pushcfunction(L, found->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto index = tointeger(L, 2) - 1;
|
|
||||||
if (static_cast<size_t>(index) > data.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return pushinteger(L, data.at(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_meta_newindex(lua::State* L) {
|
|
||||||
auto buffer = touserdata<LuaBytearray>(L, 1);
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto& data = buffer->data();
|
|
||||||
auto index = static_cast<size_t>(tointeger(L, 2) - 1);
|
|
||||||
auto value = tointeger(L, 3);
|
|
||||||
if (index >= data.size()) {
|
|
||||||
if (index == data.size()) {
|
|
||||||
data.push_back(static_cast<ubyte>(value));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
data[index] = static_cast<ubyte>(value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_meta_len(lua::State* L) {
|
|
||||||
if (auto buffer = touserdata<LuaBytearray>(L, 1)) {
|
|
||||||
return pushinteger(L, buffer->data().size());
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_meta_tostring(lua::State* L) {
|
|
||||||
auto buffer = touserdata<LuaBytearray>(L, 1);
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto& data = buffer->data();
|
|
||||||
if (data.size() > 512) {
|
|
||||||
return pushstring(
|
|
||||||
L, "bytearray[" + std::to_string(data.size()) + "]{...}"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "bytearray[" << std::to_string(data.size()) << "]{";
|
|
||||||
for (size_t i = 0; i < data.size(); i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
ss << " ";
|
|
||||||
}
|
|
||||||
ss << static_cast<uint>(data[i]);
|
|
||||||
}
|
|
||||||
ss << "}";
|
|
||||||
return pushstring(L, ss.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_meta_add(lua::State* L) {
|
|
||||||
auto bufferA = touserdata<LuaBytearray>(L, 1);
|
|
||||||
auto bufferB = touserdata<LuaBytearray>(L, 2);
|
|
||||||
if (bufferA == nullptr || bufferB == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto& dataA = bufferA->data();
|
|
||||||
auto& dataB = bufferB->data();
|
|
||||||
|
|
||||||
std::vector<ubyte> ab;
|
|
||||||
ab.reserve(dataA.size() + dataB.size());
|
|
||||||
ab.insert(ab.end(), dataA.begin(), dataA.end());
|
|
||||||
ab.insert(ab.end(), dataB.begin(), dataB.end());
|
|
||||||
return newuserdata<LuaBytearray>(L, std::move(ab));
|
|
||||||
}
|
|
||||||
|
|
||||||
int LuaBytearray::createMetatable(lua::State* L) {
|
|
||||||
createtable(L, 0, 6);
|
|
||||||
pushcfunction(L, lua::wrap<l_meta_index>);
|
|
||||||
setfield(L, "__index");
|
|
||||||
pushcfunction(L, lua::wrap<l_meta_newindex>);
|
|
||||||
setfield(L, "__newindex");
|
|
||||||
pushcfunction(L, lua::wrap<l_meta_len>);
|
|
||||||
setfield(L, "__len");
|
|
||||||
pushcfunction(L, lua::wrap<l_meta_tostring>);
|
|
||||||
setfield(L, "__tostring");
|
|
||||||
pushcfunction(L, lua::wrap<l_meta_add>);
|
|
||||||
setfield(L, "__add");
|
|
||||||
|
|
||||||
createtable(L, 0, 1);
|
|
||||||
pushcfunction(L, lua::wrap<l_meta_meta_call>);
|
|
||||||
setfield(L, "__call");
|
|
||||||
setmetatable(L);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user