refactor descriptors_manager

This commit is contained in:
MihailRis 2026-06-10 23:08:48 +03:00
parent 4cc6a83872
commit 07702f9e57
6 changed files with 166 additions and 166 deletions

View file

@ -9,10 +9,19 @@ local lib = {
close = file.__close_descriptor
}
local __open_descriptor = file.__open_descriptor
file.__open_descriptor = nil
file.__read_descriptor = nil
file.__write_descriptor = nil
file.__seek_descriptor = nil
file.__flush_descriptor = nil
file.__has_descriptor = nil
file.__close_descriptor = nil
return function(path, mode)
return io_stream.new(
file.__open_descriptor(path, mode),
__open_descriptor(path, mode),
mode:find('b') ~= nil,
lib
)
end
end

View file

@ -1,104 +0,0 @@
#include "logic/scripting/descriptors_manager.hpp"
#include "debug/Logger.hpp"
static debug::Logger logger("descriptors-manager");
namespace scripting {
std::vector<std::optional<StreamDescriptor>> descriptors_manager::descriptors;
std::istream* descriptors_manager::get_input(int descriptor) {
if (!is_readable(descriptor))
return nullptr;
return descriptors[descriptor]->in.get();
}
std::ostream* descriptors_manager::get_output(int descriptor) {
if (!is_writeable(descriptor))
return nullptr;
return descriptors[descriptor]->out.get();
}
void descriptors_manager::flush(int descriptor) {
if (is_writeable(descriptor)) {
descriptors[descriptor]->out->flush();
}
}
bool descriptors_manager::has_descriptor(int descriptor) {
return is_readable(descriptor) || is_writeable(descriptor);
}
bool descriptors_manager::is_readable(int descriptor) {
return descriptor >= 0 && descriptor < static_cast<int>(descriptors.size())
&& descriptors[descriptor].has_value()
&& descriptors[descriptor]->in != nullptr;
}
bool descriptors_manager::is_writeable(int descriptor) {
return descriptor >= 0 && descriptor < static_cast<int>(descriptors.size())
&& descriptors[descriptor].has_value()
&& descriptors[descriptor]->out != nullptr;
}
void descriptors_manager::close(int descriptor) {
if (descriptor >= 0 && descriptor < static_cast<int>(descriptors.size())) {
if (descriptors[descriptor].has_value()) {
auto& desc = descriptors[descriptor].value();
if (desc.out)
desc.out->flush();
desc.in.reset();
desc.out.reset();
}
descriptors[descriptor].reset();
descriptors[descriptor] = std::nullopt;
}
}
int descriptors_manager::open_descriptor(const io::path& path, bool write, bool read) {
std::unique_ptr<std::istream> in;
std::unique_ptr<std::ostream> out;
try {
if (read)
in = io::read(path);
if (write)
out = io::write(path);
} catch (const std::exception& e) {
logger.error() << "failed to open descriptor for " << path.string()
<< ": " << e.what();
return -1;
}
for (int i = 0; i < static_cast<int>(descriptors.size()); ++i) {
if (!descriptors[i].has_value()) {
descriptors[i] = StreamDescriptor{ std::move(in), std::move(out) };
return i;
}
}
descriptors.emplace_back(StreamDescriptor{ std::move(in), std::move(out) });
return static_cast<int>(descriptors.size() - 1);
}
void descriptors_manager::close_all_descriptors() {
for (int i = 0; i < static_cast<int>(descriptors.size()); ++i) {
if (descriptors[i].has_value()) {
close(i);
}
}
descriptors.clear();
}
}

View file

@ -1,39 +0,0 @@
#pragma once
#include <memory>
#include <vector>
#include <optional>
#include <string>
#include <istream>
#include <ostream>
#include "io/io.hpp"
namespace scripting {
struct StreamDescriptor {
std::unique_ptr<std::istream> in;
std::unique_ptr<std::ostream> out;
};
class descriptors_manager {
private:
static std::vector<std::optional<StreamDescriptor>> descriptors;
public:
static std::istream* get_input(int descriptor);
static std::ostream* get_output(int descriptor);
static void flush(int descriptor);
static bool has_descriptor(int descriptor);
static bool is_readable(int descriptor);
static bool is_writeable(int descriptor);
static void close(int descriptor);
static int open_descriptor(const io::path& path, bool write, bool read);
static void close_all_descriptors();
};
}

View file

