Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add lua user types + bytearray #251

Merged
merged 7 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions res/modules/bit_converter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,19 @@ local function floatOrDoubleToBytes(val, opt)
if opt == 'd' then
val = mantissa
for i = 1, 6 do
table.insert(bytes, math.floor(val) % (2 ^ 8))
bytes[#bytes + 1] = math.floor(val) % (2 ^ 8)
val = math.floor(val / (2 ^ 8))
end
else
table.insert(bytes, math.floor(mantissa) % (2 ^ 8))
bytes[#bytes + 1] = math.floor(mantissa) % (2 ^ 8)
val = math.floor(mantissa / (2 ^ 8))
table.insert(bytes, math.floor(val) % (2 ^ 8))
bytes[#bytes + 1] = math.floor(val) % (2 ^ 8)
val = math.floor(val / (2 ^ 8))
end

table.insert(bytes, math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8))
bytes[#bytes + 1] = math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8)
val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8))
table.insert(bytes, math.floor(sign * 128 + val) % (2 ^ 8))
bytes[#bytes + 1] = math.floor(sign * 128 + val) % (2 ^ 8)
val = math.floor((sign * 128 + val) / (2 ^ 8))

if not endianness then
Expand Down
15 changes: 15 additions & 0 deletions src/files/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ std::unique_ptr<ubyte[]> files::read_bytes(const fs::path& filename, size_t& len
return data;
}

std::vector<ubyte> files::read_bytes(const fs::path& filename) {
std::ifstream input(filename, std::ios::binary);
if (!input.is_open())
return {};
input.seekg(0, std::ios_base::end);
size_t length = input.tellg();
input.seekg(0, std::ios_base::beg);

std::vector<ubyte> data(length);
data.resize(length);
input.read((char*)data.data(), length);
input.close();
return data;
}

std::string files::read_string(const fs::path& filename) {
size_t size;
std::unique_ptr<ubyte[]> bytes (read_bytes(filename, size));
Expand Down
1 change: 1 addition & 0 deletions src/files/files.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace files {

bool read(const fs::path&, char* data, size_t size);
std::unique_ptr<ubyte[]> read_bytes(const fs::path&, size_t& length);
std::vector<ubyte> read_bytes(const fs::path&);
std::string read_string(const fs::path& filename);

/// @brief Read JSON or BJSON file
Expand Down
21 changes: 7 additions & 14 deletions src/logic/scripting/lua/libfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,8 @@ static int l_file_mkdirs(lua::State* L) {
static int l_file_read_bytes(lua::State* L) {
fs::path path = resolve_path(lua::require_string(L, 1));
if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(path));

auto bytes = files::read_bytes(path, length);

lua::createtable(L, length, 0);
int newTable = lua::gettop(L);

for(size_t i = 0; i < length; i++) {
lua::pushinteger(L, bytes[i]);
lua::rawseti(L, i+1, newTable);
}
return 1;
auto bytes = files::read_bytes(path);
return lua::newuserdata<lua::Bytearray>(L, std::move(bytes));
}
throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
}
Expand Down Expand Up @@ -151,10 +141,13 @@ static int l_file_write_bytes(lua::State* L) {

fs::path path = resolve_path(lua::require_string(L, pathIndex));

std::vector<ubyte> bytes;
if (auto bytearray = lua::touserdata<lua::Bytearray>(L, -1)) {
auto& bytes = bytearray->data();
return lua::pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size()));
}

std::vector<ubyte> bytes;
int result = read_bytes_from_table(L, -1, bytes);

if(result != 1) {
return result;
} else {
Expand Down
183 changes: 183 additions & 0 deletions src/logic/scripting/lua/lua_custom_types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#include "lua_custom_types.hpp"

#include "lua_util.hpp"

#include <sstream>

using namespace lua;


Bytearray::Bytearray(size_t capacity)
: buffer(capacity) {
buffer.resize(capacity);
}

Bytearray::Bytearray(std::vector<ubyte> buffer) : buffer(std::move(buffer)) {
}

Bytearray::~Bytearray() {
}

static int l_bytearray_append(lua::State* L) {
if (auto buffer = touserdata<Bytearray>(L, 1)) {
auto value = tointeger(L, 2);
buffer->data().push_back(static_cast<ubyte>(value));
}
return 0;
}

static int l_bytearray_insert(lua::State* L) {
auto buffer = touserdata<Bytearray>(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;
}
auto value = tointeger(L, 3);
data.insert(data.begin() + index, static_cast<ubyte>(value));
return 0;
}

static int l_bytearray_remove(lua::State* L) {
auto buffer = touserdata<Bytearray>(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> bytearray_methods {
{"append", lua::wrap<l_bytearray_append>},
{"insert", lua::wrap<l_bytearray_insert>},
{"remove", lua::wrap<l_bytearray_remove>},
};

static int l_bytearray_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<Bytearray>(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<Bytearray>(L, static_cast<size_t>(size));
}

static int l_bytearray_meta_index(lua::State* L) {
auto buffer = touserdata<Bytearray>(L, 1);
if (buffer == nullptr) {
return 0;
}
auto& data = buffer->data();
if (isstring(L, 2)) {
auto found = bytearray_methods.find(tostring(L, 2));
if (found != bytearray_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[index]);
}

static int l_bytearray_meta_newindex(lua::State* L) {
auto buffer = touserdata<Bytearray>(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_bytearray_meta_len(lua::State* L) {
if (auto buffer = touserdata<Bytearray>(L, 1)) {
return pushinteger(L, buffer->data().size());
}
return 0;
}

static int l_bytearray_meta_tostring(lua::State* L) {
auto buffer = touserdata<Bytearray>(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_bytearray_meta_add(lua::State* L) {
auto bufferA = touserdata<Bytearray>(L, 1);
auto bufferB = touserdata<Bytearray>(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<Bytearray>(L, std::move(ab));
}

int Bytearray::createMetatable(lua::State* L) {
createtable(L, 0, 6);
pushcfunction(L, lua::wrap<l_bytearray_meta_index>);
setfield(L, "__index");
pushcfunction(L, lua::wrap<l_bytearray_meta_newindex>);
setfield(L, "__newindex");
pushcfunction(L, lua::wrap<l_bytearray_meta_len>);
setfield(L, "__len");
pushcfunction(L, lua::wrap<l_bytearray_meta_tostring>);
setfield(L, "__tostring");
pushcfunction(L, lua::wrap<l_bytearray_meta_add>);
setfield(L, "__add");

createtable(L, 0, 1);
pushcfunction(L, lua::wrap<l_bytearray_meta_meta_call>);
setfield(L, "__call");
setmetatable(L);
return 1;
}
35 changes: 35 additions & 0 deletions src/logic/scripting/lua/lua_custom_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef LOGIC_SCRIPTING_LUA_LUA_CUSTOM_TYPES_HPP_
#define LOGIC_SCRIPTING_LUA_LUA_CUSTOM_TYPES_HPP_

#include "lua_commons.hpp"

#include <string>
#include <vector>

namespace lua {
class Userdata {
public:
virtual ~Userdata() {};
virtual const std::string& getTypeName() const = 0;
};

class Bytearray : public Userdata {
std::vector<ubyte> buffer;
public:
Bytearray(size_t capacity);
Bytearray(std::vector<ubyte> buffer);
virtual ~Bytearray();

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";
};
}

#endif // LOGIC_SCRIPTING_LUA_LUA_CUSTOM_TYPES_HPP_
4 changes: 3 additions & 1 deletion src/logic/scripting/lua/lua_engine.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "lua_engine.hpp"

#include "api_lua.hpp"
#include "lua_custom_types.hpp"
#include "../../../debug/Logger.hpp"
#include "../../../util/stringutil.hpp"

Expand Down Expand Up @@ -45,7 +46,6 @@ static void create_libs(lua::State* L) {
addfunc(L, "print", lua::wrap<l_print>);
}

#include <iostream>
void lua::initialize() {
logger.info() << LUA_VERSION;
logger.info() << LUAJIT_VERSION;
Expand Down Expand Up @@ -81,6 +81,8 @@ void lua::initialize() {

createtable(L, 0, 0);
setglobal(L, LAMBDAS_TABLE);

newusertype<Bytearray, Bytearray::createMetatable>(L, "bytearray");
}

void lua::finalize() {
Expand Down
9 changes: 9 additions & 0 deletions src/logic/scripting/lua/lua_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ using namespace lua;

static int nextEnvironment = 1;

std::unordered_map<std::type_index, std::string> lua::usertypeNames;

int lua::userdata_destructor(lua::State* L) {
if (auto obj = touserdata<Userdata>(L, 1)) {
obj->~Userdata();
}
return 0;
}

std::string lua::env_name(int env) {
return "_ENV"+util::mangleid(env);
}
Expand Down
Loading
Loading