Streaming I/O and support of named pipes (#570)

* added streaming i/o for scripting, and a byteutil.get_size function

* added i/o stream class, also added named pipes support on lua side via ffi

* added constant file.named_pipes_prefix

* added buffered and yield modes for io_stream

* added new time function for work with UTC - utc_time, utc_offset, local_time

* docs updated

* constant pid moved to os.pid

* now gmtime_s and localtime_s used only in windows
This commit is contained in:
Onran
2025-08-01 20:26:43 +03:00
committed by GitHub
parent cd2bc8fbf6
commit aae642a13e
16 changed files with 1303 additions and 1 deletions
+151
View File
@@ -9,6 +9,7 @@
#include "util/stringutil.hpp"
#include "api_lua.hpp"
#include "../lua_engine.hpp"
#include "logic/scripting/descriptors_manager.hpp"
namespace fs = std::filesystem;
using namespace scripting;
@@ -258,6 +259,149 @@ static int l_create_zip(lua::State* L) {
return 0;
}
static int l_open_descriptor(lua::State* L) {
io::path path = lua::require_string(L, 1);
auto mode = lua::require_lstring(L, 2);
bool write = mode.find('w') != std::string::npos;
bool read = mode.find('r') != std::string::npos;
if (write && !is_writeable(path.entryPoint())) {
throw std::runtime_error("access denied");
}
if(!write && !read) {
throw std::runtime_error("mode must contain read or write flag");
}
if(write && read) {
throw std::runtime_error("random access file i/o is not supported");
}
bool wplusMode = write && mode.find('+') != std::string::npos;
std::vector<char> buffer;
if(wplusMode) {
int temp_descriptor = scripting::descriptors_manager::open_descriptor(path, false, true);
if (temp_descriptor == -1) {
throw std::runtime_error("failed to open descriptor for initial reading");
}
auto* in_stream = scripting::descriptors_manager::get_input(temp_descriptor);
in_stream->seekg(0, std::ios::end);
std::streamsize size = in_stream->tellg();
in_stream->seekg(0, std::ios::beg);
buffer.resize(size);
in_stream->read(buffer.data(), size);
scripting::descriptors_manager::close(temp_descriptor);
}
int descriptor = scripting::descriptors_manager::open_descriptor(path, write, read);
if(descriptor == -1) {
throw std::runtime_error("failed to open descriptor");
}
if(wplusMode) {
auto* out_stream = scripting::descriptors_manager::get_output(descriptor);
out_stream->write(buffer.data(), buffer.size());
out_stream->flush();
}
return lua::pushinteger(L, descriptor);
}
static int l_has_descriptor(lua::State* L) {
return lua::pushboolean(L, scripting::descriptors_manager::has_descriptor(lua::tointeger(L, 1)));
}
static int l_read_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
if (!scripting::descriptors_manager::is_readable(descriptor)) {
throw std::runtime_error("descriptor is not readable");
}
int maxlen = lua::tointeger(L, 2);
auto* stream = scripting::descriptors_manager::get_input(descriptor);
util::Buffer<char> buffer(maxlen);
stream->read(buffer.data(), maxlen);
std::streamsize read_len = stream->gcount();
return lua::create_bytearray(L, buffer.data(), read_len);
}
static int l_write_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
if (!scripting::descriptors_manager::is_writeable(descriptor)) {
throw std::runtime_error("descriptor is not writeable");
}
auto data = lua::bytearray_as_string(L, 2);
auto* stream = scripting::descriptors_manager::get_output(descriptor);
stream->write(data.data(), static_cast<std::streamsize>(data.size()));
if (!stream->good()) {
throw std::runtime_error("failed to write to stream");
}
return 0;
}
static int l_flush_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
if (!scripting::descriptors_manager::is_writeable(descriptor)) {
throw std::runtime_error("descriptor is not writeable");
}
scripting::descriptors_manager::flush(descriptor);
return 0;
}
static int l_close_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
scripting::descriptors_manager::close(descriptor);
return 0;
}
static int l_close_all_descriptors(lua::State* L) {
scripting::descriptors_manager::close_all_descriptors();
return 0;
}
const luaL_Reg filelib[] = {
{"exists", lua::wrap<l_exists>},
{"find", lua::wrap<l_find>},
@@ -283,5 +427,12 @@ const luaL_Reg filelib[] = {
{"mount", lua::wrap<l_mount>},
{"unmount", lua::wrap<l_unmount>},
{"create_zip", lua::wrap<l_create_zip>},
{"__open_descriptor", lua::wrap<l_open_descriptor>},
{"__has_descriptor", lua::wrap<l_has_descriptor>},
{"__read_descriptor", lua::wrap<l_read_descriptor>},
{"__write_descriptor", lua::wrap<l_write_descriptor>},
{"__flush_descriptor", lua::wrap<l_flush_descriptor>},
{"__close_descriptor", lua::wrap<l_close_descriptor>},
{"__close_all_descriptors", lua::wrap<l_close_all_descriptors>},
{NULL, NULL}
};