Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
2a121caf42
|
|||
|
3f829f7a58
|
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <lua.hpp>
|
|
||||||
#include <luajit.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
// Any function marked with this means that the exposed lua API is not sandboxed
|
|
||||||
#define LUA_UNSAFE
|
|
||||||
@@ -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);
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "includes.h"
|
|
||||||
#include "dynarray.hpp"
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
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<ref_t> 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<std::string, ref_t> m_node_name_mapping;
|
|
||||||
// A list of all nodes in the dependency tree
|
|
||||||
dynarray<node> m_nodes;
|
|
||||||
|
|
||||||
node& operator[](const ref_t idx) noexcept;
|
|
||||||
const node& operator[](const ref_t idx) const noexcept;
|
|
||||||
|
|
||||||
dynarray<ref_t> get_leaf_nodes(const bool ignore_fulfilled=false) const;
|
|
||||||
dynarray<const char*> get_leaf_node_names(const bool ignore_fulfilled=false) const;
|
|
||||||
dynarray<ref_t> 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<ref_t>& dependents);
|
|
||||||
ref_t add_node(const char* node_name, const dynarray<const char*>& dependents);
|
|
||||||
ref_t add_node(const char* node_name, const std::initializer_list<ref_t>& dependents);
|
|
||||||
ref_t add_node(const char* node_name, const std::initializer_list<const char*>& 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<ref_t>& dependencies);
|
|
||||||
void add_node_dependencies(const ref_t node, const dynarray<ref_t>& dependencies);
|
|
||||||
void add_node_dependencies(const ref_t node, const std::initializer_list<const char*>& dependencies);
|
|
||||||
void add_node_dependencies(const ref_t node, const dynarray<const char*>& 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);
|
|
||||||
@@ -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<boolean> function fs.is_newer(path_a: string | number, path_b: string | table[string])
|
|
||||||
int lua_fs_is_newer(lua_State* L);
|
|
||||||
// table<string> | 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<file_hdl> | nil function fs.open_file(path: string)
|
|
||||||
int lua_fs_open_file(lua_State* L);
|
|
||||||
// nil function fs.close_file(userdata<file_hdl>)
|
|
||||||
// file dtor
|
|
||||||
int lua_fs_close_file(lua_State* L);
|
|
||||||
// string | nil function fs.read_file(userdata<file_hdl>, num_bytes: number)
|
|
||||||
int lua_fs_read_file(lua_State* L);
|
|
||||||
// nil function fs.seek(userdata<file_hdl>, num_bytes: number, [opt] boolean: seek_backward=false)
|
|
||||||
int lua_fs_seek_file(lua_State* L);
|
|
||||||
// nil function fs.getpos(userdata<file_hdl>)
|
|
||||||
int lua_fs_getpos_file(lua_State* L);
|
|
||||||
// nil function fs.write(userdata<file_hdl>, string)
|
|
||||||
int lua_fs_write_file(lua_State* L);
|
|
||||||
// nil function fs.append(userdata<file_hdl>, 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);
|
|
||||||
@@ -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<thread> 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> thread)
|
|
||||||
int lua_parallel_join_thread(lua_State* L);
|
|
||||||
// nil function parallel.request_stop(userdata<thread> 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> thread, ...)
|
|
||||||
int lua_parallel_sendmsg_thread(lua_State* L);
|
|
||||||
// table function parallel.recvmsg(userdata<thread>[] | nil filter)
|
|
||||||
int lua_parallel_recvmsg_thread(lua_State* L);
|
|
||||||
// number function parallel.recvsize(userdata<thread>[] | nil filter)
|
|
||||||
int lua_parallel_recvsize_thread(lua_State* L);
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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<string, boolean>
|
|
||||||
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<string>)
|
|
||||||
int lua_platform_exec(lua_State* L);
|
|
||||||
|
|
||||||
// Executes a command asynchronosly, returning a promise to the functions return values
|
|
||||||
// promise<int>, promise<string>, promise<string> function platform.exec_async(cmd: string, args: array<string>)
|
|
||||||
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<int>, promise<string>, promise<string>] function platform.exec_parallel_async(cmd: string, N: int, args: array<array<string>>)
|
|
||||||
int lua_platform_exec_parallel_async(lua_State* L);
|
|
||||||
|
|
||||||
// array<int>, array<string>, array<string> function platform.exec_parallel(cmd: string, N: int, args: array<array<string>>)
|
|
||||||
int lua_platform_exec_parallel(lua_State* L);
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdio.h>
|
|
||||||
#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
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#include <malloc.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
132
makefile
132
makefile
@@ -1,72 +1,70 @@
|
|||||||
CXX := clang++
|
CC=clang
|
||||||
CC := clang
|
CFLAGS = -Wall -Wextra
|
||||||
|
|
||||||
INCLUDES := include src thirdparty/luajit/src thirdparty/uniproc/include thirdparty/libgit2/include
|
ifeq ($(OS),Windows_NT)
|
||||||
LIBRARY_DIRECTORIES := thirdparty/luajit/src thirdparty/libgit2
|
CFLAGS += -D WIN32
|
||||||
LINKER_INPUTS := lua51 luajit
|
ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
|
||||||
|
CFLAGS += -D AMD64
|
||||||
DEBUG_DEFINES :=
|
else
|
||||||
DEFINES :=
|
ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
|
||||||
|
CFLAGS += -D AMD64
|
||||||
CXX_FLAGS := -std=c11 -std=c++20 -g -O0
|
endif
|
||||||
CC_FLAGS := -std=c11 -g -O0
|
ifeq ($(PROCESSOR_ARCHITECTURE),x86)
|
||||||
CXX_DEBUG_FLAGS :=
|
CFLAGS += -D IA32
|
||||||
LNK_FLAGS := -g -O0
|
endif
|
||||||
LNK_DEBUG_FLAGS :=
|
endif
|
||||||
|
|
||||||
LUAJUT_BUILD_CMD := call msvcbuild.bat
|
RELEASE_TARGET=bin/lbs.exe
|
||||||
|
DEBUG_TARGET=bin/lbs-dbg.exe
|
||||||
.PHONY: all clean
|
|
||||||
all: build_deps link_lbs
|
|
||||||
|
|
||||||
# From https://stackoverflow.com/a/18258352/8617429
|
|
||||||
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
|
|
||||||
define \n
|
|
||||||
|
|
||||||
endef
|
|
||||||
ifeq ($(OS), Windows_NT)
|
|
||||||
PLATFORM_SEPERATOR := &
|
|
||||||
touch = type nul > $(1)
|
|
||||||
rm = rmdir /S /Q $(1) > nul || (exit 0)
|
|
||||||
RM = del
|
|
||||||
mkdir = mkdir $(subst /,\,$(1)) > nul 2>&1 || (exit 0)
|
|
||||||
OUTPUT_NAME := lbs.exe
|
|
||||||
else
|
else
|
||||||
PLATFORM_SEPERATOR := &&
|
UNAME_S := $(shell uname -s)
|
||||||
touch = touch $(1)
|
ifeq ($(UNAME_S),Linux)
|
||||||
rm = rm -rf $(1)
|
CFLAGS += -D LINUX
|
||||||
RM = rm -f
|
endif
|
||||||
mkdir = mkdir -p $(1)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
OUTPUT_NAME := lbs
|
CFLAGS += -D OSX
|
||||||
|
endif
|
||||||
|
UNAME_P := $(shell uname -p)
|
||||||
|
ifeq ($(UNAME_P),x86_64)
|
||||||
|
CFLAGS += -D AMD64
|
||||||
|
endif
|
||||||
|
ifneq ($(filter %86,$(UNAME_P)),)
|
||||||
|
CFLAGS += -D IA32
|
||||||
|
endif
|
||||||
|
ifneq ($(filter arm%,$(UNAME_P)),)
|
||||||
|
CFLAGS += -D ARM
|
||||||
|
endif
|
||||||
|
RELEASE_TARGET=bin/lbs
|
||||||
|
DEBUG_TARGET=bin/lbs-dbg
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# If the first argument is "modules"...
|
||||||
|
ifeq (modules,$(firstword $(MAKECMDGOALS)))
|
||||||
|
# use the rest as arguments for "run"
|
||||||
|
MODULE_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
||||||
|
# ...and turn them into do-nothing targets
|
||||||
|
$(eval $(MODULE_ARGS):;@:)
|
||||||
|
endif
|
||||||
|
|
||||||
|
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
|
||||||
|
|
||||||
|
SRC_FILES=$(call rwildcard, src, *.c)
|
||||||
|
OBJ_FILES=$(addprefix obj/, $(SRC_FILES:.c=.o))
|
||||||
|
modules:
|
||||||
|
cd modules && $(MAKE) $(MODULE_ARGS)
|
||||||
|
|
||||||
|
|
||||||
|
obj/src/%.o: src/%.c
|
||||||
|
$(CC) $(CFLAGS) -c $(@:obj/%.o=%.c) -o $@
|
||||||
|
|
||||||
|
release: $(RELEASE_TARGET)
|
||||||
|
$(RELEASE_TARGET): $(OBJ_FILES)
|
||||||
|
$(CC) $(LFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
debug: $(DEBUG_TARGET)
|
||||||
|
$(DEBUG_TARGET): $(OBJ_FILES)
|
||||||
|
$(CC) $(LFLAGS) $^ -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(call RM,$(call rwildcard, obj,*.o) build/$(OUTPUT_NAME))
|
echo TODO
|
||||||
|
|
||||||
SOURCE_FILES := $(call rwildcard,src,*.cpp,*.hpp) $(call rwildcard,thirdparty/uniproc/src,*.c)
|
|
||||||
OBJECT_FILES := $(foreach d,$(addsuffix .o,$(SOURCE_FILES)), obj/$(d))
|
|
||||||
|
|
||||||
obj/thirdparty/uniproc/src/%.c.o: thirdparty/uniproc/src/%.c
|
|
||||||
$(CC) -c $(CC_FLAGS) $(foreach inc,$(INCLUDES),-I$(inc)) $(foreach def,$(DEFINES),-D$(def)) $< -o $@
|
|
||||||
obj/src/%.cpp.o: src/%.cpp
|
|
||||||
$(CXX) -c $(CXX_FLAGS) $(foreach inc,$(INCLUDES),-I$(inc)) $(foreach def,$(DEFINES),-D$(def)) $< -o $@
|
|
||||||
|
|
||||||
link_lbs: $(OBJECT_FILES)
|
|
||||||
$(CXX) $(LNK_FLAGS) $(LNK_FLAGS) $(foreach lib,$(LIBRARY_DIRECTORIES),-L$(lib)) $(foreach lnk,$(LINKER_INPUTS),-l$(lnk)) $^ -o build/$(OUTPUT_NAME)
|
|
||||||
|
|
||||||
build_deps: .make/thirdparty_luajit .make/thirdparty_uniproc
|
|
||||||
|
|
||||||
.make/thirdparty_luajit:
|
|
||||||
git submodule update --init --recursive --remote
|
|
||||||
cd thirdparty/luajit/src $(PLATFORM_SEPERATOR) $(LUAJUT_BUILD_CMD)
|
|
||||||
$(call touch,".make/thirdparty_luajit")
|
|
||||||
|
|
||||||
.make/thirdparty_uniproc:
|
|
||||||
git submodule update --init --recursive --remote
|
|
||||||
$(call touch,".make/thirdparty_uniproc")
|
|
||||||
|
|
||||||
.make/thirdparty_libgit2:
|
|
||||||
git submodule update --init --recursive --remote
|
|
||||||
cd thirdparty/libgit2 && mkdir build
|
|
||||||
cd thirdparty/libgit2/build && cmake .. && cmake --build .
|
|
||||||
$(call touch,".make/thirdparty_libgit2")
|
|
||||||
|
|||||||
365
src/dynarray.hpp
365
src/dynarray.hpp
@@ -1,365 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <utility>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
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<T>& 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<T>& vals);
|
|
||||||
void push_back(const dynarray<T>& 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<typename T>
|
|
||||||
inline dynarray<T>::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<typename T>
|
|
||||||
inline dynarray<T>& dynarray<T>::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<typename T>
|
|
||||||
inline dynarray<T>::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<typename T>
|
|
||||||
inline dynarray<T>& dynarray<T>::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<typename T>
|
|
||||||
inline dynarray<T>::dynarray(void)
|
|
||||||
{
|
|
||||||
m_data = nullptr;
|
|
||||||
m_size = 0;
|
|
||||||
m_capacity = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline dynarray<T>::dynarray(const std::initializer_list<T>& src)
|
|
||||||
{
|
|
||||||
m_data = (T*)malloc(src.size()*sizeof(T));
|
|
||||||
m_size = src.size();
|
|
||||||
m_capacity = src.size();
|
|
||||||
if (std::is_trivially_copyable<T>::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<typename T>
|
|
||||||
inline dynarray<T>::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<typename T>
|
|
||||||
inline dynarray<T>::~dynarray(void)
|
|
||||||
{
|
|
||||||
if (m_data != nullptr)
|
|
||||||
{
|
|
||||||
if (!std::is_trivially_destructible<T>::value)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_size; ++i)
|
|
||||||
m_data[i].~T();
|
|
||||||
}
|
|
||||||
free(m_data);
|
|
||||||
m_data = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T& dynarray<T>::operator[](const size_t idx) noexcept
|
|
||||||
{ return m_data[idx]; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T& dynarray<T>::operator[](const size_t idx) const noexcept
|
|
||||||
{ return m_data[idx]; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T* dynarray<T>::begin(void) noexcept
|
|
||||||
{ return m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T* dynarray<T>::begin(void) const noexcept
|
|
||||||
{ return m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T* dynarray<T>::cbegin(void) const noexcept
|
|
||||||
{ return m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T* dynarray<T>::end(void) noexcept
|
|
||||||
{ return m_data == nullptr ? nullptr : (m_data + m_size); }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T* dynarray<T>::end(void) const noexcept
|
|
||||||
{ return m_data == nullptr ? nullptr : (m_data + m_size); }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T* dynarray<T>::cend(void) const noexcept
|
|
||||||
{ return m_data == nullptr ? nullptr : (m_data + m_size); }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T* dynarray<T>::c_str(void) const noexcept
|
|
||||||
{ return m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T* dynarray<T>::c_array(void) const noexcept
|
|
||||||
{ return m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T* dynarray<T>::data(void) const noexcept
|
|
||||||
{ return m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline size_t dynarray<T>::size(void) const noexcept
|
|
||||||
{ return m_size; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline size_t dynarray<T>::capacity(void) const noexcept
|
|
||||||
{ return m_capacity; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline bool dynarray<T>::is_empty(void) const noexcept
|
|
||||||
{ return m_size == 0; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline bool dynarray<T>::is_nullptr(void) const noexcept
|
|
||||||
{
|
|
||||||
return m_data == nullptr || m_capacity == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void dynarray<T>::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<typename T>
|
|
||||||
inline void dynarray<T>::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<typename T>
|
|
||||||
inline void dynarray<T>::push_back(const std::initializer_list<T>& vals)
|
|
||||||
{
|
|
||||||
const size_t prev_size = m_size;
|
|
||||||
this->resize(m_size + vals.size());
|
|
||||||
if (std::is_trivially_copyable<T>::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<typename T>
|
|
||||||
inline void dynarray<T>::push_back(const dynarray<T>& vals)
|
|
||||||
{
|
|
||||||
const size_t prev_size = m_size;
|
|
||||||
this->resize(m_size + vals.m_size);
|
|
||||||
if (std::is_trivially_copyable<T>::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<typename T>
|
|
||||||
inline void dynarray<T>::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<T>::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<typename T>
|
|
||||||
inline T&& dynarray<T>::pop_back(void) noexcept
|
|
||||||
{
|
|
||||||
m_size--;
|
|
||||||
return std::move(m_data[m_size]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T& dynarray<T>::front(void) noexcept
|
|
||||||
{ return *m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T& dynarray<T>::front(void) const noexcept
|
|
||||||
{ return *m_data; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T& dynarray<T>::back(void) noexcept
|
|
||||||
{ return m_data[m_size - 1]; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline const T& dynarray<T>::back(void) const noexcept
|
|
||||||
{ return m_data[m_size-1]; }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void dynarray<T>::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<T>::value)
|
|
||||||
for (size_t i = new_size; i < m_size; ++i)
|
|
||||||
m_data[i].~T();
|
|
||||||
m_size = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void dynarray<T>::expand(const size_t extra_capacity)
|
|
||||||
{ this->reserve(m_capacity + extra_capacity); }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void dynarray<T>::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<T>::value)
|
|
||||||
memcpy(new_data, m_data, m_size * sizeof(T));
|
|
||||||
else if constexpr (std::is_move_assignable<T>::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<T>::value)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < m_size; ++i)
|
|
||||||
new (new_data+i) T(m_data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::is_trivially_destructible<T>::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<typename T>
|
|
||||||
inline void dynarray<T>::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<T>::value)
|
|
||||||
memcpy(new_data, m_data, m_size * sizeof(T));
|
|
||||||
else if (std::is_move_assignable<T>::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<T>::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;
|
|
||||||
}
|
|
||||||
@@ -1,667 +0,0 @@
|
|||||||
#include "lua_dependency_tree.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
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::ref_t> dependency_tree::get_leaf_nodes(const bool ignore_fulfilled) const
|
|
||||||
{
|
|
||||||
dynarray<ref_t> 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<const char*> dependency_tree::get_leaf_node_names(const bool ignore_fulfilled) const
|
|
||||||
{
|
|
||||||
dynarray<ref_t> refs = this->get_leaf_nodes(ignore_fulfilled);
|
|
||||||
dynarray<const char*> names;
|
|
||||||
for (const ref_t ref : refs)
|
|
||||||
names.push_back(m_nodes[ref].m_name);
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
dynarray<dependency_tree::ref_t> dependency_tree::filter_nodes(const state_cmp_t state_cmp, const ref_t num_dependencies_gt, const bool invert_num_deps) const
|
|
||||||
{
|
|
||||||
dynarray<ref_t> 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<ref_t>& 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<ref_t>(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<const char*>& dependents)
|
|
||||||
{
|
|
||||||
dynarray<ref_t> 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<ref_t>& dependents)
|
|
||||||
{ return this->add_node(node_name, dynarray<ref_t>(dependents)); }
|
|
||||||
|
|
||||||
dependency_tree::ref_t dependency_tree::add_node(const char* node_name, const std::initializer_list<const char*>& dependents)
|
|
||||||
{
|
|
||||||
dynarray<ref_t> 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<ref_t>();
|
|
||||||
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<ref_t>& 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<ref_t>& 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<const char*>& dependencies)
|
|
||||||
{
|
|
||||||
for (const char* dep : dependencies)
|
|
||||||
this->add_node_dependency(node, dep);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dependency_tree::add_node_dependencies(const ref_t node, const dynarray<const char*>& 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<dependency_tree>");
|
|
||||||
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<dependency_tree::ref_t> 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<dependency_tree>");
|
|
||||||
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>");
|
|
||||||
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>");
|
|
||||||
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<dependency_tree::ref_t> 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>");
|
|
||||||
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<dependency_tree>");
|
|
||||||
dynarray<dependency_tree::ref_t> 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<dependency_tree>");
|
|
||||||
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<dependency_tree::ref_t> 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>");
|
|
||||||
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>");
|
|
||||||
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>");
|
|
||||||
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>");
|
|
||||||
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>");
|
|
||||||
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<dependency_tree>");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,453 +0,0 @@
|
|||||||
#include "lua_filesystem.h"
|
|
||||||
#include <filesystem>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
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<std::filesystem::directory_iterator>");
|
|
||||||
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<std::filesystem::recursive_directory_iterator>");
|
|
||||||
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<std::filesystem::directory_iterator>");
|
|
||||||
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<std::filesystem::recursive_directory_iterator>");
|
|
||||||
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::milliseconds>(
|
|
||||||
std::chrono::clock_cast<std::chrono::system_clock>(
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
#include "lua_platform.h"
|
|
||||||
#include "platform_agnostic.h"
|
|
||||||
#include "dynarray.hpp"
|
|
||||||
#include "mutex"
|
|
||||||
#include <chrono>
|
|
||||||
#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::string> std_outs;
|
|
||||||
std::vector<std::string> 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
7
src/main.c
Normal file
7
src/main.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("Hello, World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
116
src/main.cpp
116
src/main.cpp
@@ -1,116 +0,0 @@
|
|||||||
#include "lua_dependency_tree.h"
|
|
||||||
#include "lua_platform.h"
|
|
||||||
#include "lua_filesystem.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
@@ -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]; }
|
|
||||||
Reference in New Issue
Block a user