@ -0,0 +1,111 @@
#include "logic/scripting/io_descriptors.hpp"
#include "debug/Logger.hpp"
#include "io/io.hpp"
#include <memory>
#include <string>
#include <vector>
#include <optional>
static debug::Logger logger("descriptors-manager");
using namespace scripting;
namespace {
struct StreamDescriptor {
std::unique_ptr<std::istream> in;
std::unique_ptr<std::ostream> out;
};
std::vector<std::optional<StreamDescriptor>> descriptors;
}
std::istream* io_descriptors::get_input(int id) {
if (!is_readable(id)) {
return nullptr;
}
return ::descriptors[id]->in.get();
}
std::ostream* io_descriptors::get_output(int id) {
if (!is_writeable(id)) {
return nullptr;
}
return ::descriptors[id]->out.get();
}
void io_descriptors::flush(int id) {
if (is_writeable(id)) {
::descriptors[id]->out->flush();
}
}
bool io_descriptors::has_descriptor(int id) {
return id >= 0 && id < static_cast<int>(::descriptors.size()) &&
::descriptors[id].has_value() &&
(::descriptors[id]->in != nullptr ||
::descriptors[id]->out != nullptr);
}
bool io_descriptors::is_readable(int id) {
return id >= 0 && id < static_cast<int>(::descriptors.size())
&& ::descriptors[id].has_value()
&& ::descriptors[id]->in != nullptr;
}
bool io_descriptors::is_writeable(int id) {
return id >= 0 && id < static_cast<int>(::descriptors.size())
&& ::descriptors[id].has_value()
&& ::descriptors[id]->out != nullptr;
}
void io_descriptors::close(int id) {
if (!has_descriptor(id)) {
return;
}
auto& desc = ::descriptors[id].value();
if (desc.out) {
desc.out->flush();
}
desc.in.reset();
desc.out.reset();
::descriptors[id] = std::nullopt;
}
int io_descriptors::open_descriptor(const io::path& path, bool write, bool read) {
std::unique_ptr<std::istream> in;
std::unique_ptr<std::ostream> out;
try {
if (read) {
in = io::read(path);
}
if (write) {
out = io::write(path);
}
} catch (const std::exception& e) {
logger.error() << "failed to open descriptor for " << path.string()
<< ": " << e.what();
return -1;
}
for (int i = 0; i < static_cast<int>(descriptors.size()); ++i) {
if (!descriptors[i].has_value()) {
descriptors[i] = StreamDescriptor{ std::move(in), std::move(out) };
return i;
}
}
::descriptors.emplace_back(StreamDescriptor{ std::move(in), std::move(out) });
return static_cast<int>(::descriptors.size() - 1);
}
void io_descriptors::close_all_descriptors() {
for (int i = 0; i < static_cast<int>(::descriptors.size()); ++i) {
if (::descriptors[i].has_value()) {
close(i);
}
}
::descriptors.clear();
}

View file

@ -0,0 +1,23 @@
#pragma once
#include <istream>
#include <ostream>
#include "io/fwd.hpp"
namespace scripting::io_descriptors {
std::istream* get_input(int id);
std::ostream* get_output(int id);
void flush(int id);
bool has_descriptor(int id);
bool is_readable(int id);
bool is_writeable(int id);
void close(int id);
int open_descriptor(const io::path& path, bool write, bool read);
void close_all_descriptors();
}

View file

@ -10,7 +10,7 @@
#include "util/stringutil.hpp"
#include "api_lua.hpp"
#include "../lua_engine.hpp"
#include "logic/scripting/descriptors_manager.hpp"
#include "logic/scripting/io_descriptors.hpp"
namespace fs = std::filesystem;
using namespace scripting;
@ -263,13 +263,13 @@ static int l_open_descriptor(lua::State* L) {
std::vector<char> buffer;
if(wplusMode) {
int temp_descriptor = scripting::descriptors_manager::open_descriptor(path, false, true);
int temp_descriptor = io_descriptors::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);
auto* in_stream = io_descriptors::get_input(temp_descriptor);
in_stream->seekg(0, std::ios::end);
std::streamsize size = in_stream->tellg();
@ -278,17 +278,17 @@ static int l_open_descriptor(lua::State* L) {
buffer.resize(size);
in_stream->read(buffer.data(), size);
scripting::descriptors_manager::close(temp_descriptor);
io_descriptors::close(temp_descriptor);
}
int descriptor = scripting::descriptors_manager::open_descriptor(path, write, read);
int descriptor = io_descriptors::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);
auto* out_stream = io_descriptors::get_output(descriptor);
out_stream->write(buffer.data(), buffer.size());
out_stream->flush();
}
@ -297,23 +297,23 @@ static int l_open_descriptor(lua::State* L) {
}
static int l_has_descriptor(lua::State* L) {
return lua::pushboolean(L, scripting::descriptors_manager::has_descriptor(lua::tointeger(L, 1)));
return lua::pushboolean(L, io_descriptors::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)) {
if (!io_descriptors::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
if (!scripting::descriptors_manager::is_readable(descriptor)) {
if (!io_descriptors::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);
auto* stream = io_descriptors::get_input(descriptor);
util::Buffer<char> buffer(maxlen);
@ -327,17 +327,17 @@ static int l_read_descriptor(lua::State* L) {
static int l_write_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
if (!io_descriptors::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
if (!scripting::descriptors_manager::is_writeable(descriptor)) {
if (!io_descriptors::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);
auto* stream = io_descriptors::get_output(descriptor);
stream->write(data.data(), static_cast<std::streamsize>(data.size()));
@ -350,7 +350,7 @@ static int l_write_descriptor(lua::State* L) {
static int l_seek_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
if (!io_descriptors::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
@ -371,7 +371,7 @@ static int l_seek_descriptor(lua::State* L) {
throw std::runtime_error("invalid seek mode");
}
auto* stream = scripting::descriptors_manager::get_output(descriptor);
auto* stream = io_descriptors::get_output(descriptor);
stream->seekp(lua::tointeger(L, 3), dir);
@ -385,31 +385,31 @@ static int l_seek_descriptor(lua::State* L) {
static int l_flush_descriptor(lua::State* L) {
int descriptor = lua::tointeger(L, 1);
if (!scripting::descriptors_manager::has_descriptor(descriptor)) {
if (!io_descriptors::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
if (!scripting::descriptors_manager::is_writeable(descriptor)) {
if (!io_descriptors::is_writeable(descriptor)) {
throw std::runtime_error("descriptor is not writeable");
}
scripting::descriptors_manager::flush(descriptor);
io_descriptors::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)) {
if (!io_descriptors::has_descriptor(descriptor)) {
throw std::runtime_error("unknown descriptor");
}
scripting::descriptors_manager::close(descriptor);
io_descriptors::close(descriptor);
return 0;
}
static int l_close_all_descriptors(lua::State* L) {
scripting::descriptors_manager::close_all_descriptors();
io_descriptors::close_all_descriptors();
return 0;
}