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:
@@ -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}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user