diff --git a/res/modules/internal/stream_providers/file.lua b/res/modules/internal/stream_providers/file.lua index 80bc8c5bb..ec81a42c0 100644 --- a/res/modules/internal/stream_providers/file.lua +++ b/res/modules/internal/stream_providers/file.lua @@ -3,6 +3,7 @@ local io_stream = require "core:io_stream" local lib = { read = file.__read_descriptor, write = file.__write_descriptor, + seek = file.__seek_descriptor, flush = file.__flush_descriptor, is_alive = file.__has_descriptor, close = file.__close_descriptor diff --git a/res/modules/internal/stream_providers/named_pipe_unix.lua b/res/modules/internal/stream_providers/named_pipe_unix.lua index 1843dabaa..8b924f47a 100644 --- a/res/modules/internal/stream_providers/named_pipe_unix.lua +++ b/res/modules/internal/stream_providers/named_pipe_unix.lua @@ -58,6 +58,10 @@ function lib.write(fd, bytearray) end end +function lib.seek(fd, mode, offset) + error("cannot seek the named pipe") +end + function lib.flush(fd) -- no flush on unix end diff --git a/res/modules/internal/stream_providers/named_pipe_windows.lua b/res/modules/internal/stream_providers/named_pipe_windows.lua index 83691aa5a..3d4b31af1 100644 --- a/res/modules/internal/stream_providers/named_pipe_windows.lua +++ b/res/modules/internal/stream_providers/named_pipe_windows.lua @@ -62,7 +62,7 @@ function lib.read(handle, len) if not has_data then return out - elseif hasData == -1 then + elseif has_data == -1 then error("failed to read from named pipe: "..tostring(C.GetLastError())) end @@ -84,8 +84,8 @@ end function lib.write(handle, bytearray) local len = #bytearray - local buffer = FFI.new("uint8_t[?]", len) + for i = 1, len do buffer[i-1] = bytearray[i] end @@ -97,6 +97,10 @@ function lib.write(handle, bytearray) end end +function lib.seek(handle, mode, offset) + error("cannot seek the named pipe") +end + function lib.flush(handle) C.FlushFileBuffers(handle) end diff --git a/res/modules/io_stream.lua b/res/modules/io_stream.lua index 15ba85d12..b608a22a9 100644 --- a/res/modules/io_stream.lua +++ b/res/modules/io_stream.lua @@ -369,6 +369,10 @@ function io_stream:write(arg, ...) end end +function io_stream:seek(mode, offset) + self.ioLib.seek(self.descriptor, mode, offset) +end + function io_stream:is_alive() return self.ioLib.is_alive(self.descriptor) end diff --git a/src/logic/scripting/lua/libs/libfile.cpp b/src/logic/scripting/lua/libs/libfile.cpp index 687008152..26248379c 100644 --- a/src/logic/scripting/lua/libs/libfile.cpp +++ b/src/logic/scripting/lua/libs/libfile.cpp @@ -347,6 +347,41 @@ static int l_write_descriptor(lua::State* L) { return 0; } +static int l_seek_descriptor(lua::State* L) { + int descriptor = lua::tointeger(L, 1); + + if (!scripting::descriptors_manager::has_descriptor(descriptor)) { + throw std::runtime_error("unknown descriptor"); + } + + std::string mode = lua::require_string(L, 2); + std::ios_base::seekdir dir; + + switch (mode[0]) { + case 'b': + dir = std::ios_base::beg; + break; + case 'c': + dir = std::ios_base::cur; + break; + case 'e': + dir = std::ios_base::end; + break; + default: + throw std::runtime_error("invalid seek mode"); + } + + auto* stream = scripting::descriptors_manager::get_output(descriptor); + + stream->seekp(lua::tointeger(L, 3), dir); + + if (!stream->good()) { + throw std::runtime_error("failed to seek stream"); + } + + return 0; +} + static int l_flush_descriptor(lua::State* L) { int descriptor = lua::tointeger(L, 1); @@ -406,9 +441,9 @@ const luaL_Reg filelib[] = { {"__has_descriptor", lua::wrap}, {"__read_descriptor", lua::wrap}, {"__write_descriptor", lua::wrap}, + {"__seek_descriptor", lua::wrap}, {"__flush_descriptor", lua::wrap}, {"__close_descriptor", lua::wrap}, {"__close_all_descriptors", lua::wrap}, {nullptr, nullptr} }; -