From 3f829f7a58ac262219bf12bef6d9fac53bde9b3e Mon Sep 17 00:00:00 2001 From: Riley King-Saunders Date: Tue, 25 Nov 2025 00:01:47 +1100 Subject: [PATCH] Nuked existing codebase --- include/includes.h | 12 - include/lua_datetime.h | 9 - include/lua_dependency_tree.h | 101 ----- include/lua_filesystem.h | 64 ---- include/lua_git.h | 0 include/lua_parallel.h | 48 --- include/lua_platform.h | 35 -- include/lua_stack.h | 43 --- include/platform_agnostic.h | 8 - include/simple_string.h | 47 --- src/dynarray.hpp | 365 ------------------- src/lua_dependency_tree.cpp | 667 ---------------------------------- src/lua_filesystem.cpp | 453 ----------------------- src/lua_platform.cpp | 210 ----------- src/main.c | 7 + src/main.cpp | 116 ------ src/simple_string.cpp | 216 ----------- 17 files changed, 7 insertions(+), 2394 deletions(-) delete mode 100644 include/includes.h delete mode 100644 include/lua_datetime.h delete mode 100644 include/lua_dependency_tree.h delete mode 100644 include/lua_filesystem.h delete mode 100644 include/lua_git.h delete mode 100644 include/lua_parallel.h delete mode 100644 include/lua_platform.h delete mode 100644 include/lua_stack.h delete mode 100644 include/platform_agnostic.h delete mode 100644 include/simple_string.h delete mode 100644 src/dynarray.hpp delete mode 100644 src/lua_dependency_tree.cpp delete mode 100644 src/lua_filesystem.cpp delete mode 100644 src/lua_platform.cpp create mode 100644 src/main.c delete mode 100644 src/main.cpp delete mode 100644 src/simple_string.cpp diff --git a/include/includes.h b/include/includes.h deleted file mode 100644 index 0c16627..0000000 --- a/include/includes.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -// Any function marked with this means that the exposed lua API is not sandboxed -#define LUA_UNSAFE diff --git a/include/lua_datetime.h b/include/lua_datetime.h deleted file mode 100644 index db354c4..0000000 --- a/include/lua_datetime.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "includes.h" - -int luaopen_datetime(lua_State* L); - -int lua_datetime_unix_time(lua_State* L); - -int lua_datetime_tostring(lua_State* L); -int lua_datetime_tounix(lua_State* L); \ No newline at end of file diff --git a/include/lua_dependency_tree.h b/include/lua_dependency_tree.h deleted file mode 100644 index 69705cc..0000000 --- a/include/lua_dependency_tree.h +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once -#include "includes.h" -#include "dynarray.hpp" -#include -#include -#include - -struct dependency_tree -{ - typedef uint32_t ref_t; - typedef ref_t state_t; - typedef ref_t state_cmp_t; - - enum STATE : state_t - { - FULFILLED = 0, - FAILED = 1, - WAITING = 2, - WORKING = 3 - }; - enum STATE_CMP : state_cmp_t - { - CMP_FULFILED = 1, - CMP_FAILED = 2, - CMP_WAITING = 4, - CMP_WORKING = 8 - }; - - struct node - { - node(const node&) = delete; - node& operator =(const node&) = delete; - node(node&& other) noexcept; - node& operator =(node&& other) noexcept; - node(); - // What depends on this node - std::set m_dependents = {}; - // Name of the node - const char* m_name = nullptr; - // How many other nodes does this node depend on - ref_t m_num_pending_dependencies = 0; - // A user-controlled u30 - ref_t m_userdata : (sizeof(ref_t)-2) = -1; - // State of the node - state_t m_state : 2; - - ~node(); - }; - - ~dependency_tree(); - - // A list that maps a nodes name to its index - std::map m_node_name_mapping; - // A list of all nodes in the dependency tree - dynarray m_nodes; - - node& operator[](const ref_t idx) noexcept; - const node& operator[](const ref_t idx) const noexcept; - - dynarray get_leaf_nodes(const bool ignore_fulfilled=false) const; - dynarray get_leaf_node_names(const bool ignore_fulfilled=false) const; - dynarray filter_nodes(const state_cmp_t state_cmp, const ref_t num_dependencies_gt, const bool invert_num_deps) const; - void set_node_state(const ref_t node, const state_t new_state); - void set_node_state(const char* node, const state_t new_state); - - ref_t add_node(const char* node_name, const dynarray& dependents); - ref_t add_node(const char* node_name, const dynarray& dependents); - ref_t add_node(const char* node_name, const std::initializer_list& dependents); - ref_t add_node(const char* node_name, const std::initializer_list& dependents); - ref_t add_node(const char* node_name); - - void add_node_dependency(const ref_t node, const ref_t dependency); - void add_node_dependency(const ref_t node, const char* dependency); - void add_node_dependency(const char* node, const ref_t dependency); - void add_node_dependency(const char* node, const char* dependency); - - void add_node_dependencies(const ref_t node, const std::initializer_list& dependencies); - void add_node_dependencies(const ref_t node, const dynarray& dependencies); - void add_node_dependencies(const ref_t node, const std::initializer_list& dependencies); - void add_node_dependencies(const ref_t node, const dynarray& dependencies); -}; - - -int luaopen_dependency_tree(lua_State* L); - -int lua_dependency_create(lua_State* L); -int lua_dependency_destroy(lua_State* L); -int lua_dependency_add_node(lua_State* L); -int lua_dependency_add_dependency(lua_State* L); -int lua_dependency_remove_dependency(lua_State* L); -int lua_dependency_add_dependencies(lua_State* L); -int lua_dependency_remove_dependencies(lua_State* L); -int lua_dependency_get_leafs(lua_State* L); -int lua_dependency_match_nodes(lua_State* L); -int lua_dependency_get_node_state(lua_State* L); -int lua_dependency_set_node_state(lua_State* L); -int lua_dependency_get_node_userval(lua_State* L); -int lua_dependency_set_node_userval(lua_State* L); -int lua_dependency_get_node_name(lua_State* L); -int lua_dependency_get_node(lua_State* L); -int lua_dependency_index(lua_State* L); \ No newline at end of file diff --git a/include/lua_filesystem.h b/include/lua_filesystem.h deleted file mode 100644 index 61a55f9..0000000 --- a/include/lua_filesystem.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include "includes.h" - -// Provides variables; -// fs.work_dir: string -int luaopen_filesystem(lua_State* L); - -// x = list_dir(path) -int lua_fs_list_dir(lua_State* L); - -// x = list_all_dirs(path) -int lua_fs_list_alldirs(lua_State* L); - -int lua_fs_foreach_dir(lua_State* L); -int lua_fs_forall_dir(lua_State* L); - -int lua_fs_foreach_dir_next(lua_State* L); -int lua_fs_forall_dir_next(lua_State* L); - -int lua_fs_foreach_dir_dtor(lua_State* L); -int lua_fs_forall_dir_dtor(lua_State* L); - -// Returns true when a is newer than b. If b does not exist it returns true. If a does not exist it returns false -// boolean | table function fs.is_newer(path_a: string | number, path_b: string | table[string]) -int lua_fs_is_newer(lua_State* L); -// table | nil function fs.filter_newer(path_a: string | number, path_b: string | table[string]) -int lua_fs_filter_newer(lua_State* L); - -// number | nil function fs.last_modified(path: string) -int lua_fs_last_modified(lua_State* L); -// boolean function fs.exists(path: string) -int lua_fs_exists(lua_State* L); -// boolean function fs.is_dir(path: string) -int lua_fs_is_dir(lua_State* L); -// boolean function fs.is_file(path: string) -int lua_fs_is_file(lua_State* L); -// boolean function create_dir(path: string) -int lua_fs_create_dir(lua_State* L); -// userdata | nil function fs.open_file(path: string) -int lua_fs_open_file(lua_State* L); -// nil function fs.close_file(userdata) -// file dtor -int lua_fs_close_file(lua_State* L); -// string | nil function fs.read_file(userdata, num_bytes: number) -int lua_fs_read_file(lua_State* L); -// nil function fs.seek(userdata, num_bytes: number, [opt] boolean: seek_backward=false) -int lua_fs_seek_file(lua_State* L); -// nil function fs.getpos(userdata) -int lua_fs_getpos_file(lua_State* L); -// nil function fs.write(userdata, string) -int lua_fs_write_file(lua_State* L); -// nil function fs.append(userdata, string) -int lua_fs_append_file(lua_State* L); - -// string function fs.relative(string base, string path) -int lua_fs_relative(lua_State* L); -// string function fs.absolute(string path) -int lua_fs_absolute(lua_State* L); -// string function fs.file_name(string path) -int lua_fs_file_name(lua_State* L); -// string function fs.file_extension(string path) -int lua_fs_file_extension(lua_State* L); -// string function fs.file_directory(string path) -int lua_fs_file_directory(lua_State* L); \ No newline at end of file diff --git a/include/lua_git.h b/include/lua_git.h deleted file mode 100644 index e69de29..0000000 diff --git a/include/lua_parallel.h b/include/lua_parallel.h deleted file mode 100644 index 3be2f4f..0000000 --- a/include/lua_parallel.h +++ /dev/null @@ -1,48 +0,0 @@ -// A lua module that provides multithreadding utilities to lua -#pragma once -#include "lua_stack.h" - -// All functions are sandboxed -int luaopen_parallel_safe(lua_State* L); -// Some functions are not sandboxed -int luaopen_parallel_unsafe(lua_State* L); - -int lua_parallel_create_mutex(lua_State* L); -int lua_parallel_destroy_mutex(lua_State* L); -int lua_parallel_lock_mutex(lua_State* L); -int lua_parallel_unlock_mutex(lua_State* L); - -int lua_parallel_create_promise(lua_State* L); -int lua_parallel_destroy_promise(lua_State* L); -int lua_parallel_await_promise(lua_State* L); -int lua_parallel_fullfilled_promise(lua_State* L); -int lua_parallel_fullfilled_all_promises(lua_State* L); - -struct lua_parallel_thread -{ - // A list of all messages recieved from other threads - lua_stack stack; - // Coroutine lua state pointer - lua_State* L; - // underlying thread object - std::jthread thread; -}; - -// userdata function parallel.create_thread(function fn, ...) -int lua_parallel_create_thread(lua_State* L); -// N/A -int lua_parallel_destroy_thread(lua_State* L); -// nil function parallel.join(userdata thread) -int lua_parallel_join_thread(lua_State* L); -// nil function parallel.request_stop(userdata thread) -int lua_parallel_request_stop(lua_State* L); -// boolean function parallel.stop_requested() -int lua_parallel_stop_requested(lua_State* L); -// nil function parallel.sendmsg(userdata thread, ...) -int lua_parallel_sendmsg_thread(lua_State* L); -// table function parallel.recvmsg(userdata[] | nil filter) -int lua_parallel_recvmsg_thread(lua_State* L); -// number function parallel.recvsize(userdata[] | nil filter) -int lua_parallel_recvsize_thread(lua_State* L); - - diff --git a/include/lua_platform.h b/include/lua_platform.h deleted file mode 100644 index 01c4e22..0000000 --- a/include/lua_platform.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "lua_parallel.h" -// Platform-related code - -// Provided variables; -// platform.os: string -// platform.arch: string -// platform.call_convention: string -// platform.isa_exts: table -int luaopen_platform(lua_State* L); - -// Returns the exit code of the command as well as a string of its stdout -// int, string, string function platform.exec(cmd: string, args: array) -int lua_platform_exec(lua_State* L); - -// Executes a command asynchronosly, returning a promise to the functions return values -// promise, promise, promise function platform.exec_async(cmd: string, args: array) -int lua_platform_exec_async(lua_State* L); - -// Executes a command asynchronosly, calling a callback on its completion with its error code and -// overall stdout and another callback on each token read from its stdout -// function platform.exec_async_cb(cmd: string, -// function on_complete(cmd: string, exit_code: int, overall_output: string), -// function on_stdout(cmd: string, overall_output: string, delta_output: string) -// function on_stderr(cmd: string, overall_output: string, delta_output: string) -// ) -int lua_platform_exec_async_cb(lua_State* L); - - -// Executes the same command up to N times in parallel, iterating through the args provided until all arguments have been used -// array[promise, promise, promise] function platform.exec_parallel_async(cmd: string, N: int, args: array>) -int lua_platform_exec_parallel_async(lua_State* L); - -// array, array, array function platform.exec_parallel(cmd: string, N: int, args: array>) -int lua_platform_exec_parallel(lua_State* L); \ No newline at end of file diff --git a/include/lua_stack.h b/include/lua_stack.h deleted file mode 100644 index c4dc453..0000000 --- a/include/lua_stack.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "includes.h" - - -struct lua_stack -{ - typedef uint8_t type_t; - enum TYPES : type_t - { - NIL, - NUMBER, - BOOLEAN, - INTEGER, - LSTRING, - STRING, - USERDATA, - THREAD, - CFUNCTION, - CCLOSURE, - TABLE - }; - void push_nil (void); - void push_boolean (const bool val); - void push_integer (const lua_Integer val); - void push_number (const lua_Number val); - void push_lstring (const char* beg, const char* end); - void push_lstring (const std::string::iterator& beg, const std::string::iterator& end); - void push_lstring (const char* val, const size_t slen); - void push_string (const char* val); - void push_string (const std::string& val); - void push_lightuserdata (void* p); - void push_thread (lua_State* L); - void push_cfunction (const lua_CFunction f); - void push_cclosure (const lua_CFunction fn, const int num_upvalues); - void push_table (lua_State* L, const int tbl_idx); - - void value_type(const size_t idx); - - uint8_t* m_data; - uint8_t* m_types; - size_t m_size; - size_t m_capacity; -}; \ No newline at end of file diff --git a/include/platform_agnostic.h b/include/platform_agnostic.h deleted file mode 100644 index cf36c1c..0000000 --- a/include/platform_agnostic.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include -#if defined (WIN32) || defined (_WIN32) -FILE* popen(const char* cmd, const char* mode) { return _popen(cmd, mode); } -int pclose(FILE* stream) { return _pclose(stream); }; -#else - -#endif \ No newline at end of file diff --git a/include/simple_string.h b/include/simple_string.h deleted file mode 100644 index 25629c7..0000000 --- a/include/simple_string.h +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include - -class simple_string -{ -public: - simple_string(const simple_string& src); - simple_string& operator =(const simple_string& src); - simple_string(simple_string&& src) noexcept; - simple_string& operator =(simple_string&& src) noexcept; - - simple_string(const char* beg, const char* end); - simple_string(const char* str, const size_t slen); - simple_string(const char* str); - simple_string(const size_t initial_capacity, const char fill_value='\0'); - simple_string(const std::string& str); - simple_string(); - - ~simple_string(void); - - simple_string& append(const char* other); - simple_string& append(const char* beg, const char* end); - simple_string& append(const char* other, const size_t slen); - simple_string& append(const std::string& other); - simple_string& append(const simple_string& other); - simple_string& append(const char x); - - void resize(const size_t new_size); - void expand(const size_t extra_capacity); - void reserve(const size_t new_capacity); - - const char* c_str(void) const noexcept; - char* data(void) noexcept; - size_t size(void) const noexcept; - - char* begin(void) noexcept; - char* end(void) noexcept; - const char* cbegin(void) const noexcept; - const char* cend(void) const noexcept; - - char& operator [](const size_t idx) noexcept; - const char& operator [](const size_t idx) const noexcept; -private: - char* m_data = nullptr; - size_t m_size = 0; - size_t m_capacity = 0; -}; \ No newline at end of file diff --git a/src/dynarray.hpp b/src/dynarray.hpp deleted file mode 100644 index 8d36db8..0000000 --- a/src/dynarray.hpp +++ /dev/null @@ -1,365 +0,0 @@ -#pragma once -#include -#include - -template -class dynarray -{ -public: - dynarray(const dynarray& src); - dynarray& operator =(const dynarray& src); - dynarray(dynarray&& other) noexcept; - dynarray& operator =(dynarray&& other) noexcept; - - dynarray(void); - dynarray(const std::initializer_list& src); - dynarray(const size_t initial_capacity); - - ~dynarray(void); - - T& operator [](const size_t idx) noexcept; - const T& operator [](const size_t idx) const noexcept; - - T* begin(void) noexcept; - const T* begin(void) const noexcept; - const T* cbegin(void) const noexcept; - T* end(void) noexcept; - const T* end(void) const noexcept; - const T* cend(void) const noexcept; - - T* c_str(void) const noexcept; - T* c_array(void) const noexcept; - T* data(void) const noexcept; - size_t size(void) const noexcept; - size_t capacity(void) const noexcept; - - bool is_empty(void) const noexcept; - bool is_nullptr(void) const noexcept; - - void push_back(const T& val); - void push_back(T&& val); - void push_back(const std::initializer_list& vals); - void push_back(const dynarray& vals); - void push_back(const T* vals, const size_t num_vals); - - T&& pop_back(void) noexcept; - - T& front(void) noexcept; - const T& front(void) const noexcept; - T& back(void) noexcept; - const T& back(void) const noexcept; - - void resize(const size_t new_size); - void expand(const size_t extra_capacity); - void reserve(const size_t new_capacity); - void shrink_to_fit(void); -private: - T* m_data = nullptr; - size_t m_capacity = 0; - size_t m_size = 0; -}; - -template -inline dynarray::dynarray(const dynarray& src) -{ - if (m_data == src.m_data) return; - m_size = src.m_size; - m_capacity = src.m_capacity; - m_data = (T*)malloc(src.m_size*sizeof(T)); - if (src.m_data != nullptr) - for (size_t i = 0; i < m_size; ++i) - m_data[i] = src.m_data[i]; -} - -template -inline dynarray& dynarray::operator=(const dynarray& src) -{ - if (m_data == src.m_data) return; - if (m_data != nullptr) delete[] m_data; - m_data = nullptr; - m_size = src.m_size; - m_capacity = src.m_capacity; - m_data = (T*)malloc(src.m_size*sizeof(T)); - if (src.m_data != nullptr) - for (size_t i = 0; i < m_size; ++i) - m_data[i] = src.m_data[i]; - return *this; -} - -template -inline dynarray::dynarray(dynarray&& other) noexcept -{ - if (this == &other) return; - m_data = other.m_data; - m_size = other.m_size; - m_capacity = other.m_capacity; - other.m_size = 0; - other.m_capacity = 0; - other.m_data = nullptr; -} - -template -inline dynarray& dynarray::operator=(dynarray&& other) noexcept -{ - if (this == &other) return *this; - if (m_data != nullptr) delete[] m_data; - m_data = other.m_data; - m_size = other.m_size; - m_capacity = other.m_capacity; - other.m_size = 0; - other.m_capacity = 0; - other.m_data = nullptr; - return *this; -} - -template -inline dynarray::dynarray(void) -{ - m_data = nullptr; - m_size = 0; - m_capacity = 0; -} - -template -inline dynarray::dynarray(const std::initializer_list& src) -{ - m_data = (T*)malloc(src.size()*sizeof(T)); - m_size = src.size(); - m_capacity = src.size(); - if (std::is_trivially_copyable::value) - memcpy(m_data, src.begin(), sizeof(T) * m_size); - else - for (size_t i = 0; i < src.size(); ++i) - m_data[i++] = src.begin()[i]; -} - -template -inline dynarray::dynarray(const size_t initial_capacity) -{ - m_data = (initial_capacity == 0) ? nullptr : (T*)malloc(initial_capacity*sizeof(T)); - m_size = 0; - m_capacity = initial_capacity; -} - -template -inline dynarray::~dynarray(void) -{ - if (m_data != nullptr) - { - if (!std::is_trivially_destructible::value) - { - for (size_t i = 0; i < m_size; ++i) - m_data[i].~T(); - } - free(m_data); - m_data = nullptr; - } -} - -template -inline T& dynarray::operator[](const size_t idx) noexcept -{ return m_data[idx]; } - -template -inline const T& dynarray::operator[](const size_t idx) const noexcept -{ return m_data[idx]; } - -template -inline T* dynarray::begin(void) noexcept -{ return m_data; } - -template -inline const T* dynarray::begin(void) const noexcept -{ return m_data; } - -template -inline const T* dynarray::cbegin(void) const noexcept -{ return m_data; } - -template -inline T* dynarray::end(void) noexcept -{ return m_data == nullptr ? nullptr : (m_data + m_size); } - -template -inline const T* dynarray::end(void) const noexcept -{ return m_data == nullptr ? nullptr : (m_data + m_size); } - -template -inline const T* dynarray::cend(void) const noexcept -{ return m_data == nullptr ? nullptr : (m_data + m_size); } - -template -inline T* dynarray::c_str(void) const noexcept -{ return m_data; } - -template -inline T* dynarray::c_array(void) const noexcept -{ return m_data; } - -template -inline T* dynarray::data(void) const noexcept -{ return m_data; } - -template -inline size_t dynarray::size(void) const noexcept -{ return m_size; } - -template -inline size_t dynarray::capacity(void) const noexcept -{ return m_capacity; } - -template -inline bool dynarray::is_empty(void) const noexcept -{ return m_size == 0; } - -template -inline bool dynarray::is_nullptr(void) const noexcept -{ - return m_data == nullptr || m_capacity == 0; -} - -template -inline void dynarray::push_back(const T& val) -{ - // Double capacity if we can not fit an extra value - if (m_size + 1 > m_capacity) this->expand(m_capacity == 0 ? 32 : m_capacity); - m_data[m_size++] = val; -} - -template -inline void dynarray::push_back(T&& val) -{ - // Double capacity if we can not fit an extra value - if (m_size + 1 > m_capacity) this->expand(m_capacity == 0 ? 32 : m_capacity); - new (m_data + m_size) T(std::move(val)); - m_size++; -} - -template -inline void dynarray::push_back(const std::initializer_list& vals) -{ - const size_t prev_size = m_size; - this->resize(m_size + vals.size()); - if (std::is_trivially_copyable::value) - memcpy(m_data + prev_size, vals.begin(), sizeof(T) * vals.size()); - else - for (size_t i = 0; i < vals.size(); ++i) - m_data[prev_size + i] = vals.begin()[i]; -} - -template -inline void dynarray::push_back(const dynarray& vals) -{ - const size_t prev_size = m_size; - this->resize(m_size + vals.m_size); - if (std::is_trivially_copyable::value) - memcpy(m_data + prev_size, vals.m_data, sizeof(T) * vals.m_size); - else - for (size_t i = 0; i < vals.m_size; ++i) - m_data[prev_size + i] = vals.m_data[i]; -} - -template -inline void dynarray::push_back(const T* vals, const size_t num_vals) -{ - const size_t prev_size = m_size; - this->resize(m_size + num_vals); - if (std::is_trivially_copyable::value) - memcpy(m_data + prev_size, vals, sizeof(T) * num_vals); - else - for (size_t i = 0; i < num_vals; ++i) - m_data[prev_size + i] = vals[i]; -} - -template -inline T&& dynarray::pop_back(void) noexcept -{ - m_size--; - return std::move(m_data[m_size]); -} - -template -inline T& dynarray::front(void) noexcept -{ return *m_data; } - -template -inline const T& dynarray::front(void) const noexcept -{ return *m_data; } - -template -inline T& dynarray::back(void) noexcept -{ return m_data[m_size - 1]; } - -template -inline const T& dynarray::back(void) const noexcept -{ return m_data[m_size-1]; } - -template -inline void dynarray::resize(const size_t new_size) -{ - if (new_size > m_capacity) - this->expand(new_size); - else if (new_size < m_size && std::is_trivially_destructible::value) - for (size_t i = new_size; i < m_size; ++i) - m_data[i].~T(); - m_size = new_size; -} - -template -inline void dynarray::expand(const size_t extra_capacity) -{ this->reserve(m_capacity + extra_capacity); } - -template -inline void dynarray::reserve(const size_t new_capacity) -{ - if (new_capacity <= m_capacity) return; - T* new_data = (T*)malloc(new_capacity*sizeof(T)); - if (new_data == nullptr) return; - if constexpr (std::is_trivially_copyable::value) - memcpy(new_data, m_data, m_size * sizeof(T)); - else if constexpr (std::is_move_assignable::value) - { - for (size_t i = 0; i < m_size; ++i) - new (new_data + i) T(std::move(m_data[i])); - } - else if constexpr (std::is_copy_assignable::value) - { - for (size_t i = 0; i < m_size; ++i) - new (new_data+i) T(m_data[i]); - } - - if (!std::is_trivially_destructible::value) - { - for (size_t i = 0; i < m_size; ++i) - m_data[i].~T(); - } - free(m_data); - - m_data = new_data; - m_capacity = new_capacity; -} - -template -inline void dynarray::shrink_to_fit(void) -{ - if (m_capacity == m_size) return; - if (m_size == 0) - { - delete[] m_data; - m_capacity = 0; - m_data = nullptr; - } - - T* new_data = (T*)malloc(m_size*sizeof(T)); - if (std::is_trivially_copyable::value) - memcpy(new_data, m_data, m_size * sizeof(T)); - else if (std::is_move_assignable::value) - for (size_t i = 0; i < m_size; ++i) - new (new_data+i) T(std::move(m_data[i])); - else if (std::is_copy_assignable::value) - for (size_t i = 0; i < m_size; ++i) - new (new_data+i) T(m_data[i]); - delete[] m_data; - m_data = new_data; - m_capacity = m_size; -} diff --git a/src/lua_dependency_tree.cpp b/src/lua_dependency_tree.cpp deleted file mode 100644 index 9800605..0000000 --- a/src/lua_dependency_tree.cpp +++ /dev/null @@ -1,667 +0,0 @@ -#include "lua_dependency_tree.h" -#include - -dependency_tree::node& dependency_tree::operator[](const ref_t idx) noexcept -{ return m_nodes[idx]; } - -const dependency_tree::node& dependency_tree::operator[](const ref_t idx) const noexcept -{ return m_nodes[idx]; } - -dynarray dependency_tree::get_leaf_nodes(const bool ignore_fulfilled) const -{ - dynarray result; - for (size_t i = 0; i < m_nodes.size(); ++i) - { - if (m_nodes[i].m_num_pending_dependencies == 0 && - (!ignore_fulfilled || m_nodes[i].m_state != FULFILLED)) - result.push_back(i); - } - return result; -} - -dynarray dependency_tree::get_leaf_node_names(const bool ignore_fulfilled) const -{ - dynarray refs = this->get_leaf_nodes(ignore_fulfilled); - dynarray names; - for (const ref_t ref : refs) - names.push_back(m_nodes[ref].m_name); - return names; -} - -dynarray dependency_tree::filter_nodes(const state_cmp_t state_cmp, const ref_t num_dependencies_gt, const bool invert_num_deps) const -{ - dynarray res; - - for (ref_t i = 0; i < m_nodes.size(); ++i) - { - const node& n = m_nodes[i]; - // Ignore nodes that do not match the num_dependencies requirement - if (!((n.m_num_pending_dependencies > num_dependencies_gt) ^ invert_num_deps)) continue; - - bool inc = false; - inc |= (state_cmp & CMP_FULFILED) > 0 && n.m_state == FULFILLED; - inc |= (state_cmp & CMP_FAILED ) > 0 && n.m_state == FAILED; - inc |= (state_cmp & CMP_WORKING ) > 0 && n.m_state == WORKING; - inc |= (state_cmp & CMP_WAITING ) > 0 && n.m_state == WAITING; - if (!inc) continue; - - res.push_back(i); - } - - return res; -} - -// Sets the state of a node -// If the node transitions from a fulfilled state it will recursively update its parents -void dependency_tree::set_node_state(const ref_t ref_node, const state_t new_state) -{ - node& n = m_nodes[ref_node]; - if (n.m_state == new_state) return; - if (new_state == WORKING && n.m_num_pending_dependencies != 0) return; - if (new_state == FULFILLED && n.m_num_pending_dependencies != 0) return; - - - - else if (n.m_state == FULFILLED && new_state != FULFILLED) - { - for (const ref_t ref_p : n.m_dependents) - { - node& p = m_nodes[ref_p]; - p.m_num_pending_dependencies++; - if (p.m_state == FULFILLED) - this->set_node_state(ref_p, WAITING); - } - } - // If changing from a non-resolved state to a resolved state, - // Decrement the node and update its parents - else if (new_state == FULFILLED) - { - for (const ref_t ref_p : n.m_dependents) - { - node& p = m_nodes[ref_p]; - p.m_num_pending_dependencies--; - if (p.m_num_pending_dependencies == 0) - this->set_node_state(ref_p, WORKING); - } - } - - n.m_state = new_state; -} - -void dependency_tree::set_node_state(const char* node, const state_t new_state) -{ this->set_node_state(m_node_name_mapping[node], new_state); } - -dependency_tree::ref_t dependency_tree::add_node(const char* node_name, const dynarray& dependents) -{ - ref_t ret = -1; - // The node already exists, so just add non-duplicating dependents to it - if (m_node_name_mapping.contains(node_name)) - { - ret = m_node_name_mapping[node_name]; - for (const ref_t dep : dependents) - { - if (m_nodes[ret].m_dependents.insert(dep).second) - m_nodes[dep].m_num_pending_dependencies += m_nodes[ret].m_state != FULFILLED; - } - } - // Otherwise create the node and add the dependencies to it - else - { - ret = (ref_t)m_nodes.size(); - node n; - n.m_dependents = std::set(dependents.cbegin(), dependents.cend()); - size_t sl = strlen(node_name); - char* local_name = new char[sl + 1]; - local_name[sl] = '\0'; - memcpy(local_name, node_name, sl); - n.m_name = local_name; - n.m_num_pending_dependencies = 0; - n.m_state = WAITING; - n.m_userdata = 0; - m_nodes.push_back(std::move(n)); - m_node_name_mapping[local_name] = ret; - for (const ref_t dep : dependents) - m_nodes[dep].m_num_pending_dependencies += m_nodes.back().m_state != FULFILLED; - } - return ret; -} - -dependency_tree::ref_t dependency_tree::add_node(const char* node_name, const dynarray& dependents) -{ - dynarray ref_dependents; - for (const char* dep : dependents) - ref_dependents.push_back(m_node_name_mapping[dep]); - return this->add_node(node_name, ref_dependents); -} - -dependency_tree::ref_t dependency_tree::add_node(const char* node_name, const std::initializer_list& dependents) -{ return this->add_node(node_name, dynarray(dependents)); } - -dependency_tree::ref_t dependency_tree::add_node(const char* node_name, const std::initializer_list& dependents) -{ - dynarray ref_dependents; - for (const char* dep : dependents) - ref_dependents.push_back(m_node_name_mapping[dep]); - return this->add_node(node_name, ref_dependents); -} - -dependency_tree::ref_t dependency_tree::add_node(const char* node_name) -{ - if (!m_node_name_mapping.contains(node_name)) - { - ref_t ret = (ref_t)m_nodes.size(); - node n; - n.m_dependents = std::set(); - size_t sl = strlen(node_name); - char* local_name = new char[sl + 1]; - local_name[sl] = '\0'; - memcpy(local_name, node_name, sl); - n.m_name = local_name; - n.m_num_pending_dependencies = 0; - n.m_state = WAITING; - n.m_userdata = 0; - m_nodes.push_back(std::move(n)); - m_node_name_mapping[local_name] = ret; - return ret; - } - return m_node_name_mapping[node_name]; -} - -void dependency_tree::add_node_dependency(const ref_t node, const ref_t dependency) -{ - if (m_nodes[dependency].m_dependents.insert(node).second) - m_nodes[node].m_num_pending_dependencies++; -} - -void dependency_tree::add_node_dependency(const ref_t node, const char* dependency) -{ this->add_node_dependency(node, m_node_name_mapping[dependency]); } - -void dependency_tree::add_node_dependency(const char* node, const ref_t dependency) -{ this->add_node_dependency(m_node_name_mapping[node], dependency); } - -void dependency_tree::add_node_dependency(const char* node, const char* dependency) -{ this->add_node_dependency(m_node_name_mapping[node], m_node_name_mapping[dependency]); } - -void dependency_tree::add_node_dependencies(const ref_t node, const std::initializer_list& dependencies) -{ - for (const ref_t& dep : dependencies) - this->add_node_dependency(node, dep); -} - -void dependency_tree::add_node_dependencies(const ref_t node, const dynarray& dependencies) -{ - for (const ref_t& dep : dependencies) - this->add_node_dependency(node, dep); -} -void dependency_tree::add_node_dependencies(const ref_t node, const std::initializer_list& dependencies) -{ - for (const char* dep : dependencies) - this->add_node_dependency(node, dep); -} - -void dependency_tree::add_node_dependencies(const ref_t node, const dynarray& dependencies) -{ - for (const char* dep : dependencies) - this->add_node_dependency(node, dep); -} - -dependency_tree::~dependency_tree() {} - -dependency_tree::node::node(node&& other) noexcept -{ - this->m_dependents = std::move(other.m_dependents); - this->m_name = other.m_name; - this->m_num_pending_dependencies = other.m_num_pending_dependencies; - this->m_state = other.m_state; - this->m_userdata = other.m_userdata; - other.m_name = nullptr; - other.m_num_pending_dependencies = -1; - other.m_state = -1; - other.m_userdata = -1; -} - -dependency_tree::node& dependency_tree::node::operator=(node&& other) noexcept -{ - if (this == &other) return *this; - - if (this->m_name != nullptr) delete[] m_name; - - this->m_dependents = std::move(other.m_dependents); - this->m_name = other.m_name; - this->m_num_pending_dependencies = other.m_num_pending_dependencies; - this->m_state = other.m_state; - this->m_userdata = other.m_userdata; - other.m_name = nullptr; - other.m_num_pending_dependencies = -1; - other.m_state = -1; - other.m_userdata = -1; - - return *this; -} - -dependency_tree::node::node() -{ - this->m_name = nullptr; - this->m_num_pending_dependencies = -1; - this->m_state = -1; - this->m_userdata = -1; -} - -dependency_tree::node::~node() -{ - if (m_name == nullptr) return; - delete[] m_name; -} - - -int luaopen_dependency_tree(lua_State* L) -{ - luaL_newmetatable(L, "lbs.dependency_tree"); - - lua_pushcfunction(L, lua_dependency_destroy); - lua_setfield(L, -2, "__gc"); - - lua_pushcfunction(L, lua_dependency_add_node); - lua_setfield(L, -2, "add_node"); - lua_pushcfunction(L, lua_dependency_add_dependency); - lua_setfield(L, -2, "add_dependency"); - lua_pushcfunction(L, lua_dependency_add_dependencies); - lua_setfield(L, -2, "add_dependencies"); - lua_pushcfunction(L, lua_dependency_remove_dependency); - lua_setfield(L, -2, "remove_dependency"); - lua_pushcfunction(L, lua_dependency_remove_dependencies); - lua_setfield(L, -2, "remove_dependencies"); - lua_pushcfunction(L, lua_dependency_get_leafs); - lua_setfield(L, -2, "get_leafs"); - lua_pushcfunction(L, lua_dependency_match_nodes); - lua_setfield(L, -2, "match"); - lua_pushcfunction(L, lua_dependency_set_node_state); - lua_setfield(L, -2, "set_state"); - lua_pushcfunction(L, lua_dependency_get_node_state); - lua_setfield(L, -2, "get_state"); - lua_pushcfunction(L, lua_dependency_get_node_userval); - lua_setfield(L, -2, "get_userval"); - lua_pushcfunction(L, lua_dependency_set_node_userval); - lua_setfield(L, -2, "set_userval"); - lua_pushcfunction(L, lua_dependency_get_node_name); - lua_setfield(L, -2, "get_name"); - lua_pushcfunction(L, lua_dependency_get_node); - lua_setfield(L, -2, "get_node"); - - //lua_pushcfunction(L, lua_dependency_index); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - - - lua_newtable(L); - - lua_pushcfunction(L, lua_dependency_create); - lua_setfield(L, -2, "create"); - lua_pushcfunction(L, lua_dependency_add_node); - lua_setfield(L, -2, "add_node"); - lua_pushcfunction(L, lua_dependency_add_dependency); - lua_setfield(L, -2, "add_dependency"); - lua_pushcfunction(L, lua_dependency_add_dependencies); - lua_setfield(L, -2, "add_dependencies"); - lua_pushcfunction(L, lua_dependency_remove_dependency); - lua_setfield(L, -2, "remove_dependency"); - lua_pushcfunction(L, lua_dependency_remove_dependencies); - lua_setfield(L, -2, "remove_dependencies"); - lua_pushcfunction(L, lua_dependency_get_leafs); - lua_setfield(L, -2, "get_leafs"); - lua_pushcfunction(L, lua_dependency_match_nodes); - lua_setfield(L, -2, "match"); - lua_pushcfunction(L, lua_dependency_set_node_state); - lua_setfield(L, -2, "set_state"); - lua_pushcfunction(L, lua_dependency_get_node_state); - lua_setfield(L, -2, "get_state"); - lua_pushcfunction(L, lua_dependency_get_node_userval); - lua_setfield(L, -2, "get_userval"); - lua_pushcfunction(L, lua_dependency_set_node_userval); - lua_setfield(L, -2, "set_userval"); - lua_pushcfunction(L, lua_dependency_get_node_name); - lua_setfield(L, -2, "get_name"); - lua_pushcfunction(L, lua_dependency_get_node); - lua_setfield(L, -2, "get_node"); - - lua_pushvalue(L, -1); - lua_setfield(L, LUA_GLOBALSINDEX, "dependency_tree"); - return 1; -} - -dependency_tree* get_lua_dependency_tree(lua_State* L, int idx) -{ return (dependency_tree*)luaL_checkudata(L, idx, "lbs.dependency_tree"); } - -dependency_tree::ref_t get_lua_dependency_ref(dependency_tree* tree, lua_State* L, int idx) -{ - if (lua_isnumber(L, idx)) - { - if (lua_tonumber(L, idx) >= tree->m_nodes.size()) return -1; - return lua_tonumber(L, idx); - } - else if (lua_isstring(L, idx)) - { - const char* name = lua_tostring(L, idx); - if (tree->m_node_name_mapping.contains(name)) return tree->m_node_name_mapping[name]; - return -1; - } - return -1; -} - -int lua_dependency_create(lua_State* L) -{ - dependency_tree* tree = (dependency_tree*)lua_newuserdata(L, sizeof(dependency_tree)); - new (tree) dependency_tree(); - luaL_getmetatable(L, "lbs.dependency_tree"); - lua_setmetatable(L, -2); - return 1; -} - -int lua_dependency_destroy(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, -1); - if (tree == nullptr) return 0; - tree->~dependency_tree(); - return 0; -} - -int lua_dependency_add_node(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING, 2, "Expected first argument to be a string of the dependency nodes name"); - int t = lua_type(L, 3); - luaL_argcheck(L, lua_type(L, 3) == LUA_TTABLE || lua_type(L, 3) <= LUA_TNIL, 3, "Expected second argument to be a table of the names or references of the dependents or nil"); - - const char* node_name = lua_tostring(L, 2); - - if (lua_type(L, 3) == LUA_TTABLE) - { - static dynarray dependent_nodes; - dependent_nodes.resize(0); - dependent_nodes.reserve(lua_objlen(L, 3)); - for (size_t i = 1; i < lua_objlen(L, 3); ++i) - { - lua_rawgeti(L, 3, i); - if (lua_type(L, -1) != LUA_TSTRING && lua_type(L, -1) != LUA_TNUMBER) - return luaL_error(L, "Expected value %d in second argument to be a string or reference, not %s", i, lua_typename(L, lua_type(L, -1))); - dependency_tree::ref_t n = get_lua_dependency_ref(tree, L, -1); - if (n == -1) - return luaL_error(L, "Expected value %d in second argument to be a valid node name or reference", i); - dependent_nodes.push_back(n); - lua_pop(L, 1); - } - lua_pushinteger(L, tree->add_node(node_name, dependent_nodes)); - } - else - lua_pushinteger(L, tree->add_node(node_name)); - - return 1; -} - -int lua_dependency_add_dependency(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING || lua_type(L, 2) == LUA_TNUMBER, 2, "Expected first argument to be a string of the dependency nodes name or a reference to it"); - luaL_argcheck(L, lua_type(L, 3) == LUA_TSTRING || lua_type(L, 3) == LUA_TNUMBER, 3, "Expected second argument to be a string of the dependent node's name or a reference to it"); - dependency_tree::ref_t dependency = get_lua_dependency_ref(tree, L, 2); - if (dependency == -1) - return luaL_error(L, "Expected first argument to be a valid name or reference to a node"); - dependency_tree::ref_t dependent = get_lua_dependency_ref(tree, L, 3); - if (dependent == -1) - return luaL_error(L, "Expected second argument to be a valid name or reference to a node"); - tree->add_node_dependency(dependency, dependent); - return 0; -} - -int lua_dependency_remove_dependency(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t dependency = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, dependency != -1, 2, "Expected first argument to be a valid node name or reference"); - dependency_tree::ref_t dependent = get_lua_dependency_ref(tree, L, 3); - luaL_argcheck(L, dependent != -1, 3, "Expected second argument to be a valid node name or reference"); - tree->m_nodes[dependent].m_dependents.erase(dependency); - return 0; -} - -int lua_dependency_add_dependencies(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t dependency = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, dependency != -1, 1, "Expected first argument to be a valid name or reference to a node"); - - static dynarray dependents; - dependents.resize(0); // Clear prior values - dependents.reserve(lua_gettop(L)); // This is approx. equal to top-2 - for (size_t idx = 3; idx < lua_gettop(L); ++idx) - { - if (lua_type(L, idx) == LUA_TTABLE) - { - int tbl_len = lua_objlen(L, idx); - for (size_t i = 1; i < tbl_len; ++i) - { - lua_rawgeti(L, idx, i); - dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, idx); - if (ref == -1) - return luaL_error(L, "Expected argument %d[%d] to be a valid name or reference of a node", idx - 2, i); - dependents.push_back(ref); - lua_pop(L, 1); - } - } - else - { - dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, idx); - if (ref == -1) - return luaL_error(L, "Expected argument %d to be a valid name or reference of a node", idx-2); - dependents.push_back(ref); - } - } - - tree->add_node_dependencies(dependency, dependents); - return 0; -} - -int lua_dependency_remove_dependencies(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t dependency = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, dependency != -1, 2, "Expected first argument to be a valid node name or reference"); - - for (size_t idx = 3; idx < lua_gettop(L); ++idx) - { - if (lua_type(L, idx) == LUA_TTABLE) - { - int tbl_len = lua_objlen(L, 3); - for (int i = 1; i < tbl_len; ++i) - { - lua_rawgeti(L, idx, i); - dependency_tree::ref_t dependent = get_lua_dependency_ref(tree, L, -1); - if (dependent != -1) - return luaL_error(L, "Expected argument %d[%d] to be a valid name or reference to a node", idx-2,i); - tree->m_nodes[dependent].m_dependents.erase(dependency); - lua_pop(L, 1); - } - } - else - { - const dependency_tree::ref_t dependent = get_lua_dependency_ref(tree, L, idx); - if (dependent != -1) - return luaL_error(L, "Expected argument %d to be a valid name or reference to a node", idx - 2); - tree->m_nodes[dependent].m_dependents.erase(dependency); - } - } - - return 0; -} - -int lua_dependency_get_leafs(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dynarray leafs; - if (lua_isboolean(L, 2) && (lua_toboolean(L, 2) > 0)) - leafs = tree->get_leaf_nodes(); - else - leafs = tree->get_leaf_nodes(false); - - lua_newtable(L); - for (const dependency_tree::ref_t leaf : leafs) - { - lua_pushinteger(L, leaf); - lua_rawseti(L, -2, lua_objlen(L, -2) + 1); - } - - return 1; -} - -int lua_dependency_match_nodes(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - luaL_argcheck(L, lua_type(L, 2) == LUA_TNUMBER || lua_type(L, 2) <= LUA_TNIL, 2, "Expected first argument to be a number or nil. This is what states need to be true\n\tFulfiled = 1\n\tFailed = 2\n\tWorking = 4\n\tWaiting = 8"); - luaL_argcheck(L, lua_type(L, 3) == LUA_TNUMBER || lua_type(L, 3) <= LUA_TNIL, 3, "Expected second argument to be a number or nil. This is the least number of pending dependencies a node needs to have to pass"); - luaL_argcheck(L, lua_type(L, 4) == LUA_TBOOLEAN || lua_type(L, 4) <= LUA_TNIL, 4, "Expected third argument to be a boolean or nil. This controls whether the number of pending dependencies is greater or less-equal"); - - dynarray matches = tree->filter_nodes( - lua_tointeger(L, 2) & 0b1111, - lua_tointeger(L, 3), - lua_toboolean(L, 3) > 0 - ); - - lua_newtable(L); - for (const dependency_tree::ref_t match : matches) - { - lua_pushinteger(L, match); - lua_rawseti(L, -2, lua_objlen(L, -2)+1); - } - - return 1; -} - -int lua_dependency_set_node_state(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t node = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, node != -1, 2, "Expected first argument to be a valid node name or reference"); - luaL_argcheck(L, lua_type(L, 3) == LUA_TNUMBER || lua_type(L, 3) == LUA_TSTRING, 3, "Expected second argument to be a number or string of the state\n\t0 = FULFILLED\n\t1 = FAILED\n\t2 = WAITING\n\t3 = WORKING"); - - uint8_t new_state; - if (lua_type(L, 3) == LUA_TNUMBER) - new_state = lua_tointeger(L, 3) & 0b11; - else - { - const char* state_name = lua_tostring(L, 3); - if (strcmp(state_name, "FULFILLED") == 0 || strcmp(state_name, "fulfilled") == 0) - new_state = dependency_tree::FULFILLED; - else if (strcmp(state_name, "FAILED") == 0 || strcmp(state_name, "failed") == 0) - new_state = dependency_tree::FAILED; - else if (strcmp(state_name, "WAITING") == 0 || strcmp(state_name, "waiting") == 0) - new_state = dependency_tree::WAITING; - else if (strcmp(state_name, "WORKING") == 0 || strcmp(state_name, "working") == 0) - new_state = dependency_tree::WORKING; - else return luaL_error(L, "Expected seconda argument to be fulfilled, failed, waiting or working not %s", state_name); - } - - tree->set_node_state(node, new_state); - return 0; -} - -int lua_dependency_get_node_userval(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, ref != -1, 2, "Expected first argument to be a valid node name or reference"); - - lua_pushinteger(L, tree->m_nodes[ref].m_userdata); - - return 1; -} - -int lua_dependency_set_node_userval(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, ref != -1, 2, "Expected first argument to be a valid node name or reference"); - luaL_argcheck(L, lua_type(L, 3) == LUA_TNUMBER, 3, "Expected second argument to be a 30-bit number"); - - tree->m_nodes[ref].m_userdata = lua_tointeger(L, 3) & 0x3FFFFFFF; - - return 0; -} - -int lua_dependency_get_node_state(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, ref != -1, 2, "Expected first argument to be a valid node name or reference"); - - const dependency_tree::node& node = tree->m_nodes[ref]; - if (node.m_state == dependency_tree::FULFILLED) lua_pushstring(L, "fulfilled"); - else if (node.m_state == dependency_tree::FAILED) lua_pushstring(L, "failed"); - else if (node.m_state == dependency_tree::WAITING) lua_pushstring(L, "waiting"); - else if (node.m_state == dependency_tree::WORKING) lua_pushstring(L, "working"); - - return 1; -} - -int lua_dependency_get_node_name(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, ref != -1, 2, "Expected first argument to be a valid node name or reference"); - - lua_pushstring(L, tree->m_nodes[ref].m_name); - - return 1; -} - -int lua_dependency_get_node(lua_State* L) -{ - dependency_tree* tree = get_lua_dependency_tree(L, 1); - luaL_argcheck(L, tree != nullptr, 1, "Expected implicit argument to be userdata"); - const dependency_tree::ref_t ref = get_lua_dependency_ref(tree, L, 2); - luaL_argcheck(L, ref != -1, 2, "Expected first argument to be a valid node name or reference"); - - const dependency_tree::node& node = tree->m_nodes[ref]; - lua_newtable(L); - - lua_pushstring(L, "name"); - lua_pushstring(L, node.m_name); - lua_settable(L, -3); - - lua_pushstring(L, "pending_dependencies"); - lua_pushinteger(L, node.m_num_pending_dependencies); - lua_settable(L, -3); - - lua_pushstring(L, "state"); - if (node.m_state == dependency_tree::FULFILLED) lua_pushstring(L, "fulfilled"); - else if (node.m_state == dependency_tree::FAILED) lua_pushstring(L, "failed"); - else if (node.m_state == dependency_tree::WAITING) lua_pushstring(L, "waiting"); - else if (node.m_state == dependency_tree::WORKING) lua_pushstring(L, "working"); - lua_settable(L, -3); - - lua_pushstring(L, "userdata"); - lua_pushinteger(L, node.m_userdata); - lua_settable(L, -3); - - lua_pushstring(L, "dependents"); - lua_newtable(L); - for (const dependency_tree::ref_t dependent : node.m_dependents) - { - lua_pushinteger(L, dependent); - lua_rawseti(L, -2, lua_objlen(L, -2)); - } - lua_settable(L, -3); - - return 1; -} diff --git a/src/lua_filesystem.cpp b/src/lua_filesystem.cpp deleted file mode 100644 index e2f89ba..0000000 --- a/src/lua_filesystem.cpp +++ /dev/null @@ -1,453 +0,0 @@ -#include "lua_filesystem.h" -#include -#include - -int luaopen_filesystem(lua_State* L) -{ - luaL_newmetatable(L, "fs.file_handle"); - - // Push iterator state metatables - luaL_newmetatable(L, "fs.stdlibcpp.filesystem.directory_iterator"); - lua_pushcfunction(L, lua_fs_foreach_dir_dtor); - lua_setfield(L, -2, "__gc"); - - luaL_newmetatable(L, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); - lua_pushcfunction(L, lua_fs_forall_dir_dtor); - lua_setfield(L, -2, "__gc"); - - - // Push functions - lua_newtable(L); - - lua_pushcfunction(L, lua_fs_is_newer); - lua_setfield(L, -2, "is_newer"); - - lua_pushcfunction(L, lua_fs_filter_newer); - lua_setfield(L, -2, "filter_newer"); - - lua_pushcfunction(L, lua_fs_absolute); - lua_setfield(L, -2, "absolute"); - - lua_pushcfunction(L, lua_fs_create_dir); - lua_setfield(L, -2, "create_dir"); - - lua_pushcfunction(L, lua_fs_exists); - lua_setfield(L, -2, "exists"); - - lua_pushcfunction(L, lua_fs_file_directory); - lua_setfield(L, -2, "dir"); - - lua_pushcfunction(L, lua_fs_file_extension); - lua_setfield(L, -2, "extension"); - - lua_pushcfunction(L, lua_fs_file_name); - lua_setfield(L, -2, "file_name"); - - lua_pushcfunction(L, lua_fs_forall_dir); - lua_setfield(L, -2, "forall"); - - lua_pushcfunction(L, lua_fs_foreach_dir); - lua_setfield(L, -2, "foreach"); - - lua_pushcfunction(L, lua_fs_is_dir); - lua_setfield(L, -2, "is_dir"); - - lua_pushcfunction(L, lua_fs_is_file); - lua_setfield(L, -2, "is_file"); - - lua_pushcfunction(L, lua_fs_last_modified); - lua_setfield(L, -2, "last_modified"); - - lua_pushcfunction(L, lua_fs_list_dir); - lua_setfield(L, -2, "list_dir"); - - lua_pushcfunction(L, lua_fs_list_alldirs); - lua_setfield(L, -2, "list_alldirs"); - - lua_pushcfunction(L, lua_fs_relative); - lua_setfield(L, -2, "relative_to"); - - lua_pushvalue(L, -1); - lua_setfield(L, LUA_GLOBALSINDEX, "fs"); - - return 1; -} - -int lua_fs_list_dir(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path to make the second argument relative to"); - const char* fpath = lua_tostring(L, 1); - lua_newtable(L); - uint32_t i = 1; - for (const std::filesystem::path& p : std::filesystem::directory_iterator(fpath)) - { - const std::string x = p.string(); - lua_pushlstring(L, x.c_str(), x.size()); - lua_rawseti(L, -2, i); - } - return 1; -} - -int lua_fs_list_alldirs(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path to make the second argument relative to"); - const char* fpath = lua_tostring(L, 1); - lua_newtable(L); - uint32_t i = 1; - for (const std::filesystem::path& p : std::filesystem::recursive_directory_iterator(fpath)) - { - const std::string x = p.string(); - lua_pushlstring(L, x.c_str(), x.size()); - lua_rawseti(L, -2, i); - i++; - } - return 1; -} - -int lua_fs_foreach_dir(lua_State* L) -{ - try { - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path"); - const char* path = lua_tostring(L, 1); - - void* ud = lua_newuserdata(L, sizeof(std::filesystem::directory_iterator)); - new (ud) std::filesystem::directory_iterator(path); - } catch (const std::exception& e) - { return luaL_error(L, "%s:%d: An exception occured creating fs.foreach iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - - luaL_getmetatable(L, "fs.stdlibcpp.filesystem.directory_iterator"); - lua_setmetatable(L, -2); - lua_pushcclosure(L, lua_fs_foreach_dir_next, 1); - return 1; -} - -int lua_fs_forall_dir(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path"); - const char* path = lua_tostring(L, 1); - - try { - void* ud = lua_newuserdata(L, sizeof(std::filesystem::recursive_directory_iterator)); - new (ud) std::filesystem::recursive_directory_iterator(path); - } catch (const std::exception& e) - { return luaL_error(L, "%s:%d: An exception occured creating fs.forall iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - - luaL_getmetatable(L, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); - lua_setmetatable(L, -2); - lua_pushcclosure(L, lua_fs_forall_dir_next, 1); - return 1; -} - -int lua_fs_foreach_dir_next(lua_State* L) -{ - try { - int idx = lua_upvalueindex(1); - luaL_argcheck(L, lua_type(L, idx) == LUA_TUSERDATA, 1, "Expected first argument to fs.foreach_dir_next to be userdata"); - void* ud = luaL_checkudata(L, idx, "fs.stdlibcpp.filesystem.directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::directory_iterator"); - std::filesystem::directory_iterator& x = *(std::filesystem::directory_iterator*)ud; - if (x._At_end()) - return 0; - std::string p = (*x).path().string(); - lua_pushlstring(L, p.c_str(), p.size()); - x++; - } catch (const std::exception& e) - { return luaL_error(L, "%s:%d: An exception occured iterating fs.foreach\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - return 1; -} - -int lua_fs_forall_dir_next(lua_State* L) -{ - try { - int idx = lua_upvalueindex(1); - luaL_argcheck(L, lua_type(L, idx) == LUA_TUSERDATA, 1, "Expected first argument to fs.forall_dir_next to be userdata"); - void* ud = luaL_checkudata(L, idx, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::recursive_directory_iterator"); - std::filesystem::recursive_directory_iterator& x = *(std::filesystem::recursive_directory_iterator*)ud; - if (x == std::filesystem::recursive_directory_iterator{}) - return 0; - std::string p = (*x).path().string(); - lua_pushlstring(L, p.c_str(), p.size()); - x++; - } catch (const std::exception& e) - { return luaL_error(L, "%s:%d: An exception occured iterating fs.forall\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - return 1; -} - -int lua_fs_foreach_dir_dtor(lua_State* L) -{ - try { - luaL_argcheck(L, lua_type(L, 1) == LUA_TUSERDATA, 1, "Expected first argument to fs.foreach_dir_next to be userdata"); - void* ud = luaL_checkudata(L, 1, "fs.stdlibcpp.filesystem.directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::directory_iterator"); - std::filesystem::directory_iterator& x = *(std::filesystem::directory_iterator*)ud; - x.~directory_iterator(); - } catch (const std::exception& e) - { return luaL_error(L, "%s:%d: An exception occured destroying fs.foreach iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - return 0; -} - -int lua_fs_forall_dir_dtor(lua_State* L) -{ - try { - luaL_argcheck(L, lua_type(L, 1) == LUA_TUSERDATA, 1, "Expected first argument to fs.forall_dir_next to be userdata"); - void* ud = luaL_checkudata(L, 1, "fs.stdlibcpp.filesystem.recursive_directory_iterator"); - luaL_argcheck(L, ud != nullptr, 1, "Expected first argument's userdata type to be a std::filesystem::recursive_directory_iterator"); - std::filesystem::recursive_directory_iterator& x = *(std::filesystem::recursive_directory_iterator*)ud; - x.~recursive_directory_iterator(); - } catch (const std::exception& e) - { return luaL_error(L, "%s:%d: An exception occured destroying fs.forall iterator/generator\n\t%s\n", __FUNCTION__, __LINE__, e.what()); } - return 0; -} - -int lua_fs_relative(lua_State* L) -{ - try { - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a path to make the second argument relative to"); - luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING, 2, "Expected second argument to be a string representing a full file path"); - const std::string f = std::filesystem::relative(std::filesystem::path(lua_tostring(L, 1)), std::filesystem::path(lua_tostring(L, 2))).string(); - lua_pushlstring(L, f.c_str(), f.size()); - return 1; - } catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } -} - -int lua_fs_absolute(lua_State* L) -{ - try { - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - const std::string f = std::filesystem::absolute(std::filesystem::path(lua_tostring(L, 1))).string(); - lua_pushlstring(L, f.c_str(), f.size()); - return 1; - } catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } -} - -int lua_fs_file_name(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - const std::string f = std::filesystem::path(lua_tostring(L, 1)).filename().string(); - lua_pushlstring(L, f.c_str(), f.size()); - return 1; - } catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } -} - -int lua_fs_file_extension(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - const std::string f = std::filesystem::path(lua_tostring(L, 1)).extension().string(); - lua_pushlstring(L, f.c_str(), f.size()); - } catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 1; -} - -int lua_fs_file_directory(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - const std::string f = std::filesystem::path(lua_tostring(L, 1)).remove_filename().string(); - lua_pushlstring(L, f.c_str(), f.size()); - return 1; - } catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 0; -} - -int lua_fs_is_newer(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - const char* test_file = lua_tostring(L, 1); - if (!std::filesystem::exists(test_file)) - { - lua_pushboolean(L, false); - return 1; - } - - if (lua_type(L, 2) == LUA_TTABLE) - { - size_t tbl_len = lua_objlen(L, 2); - lua_newtable(L); - for (size_t i = 1; i <= tbl_len; ++i) - { - lua_rawgeti(L, 2, i); - if (lua_type(L, -1) != LUA_TSTRING) - return luaL_error(L, "Expected second argument at index %llu to be a string, not %s\n", - i, lua_typename(L, lua_type(L, -1))); - const char* target = lua_tostring(L, 2); - lua_pushboolean(L, - std::filesystem::last_write_time(test_file) > std::filesystem::last_write_time(target)); - lua_rawseti(L, -2, i); - lua_pop(L, 1); - } - return 1; - } - else if (lua_type(L, 2) == LUA_TSTRING) - { - const char* target = lua_tostring(L, 2); - if (!std::filesystem::exists(target)) - { - lua_pushboolean(L, true); - return 1; - } - lua_pushboolean(L, - std::filesystem::last_write_time(test_file) > std::filesystem::last_write_time(target)); - return 1; - } - else return luaL_error(L, "Expected second argument to be a string or table of strings"); -} - -int lua_fs_filter_newer(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - const char* test_file = lua_tostring(L, 1); - if (!std::filesystem::exists(test_file)) - { - lua_pushnil(L); - return 1; - } - - if (lua_type(L, 2) == LUA_TTABLE) - { - size_t tbl_len = lua_objlen(L, 2); - lua_newtable(L); - for (size_t i = 1; i <= tbl_len; ++i) - { - lua_rawgeti(L, 2, i); - if (lua_type(L, -1) != LUA_TSTRING) - return luaL_error(L, "Expected second argument at index %llu to be a string, not %s\n", - i, lua_typename(L, lua_type(L, -1))); - const char* target = lua_tostring(L, 2); - if (std::filesystem::last_write_time(test_file) > std::filesystem::last_write_time(target)) - { - lua_pushvalue(L, -1); - lua_rawseti(L, -2, lua_objlen(L, -2)+1); - } - lua_pop(L, 1); - } - return 1; - } - else if (lua_type(L, 2) == LUA_TSTRING) - { - const char* target = lua_tostring(L, 2); - if (!std::filesystem::exists(target)) - { - lua_pushvalue(L, 2); - return 1; - } - - if (std::filesystem::last_write_time(test_file) > std::filesystem::last_write_time(target)) - lua_pushvalue(L, 2); - else lua_pushnil(L); - - return 1; - } - else return luaL_error(L, "Expected second argument to be a string or table of strings"); -} - -int lua_fs_last_modified(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - const uint64_t file_last_write = std::chrono::duration_cast( - std::chrono::clock_cast( - std::filesystem::last_write_time(lua_tostring(L, 1)) - ).time_since_epoch() - ).count(); - lua_pushinteger(L, file_last_write); - return 1; - } catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 0; -} - -int lua_fs_exists(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - lua_pushboolean(L, std::filesystem::exists(lua_tostring(L, 1))); - return 1; - } - catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 0; -} - -int lua_fs_is_dir(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - lua_pushboolean(L, std::filesystem::is_directory(lua_tostring(L, 1))); - return 1; - } - catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 0; -} - -int lua_fs_is_file(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - lua_pushboolean(L, std::filesystem::is_regular_file(lua_tostring(L, 1))); - return 1; - } - catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 0; -} - -int lua_fs_create_dir(lua_State* L) -{ - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a full file path"); - try { - lua_pushboolean(L, std::filesystem::create_directories(lua_tostring(L, 1))); - return 1; - } - catch (const std::exception& e) - { - lua_pushnil(L); - lua_pushstring(L, e.what()); - return 2; - } - return 0; -} diff --git a/src/lua_platform.cpp b/src/lua_platform.cpp deleted file mode 100644 index b04e97c..0000000 --- a/src/lua_platform.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include "lua_platform.h" -#include "platform_agnostic.h" -#include "dynarray.hpp" -#include "mutex" -#include -#include "simple_string.h" -#include "uniproc.h" - -int luaopen_platform(lua_State* L) -{ - lua_newtable(L); - - lua_pushcfunction(L, lua_platform_exec); - lua_setfield(L, -2, "exec"); - lua_pushcfunction(L, lua_platform_exec_parallel); - lua_setfield(L, -2, "exec_parallel"); - - lua_pushvalue(L, -1); - lua_setfield(L, LUA_GLOBALSINDEX, "platform"); - return 1; -} - -int lua_platform_exec(lua_State* L) -{ - luaL_argcheck(L, lua_isstring(L, 1), 1, "Expected first argument to be a string"); - luaL_argcheck(L, lua_istable(L, 2), 2, "Expected second argument to be a table of strings"); - - size_t nargs = lua_objlen(L, 2); - const char** argv = (const char**)malloc(nargs * sizeof(const char*)); - for (size_t i = 0; i < nargs; ++i) - { - lua_rawgeti(L, 2, i+1); - if (lua_type(L, -1) != LUA_TSTRING) - return luaL_error(L, "Expected all values in argument table to be a string. Index %d was a %s", i+1, lua_typename(L, lua_type(L, -1))); - argv[i] = lua_tostring(L, -1); - } - - int retcode = 0; - std::string std_out; - std::string std_err; - char buf[64]; - - uniproc_process p = uniproc_create_process(lua_tostring(L, 1), nargs, argv); - if (uniproc_is_process_null(&p)) - { - lua_pushnil(L); - lua_pushstring(L, "uniproc: failed to create process"); - return 2; - } - uniproc_await_processes(&p, &retcode, 1); - - while (fgets(buf, sizeof(buf), p.out) != NULL) - std_out.append(buf); - while (fgets(buf, sizeof(buf), p.err) != NULL) - std_err.append(buf); - - uniproc_close_process(&p); - free(argv); - - lua_pushinteger(L, retcode); - lua_pushlstring(L, std_out.c_str(), std_out.size()); - lua_pushlstring(L, std_err.c_str(), std_err.size()); - return 3; -} - -int lua_platform_exec_parallel(lua_State* L) -{ - try { - luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "Expected first argument to be a string representing a command"); - luaL_argcheck(L, lua_type(L, 2) == LUA_TNUMBER, 2, "Expected second argument to be an integer representing the maximum number of parallel jobs to start"); - luaL_argcheck(L, lua_type(L, 3) == LUA_TTABLE, 3, "Expected third argument to be a table of table of strings representing the arguments"); - const char* cmd = (lua_tostring(L, 1)); - const size_t max_parallel = lua_tointeger(L, 2); - const size_t num_cmds = lua_objlen(L, 3); - - uniproc_process* workers = nullptr; - int* retcodes = nullptr; - size_t* num_args = nullptr; - const char*** args = nullptr; - std::vector std_outs; - std::vector std_errs; - - try { - num_args = (size_t*)malloc(num_cmds * sizeof(size_t)); - memset(num_args, 0, sizeof(size_t) * num_cmds); - args = (const char***)malloc(num_cmds * sizeof(const char**)); - - // Generate the command stack from lua arguments - for (size_t i = 0; i < num_cmds; ++i) - { - lua_rawgeti(L, 3, i + 1); - if (lua_istable(L, -1)) - { - const size_t tbl_num_args = lua_objlen(L, -1); - num_args[i] = tbl_num_args; - args[i] = (const char**)malloc(tbl_num_args * sizeof(const char*)); - for (size_t j = 0; j < tbl_num_args; ++j) - { - lua_rawgeti(L, -1, j + 1); - if (!lua_isstring(L, -1)) - return luaL_error(L, "Expected program argument to be a string. args[%d][%d] was a %s, not a string!\n", i, j, lua_typename(L, lua_type(L, -1))); - args[i][j] = lua_tostring(L, -1); - lua_pop(L, 1); - } - } - else if (lua_type(L, -1) == LUA_TSTRING) - { - num_args[i] = 1; - args[i] = (const char**)malloc(1 * sizeof(const char*)); - args[i][0] = lua_tostring(L, -1); - } - else - return luaL_error(L, "Expected a table of program arguments. args[%d] was a %s, not a table!\n", i, lua_typename(L, lua_type(L, -1))); - lua_pop(L, 1); - } - - workers = (uniproc_process*)malloc(max_parallel * sizeof(uniproc_process)); - uniproc_nullify_processes(workers, max_parallel); - retcodes = (int*)malloc(num_cmds * sizeof(int)); - memset(retcodes, 0, num_cmds); - - std_outs.resize(num_cmds, ""); - std_errs.resize(num_cmds, ""); - - } - catch (const std::exception& e) { - fprintf(stderr, "%s:%d: Exception occured in preparation for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); - return luaL_error(L, "%s:%d: Exception occured in preparation for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); - } - - size_t cmd_idx = 0; - while (cmd_idx < num_cmds || !uniproc_are_processes_finished(workers, max_parallel)) - { - try { - for (uniproc_process* p = workers; p != (workers + max_parallel); ++p) - { - // Check and handle a worker if it has completed - if (!uniproc_is_process_null(p) && uniproc_are_processes_finished(p, 1)) - { - char buf[64]; - // Read the std. streams into the output vectors - while (fgets(buf, sizeof(buf), p->out) != NULL) - std_outs[p->userdata].append(buf); - while (fgets(buf, sizeof(buf), p->err) != NULL) - std_errs[p->userdata].append(buf); - // Add the process return code to retcode array - uniproc_await_processes(p, retcodes + p->userdata, 1); - // Close the process and zero it - uniproc_close_process(p); - } - // If a worker is null and there is more jobs to complete - // Create a new process - // Is a while loop to handle the possibility that process creation fails - while (uniproc_is_process_null(p) && cmd_idx < num_cmds) - { - // Create process - *p = uniproc_create_process(cmd, num_args[cmd_idx], args[cmd_idx]); - p->userdata = cmd_idx; - cmd_idx++; - - // If we failed to create the process, set the output for it to an error value - if (uniproc_is_process_null(p)) - { - std_outs[p->userdata] = "uniproc: failed to create process"; - std_errs[p->userdata] = "uniproc: failed to create process"; - retcodes[p->userdata] = -1; - } - } - } - // Await a process completing before trying to iterate again - // Prevents spinning the CPU - uniproc_await_any_processes(workers, max_parallel); - } - catch (const std::exception& e) { - fprintf(stderr, "%s:%d: Exception occured in parallel execution for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); - return luaL_error(L, "%s:%d: Exception occured in parallel execution for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); - } - } - - for (size_t i = 0; i < num_cmds; ++i) - free(args[i]); - free(num_args); - free(args); - // Don't need to close processes as that is handled in the command loop - free(workers); - - - - // Join thread results together and push them to lua stack - lua_newtable(L); // rc - lua_newtable(L); // stdout - lua_newtable(L); // stderr - for (size_t i = 0; i < num_cmds; ++i) - { - lua_pushinteger(L, retcodes[i]); - lua_rawseti(L, -4, i + 1); - lua_pushlstring(L, std_outs[i].c_str(), std_outs[i].size()); - lua_rawseti(L, -3, i + 1); - lua_pushlstring(L, std_errs[i].c_str(), std_errs[i].size()); - lua_rawseti(L, -2, i + 1); - } - - return 3; - } - catch (const std::exception& e) - { - fprintf(stderr, "%s:%d: Exception occured in cleanup and result handling for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); - return luaL_error(L, "%s:%d: Exception occured in cleanup and result handling for fs.parallel_exec(...)\n\t%s\n", __FUNCTION__, __LINE__, e.what()); - } -} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..05a86d7 --- /dev/null +++ b/src/main.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + printf("Hello, World!\n"); + return 0; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index f0bf15f..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "lua_dependency_tree.h" -#include "lua_platform.h" -#include "lua_filesystem.h" -#include -#include - -// From lua -static int msghandler(lua_State* L) { - if (!lua_isstring(L, 1)) /* 'message' not a string? */ - return 1; /* keep it intact */ - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; - } - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ - return 1; -} - -int main(int argc, char** argv) -{ - const char* exec_file = "lbs.lua"; - int argstart = 1; - if (argc > 2 && ( - strcmp(argv[1], "--buildscript") == 0 || - strcmp(argv[1], "-s") == 0)) - { - exec_file = argv[2]; - argstart += 2; - } - if (!std::filesystem::exists(exec_file)) - { - fprintf(stderr, "Failed to find buildscript %s to execute\n", exec_file); - return EXIT_FAILURE; - } - - lua_State* L = luaL_newstate(); - luaL_openlibs(L); - luaopen_dependency_tree(L); - luaopen_platform(L); - luaopen_filesystem(L); - - - luaL_loadfile(L, exec_file); - for (int i = (argstart+1); i < argc; ++i) - lua_pushstring(L, argv[i]); - int err = LUA_OK; - int msg_base = lua_gettop(L) - argc - argstart - 1; - lua_pushcfunction(L, msghandler); - lua_insert(L, msg_base); - if ( (err = lua_pcall(L, argc - argstart - 1, LUA_MULTRET, msg_base)) != LUA_OK) - { - if (err == LUA_ERRRUN) - fprintf(stderr, "A runtime error when running the script %s has occured\n%s\n", exec_file, lua_tostring(L, -1)); - else if (err == LUA_ERRMEM) - fprintf(stderr, "A memory allocation error when running the script %s has occured\n%s\n", exec_file, lua_tostring(L, -1)); - else if (err == LUA_ERRERR) - fprintf(stderr, "A error handling function has errored when running the script %s\n%s\n", exec_file, lua_tostring(L, -1)); - else - fprintf(stderr, "An unknown error has occured when running the script %s\n%s\n", exec_file, lua_tostring(L, -1)); - lua_close(L); - return EXIT_FAILURE; - } - lua_remove(L, msg_base); - - - const char* lbs_cmd = argv[argstart]; - if (argstart >= argc) - lbs_cmd = "main"; - lua_getglobal(L, lbs_cmd); - if (lua_isnil(L, -1)) - { - fprintf(stderr, "Failed to find command %s in buildscript %s to execute\n", lbs_cmd, exec_file); - lua_close(L); - return EXIT_FAILURE; - } - for (int i = (argstart + 1); i < argc; ++i) - lua_pushstring(L, argv[i]); - - msg_base = lua_gettop(L) - argc - argstart - 1; - lua_pushcfunction(L, msghandler); - lua_insert(L, msg_base); - if ( (err = lua_pcall(L, argc - argstart - 1, LUA_MULTRET, msg_base)) != LUA_OK) - { - if (err == LUA_ERRRUN) - fprintf(stderr, "A runtime error when running the command %s in the script %s has occured\n%s\n", lbs_cmd, exec_file, lua_tostring(L, -1)); - else if (err == LUA_ERRMEM) - fprintf(stderr, "A memory allocation error when running the command %s in the script %s has occured\n%s\n", lbs_cmd, exec_file, lua_tostring(L, -1)); - else if (err == LUA_ERRERR) - fprintf(stderr, "A error handling function has errored when running the command %s in the script %s\n%s\n", lbs_cmd, exec_file, lua_tostring(L, -1)); - else - fprintf(stderr, "An unknown error has occured when running the command %s in the script %s\n%s\n", lbs_cmd, exec_file, lua_tostring(L, -1)); - lua_close(L); - return EXIT_FAILURE; - } - lua_remove(L, msg_base); - - // If a return value was provided, return it - if (lua_isnumber(L, -1)) - { - int rc = lua_tointeger(L, -1); - lua_close(L); - return rc; - } - - // Otherwise return success - lua_close(L); - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/src/simple_string.cpp b/src/simple_string.cpp deleted file mode 100644 index 96c1e77..0000000 --- a/src/simple_string.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "simple_string.h" - -simple_string::simple_string(const simple_string& src) -{ - m_data = (char*)malloc(src.m_size * sizeof(char)); - m_size = src.m_size; - m_capacity = src.m_capacity; - memcpy(m_data, src.m_data, src.m_size * sizeof(char)); -} - -simple_string& simple_string::operator=(const simple_string& src) -{ - if (this == &src) return *this; - this->~simple_string(); - m_data = (char*)malloc(src.m_size * sizeof(char)); - m_size = src.m_size; - m_capacity = src.m_capacity; - memcpy(m_data, src.m_data, src.m_size * sizeof(char)); - return *this; -} - -simple_string::simple_string(simple_string&& src) noexcept -{ - m_data = src.m_data; - m_size = src.m_size; - m_capacity = src.m_capacity; - src.m_data = nullptr; - src.m_size = 0; - src.m_capacity = 0; -} - -simple_string& simple_string::operator=(simple_string&& src) noexcept -{ - if (this == &src) return *this; - this->~simple_string(); - m_data = src.m_data; - m_size = src.m_size; - m_capacity = src.m_capacity; - src.m_data = nullptr; - src.m_size = 0; - src.m_capacity = 0; - return *this; -} - -simple_string::simple_string(const char* beg, const char* end) -{ - const ptrdiff_t slen = (ptrdiff_t)(end - beg); - m_size = slen; - m_capacity = slen; - m_data = (char*)malloc(slen*sizeof(char)+1); - memcpy(m_data, beg, slen * sizeof(char)); - m_data[slen - 1] = '\0'; -} - -simple_string::simple_string(const char* str, const size_t slen) -{ - m_size = slen; - m_capacity = slen; - m_data = (char*)malloc(slen * sizeof(char)+1); - memcpy(m_data, str, slen * sizeof(char)); - m_data[slen - 1] = '\0'; -} - -simple_string::simple_string(const char* str) -{ - size_t slen = strlen(str); - m_size = slen; - m_capacity = slen; - m_data = (char*)malloc(slen * sizeof(char)+1); - memcpy(m_data, str, slen * sizeof(char)); - m_data[slen - 1] = '\0'; -} - -simple_string::simple_string(const size_t initial_capacity, const char fill_value) -{ - m_size = 0; - m_capacity = initial_capacity; - m_data = (char*)malloc(initial_capacity * sizeof(char)); - memset(m_data, fill_value, m_capacity); -} - -simple_string::simple_string(const std::string& str) -{ - m_capacity = str.size(); - m_size = str.size(); - m_data = (char*)malloc(m_size*sizeof(char)+1); - memcpy(m_data, str.data(), m_size*sizeof(char)); - m_data[m_size - 1] = '\0'; -} - -simple_string::simple_string() -{ - m_data = nullptr; - m_capacity = 0; - m_size = 0; -} - -simple_string::~simple_string(void) -{ - if (m_data != nullptr) - free(m_data); -} - -simple_string& simple_string::append(const char* other) -{ - const size_t slen = strlen(other); - if (slen == 0) return *this; - if (m_size + slen + 1 > m_capacity) - this->resize(m_size + slen); - memcpy(m_data + m_size, other, slen * sizeof(char)); - m_size += slen; - m_data[m_size] = '\0'; - return *this; -} - -simple_string& simple_string::append(const char* beg, const char* end) -{ - const ptrdiff_t slen = (ptrdiff_t)(end - beg); - if (slen == 0) return *this; - if (m_size + slen + 1 > m_capacity) - this->resize(m_size + slen); - memcpy(m_data + m_size, beg, slen * sizeof(char)); - m_size += slen; - m_data[m_size] = '\0'; - return *this; -} - -simple_string& simple_string::append(const char* other, const size_t slen) -{ - if (slen == 0) return *this; - if (m_size + slen + 1> m_capacity) - this->resize(m_size + slen); - memcpy(m_data + m_size, other, slen * sizeof(char)); - m_size += slen; - m_data[m_size] = '\0'; - return *this; -} - -simple_string& simple_string::append(const std::string& other) -{ - if (other.size() == 0) return *this; - if (m_size + other.size() > m_capacity) - this->resize(m_size + other.size()); - memcpy(m_data + m_size, other.data(), other.size() * sizeof(char)); - m_size += other.size(); - return *this; -} - -simple_string& simple_string::append(const simple_string& other) -{ - if (other.m_size == 0) return *this; - if (m_size + other.m_size > m_capacity) - this->resize(m_size + other.m_size); - memcpy(m_data + m_size, other.m_data, other.m_size * sizeof(char)); - m_size += other.m_size; - return *this; -} - -simple_string& simple_string::append(const char x) -{ - if (m_size + 1 > m_capacity) - this->expand(std::max(m_capacity, 1ULL)); - m_data[m_size] = x; - ++m_size; - return *this; -} - -void simple_string::resize(const size_t new_size) -{ - if (new_size >= m_capacity) - this->expand(std::max(new_size, m_capacity)); - m_size = new_size; -} - -void simple_string::expand(const size_t extra_capacity) -{ this->reserve(m_capacity + extra_capacity); } - -void simple_string::reserve(const size_t new_capacity) -{ - if (new_capacity <= m_capacity) return; - char* new_data = (char*)malloc(new_capacity*sizeof(char)); - if (m_capacity != 0 && m_data != nullptr) - { - memcpy(new_data, m_data, m_size * sizeof(char)); - free(m_data); - } - m_data = new_data; - m_capacity = new_capacity; -} - -const char* simple_string::c_str(void) const noexcept -{ return m_data; } - -char* simple_string::data(void) noexcept -{ return m_data; } - -size_t simple_string::size(void) const noexcept -{ return m_size; } - -char* simple_string::begin(void) noexcept -{ return m_data; } - -char* simple_string::end(void) noexcept -{ return m_data + m_size; } - -const char* simple_string::cbegin(void) const noexcept -{ return m_data; } - -const char* simple_string::cend(void) const noexcept -{ return m_data; } - -char& simple_string::operator[](const size_t idx) noexcept -{ return m_data[idx]; } - -const char& simple_string::operator[](const size_t idx) const noexcept -{ return m_data[idx]; }