mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-11 14:01:49 +00:00
added low-level ioLib.available for io_stream's
This commit is contained in:
parent
fdec2d722d
commit
bf98091a9c
9 changed files with 97 additions and 12 deletions
|
|
@ -154,16 +154,6 @@ io_stream:seek(
|
||||||
## Методы Buffered-режима
|
## Методы Buffered-режима
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
--[[
|
|
||||||
Если length определён, то возвращает true, если length байт доступно к чтению. Иначе возвращает false
|
|
||||||
|
|
||||||
Если не определён, то возвращает количество байт, которое можно прочитать
|
|
||||||
|
|
||||||
--]]
|
|
||||||
io_stream:available(
|
|
||||||
[опционально] length: number
|
|
||||||
) -> number | boolean
|
|
||||||
|
|
||||||
-- Возвращает максимальный размер буферов
|
-- Возвращает максимальный размер буферов
|
||||||
io_stream:get_max_buffer_size() -> number
|
io_stream:get_max_buffer_size() -> number
|
||||||
|
|
||||||
|
|
@ -174,6 +164,14 @@ io_stream:set_max_buffer_size(max_size: number)
|
||||||
## Методы контроля состояния потока
|
## Методы контроля состояния потока
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
--[[
|
||||||
|
Если length определён, то возвращает true, если length байт доступно к чтению. Иначе возвращает false.
|
||||||
|
|
||||||
|
Если не определён, то возвращает количество байт, которое можно прочитать.
|
||||||
|
--]]
|
||||||
|
io_stream:available(
|
||||||
|
[опционально] length: number
|
||||||
|
) -> number | boolean
|
||||||
|
|
||||||
-- Возвращает true, если поток открыт на данный момент
|
-- Возвращает true, если поток открыт на данный момент
|
||||||
io_stream:is_alive() -> bool
|
io_stream:is_alive() -> bool
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,15 @@ function lib.flush(descriptor)
|
||||||
requireDescriptor(descriptor)
|
requireDescriptor(descriptor)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function lib.available(descriptor)
|
||||||
|
requireDescriptor(descriptor)
|
||||||
|
|
||||||
|
local buf = buffers[descriptor]
|
||||||
|
local pos = positions[descriptor]
|
||||||
|
|
||||||
|
return math.max(#buf - pos + 1, 0)
|
||||||
|
end
|
||||||
|
|
||||||
function lib.is_alive(descriptor)
|
function lib.is_alive(descriptor)
|
||||||
return buffers[descriptor] ~= nil
|
return buffers[descriptor] ~= nil
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ local lib = {
|
||||||
write = file.__write_descriptor,
|
write = file.__write_descriptor,
|
||||||
seek = file.__seek_descriptor,
|
seek = file.__seek_descriptor,
|
||||||
flush = file.__flush_descriptor,
|
flush = file.__flush_descriptor,
|
||||||
|
available = file.__available_descriptor,
|
||||||
is_alive = file.__has_descriptor,
|
is_alive = file.__has_descriptor,
|
||||||
close = file.__close_descriptor
|
close = file.__close_descriptor
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ int close(int fd);
|
||||||
ssize_t read(int fd, void *buf, size_t count);
|
ssize_t read(int fd, void *buf, size_t count);
|
||||||
ssize_t write(int fd, const void *buf, size_t count);
|
ssize_t write(int fd, const void *buf, size_t count);
|
||||||
int fcntl(int fd, int cmd, ...);
|
int fcntl(int fd, int cmd, ...);
|
||||||
|
int ioctl(int fd, unsigned long request, ...);
|
||||||
|
|
||||||
const char *strerror(int errnum);
|
const char *strerror(int errnum);
|
||||||
]]
|
]]
|
||||||
|
|
@ -20,6 +21,7 @@ local O_WRONLY = 0x1
|
||||||
local O_RDWR = 0x2
|
local O_RDWR = 0x2
|
||||||
local O_NONBLOCK = 0x800
|
local O_NONBLOCK = 0x800
|
||||||
local F_GETFL = 3
|
local F_GETFL = 3
|
||||||
|
local FIONREAD = 0x541B
|
||||||
|
|
||||||
local function getError()
|
local function getError()
|
||||||
local err = FFI.errno()
|
local err = FFI.errno()
|
||||||
|
|
@ -66,6 +68,18 @@ function lib.flush(fd)
|
||||||
-- no flush on unix
|
-- no flush on unix
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function lib.available(fd)
|
||||||
|
if fd == nil or fd < 0 then return 0 end
|
||||||
|
|
||||||
|
local bytes_ready = FFI.new("int[1]", 0)
|
||||||
|
|
||||||
|
if C.ioctl(fd, FIONREAD, bytes_ready) == -1 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return tonumber(bytes_ready[0])
|
||||||
|
end
|
||||||
|
|
||||||
function lib.is_alive(fd)
|
function lib.is_alive(fd)
|
||||||
if fd == nil or fd < 0 then return false end
|
if fd == nil or fd < 0 then return false end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,22 @@ function lib.flush(handle)
|
||||||
C.FlushFileBuffers(handle)
|
C.FlushFileBuffers(handle)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function lib.available(handle)
|
||||||
|
if handle == nil or handle == INVALID_HANDLE_VALUE then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local bytes_available = FFI.new("DWORD[1]")
|
||||||
|
|
||||||
|
local success = C.PeekNamedPipe(handle, nil, 0, nil, bytes_available, nil)
|
||||||
|
|
||||||
|
if success == 0 then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return tonumber(bytes_available[0])
|
||||||
|
end
|
||||||
|
|
||||||
function lib.is_alive(handle)
|
function lib.is_alive(handle)
|
||||||
if handle == nil or handle == INVALID_HANDLE_VALUE then
|
if handle == nil or handle == INVALID_HANDLE_VALUE then
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,17 @@ local function readFully(result, readFunc)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|
||||||
descriptor - descriptor of stream for provided I/O library
|
descriptor - descriptor of stream for provided I/O library
|
||||||
binaryMode - if enabled, most methods will expect bytes instead of strings
|
binaryMode - if enabled, most methods will expect bytes instead of strings
|
||||||
ioLib - I/O library. Should include the following functions:
|
ioLib - I/O library. Should include the following functions:
|
||||||
read(descriptor: int, length: int) -> Bytearray
|
read(descriptor: int, length: int) -> Bytearray
|
||||||
May return bytearray with a smaller size if bytes have not arrived yet or have run out
|
May return bytearray with a smaller size if bytes have not arrived yet or have run out
|
||||||
write(descriptor: int, data: Bytearray)
|
write(descriptor: int, data: Bytearray)
|
||||||
|
seek(descriptor: int, mode: string, offset: int)
|
||||||
|
Mode may be 'b' (relative begin), 'c' (relative current), 'e' (relative end + 1)
|
||||||
flush(descriptor: int)
|
flush(descriptor: int)
|
||||||
|
available(descriptor: int) -> int
|
||||||
|
May return 0 if environment is not support available method
|
||||||
is_alive(descriptor: int) -> bool
|
is_alive(descriptor: int) -> bool
|
||||||
close(descriptor: int)
|
close(descriptor: int)
|
||||||
--]]
|
--]]
|
||||||
|
|
@ -130,7 +133,7 @@ function io_stream:available(length)
|
||||||
else
|
else
|
||||||
return #self.readBuffer >= length
|
return #self.readBuffer >= length
|
||||||
end
|
end
|
||||||
end
|
else return self.ioLib.available(self.descriptor) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function io_stream:__update_read_buffer()
|
function io_stream:__update_read_buffer()
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,33 @@ namespace scripting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int descriptors_manager::available(int descriptor) {
|
||||||
|
if (!is_readable(descriptor))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto* stream = descriptors[descriptor]->in.get();
|
||||||
|
|
||||||
|
auto current_pos = stream->tellg();
|
||||||
|
|
||||||
|
if (current_pos == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->seekg(0, std::ios::end);
|
||||||
|
|
||||||
|
auto end_pos = stream->tellg();
|
||||||
|
|
||||||
|
stream->seekg(current_pos, std::ios::beg);
|
||||||
|
|
||||||
|
auto remaining = end_pos - current_pos;
|
||||||
|
|
||||||
|
if (remaining > std::numeric_limits<int>::max()) {
|
||||||
|
return std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int>(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
bool descriptors_manager::has_descriptor(int descriptor) {
|
bool descriptors_manager::has_descriptor(int descriptor) {
|
||||||
return is_readable(descriptor) || is_writeable(descriptor);
|
return is_readable(descriptor) || is_writeable(descriptor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ namespace scripting {
|
||||||
|
|
||||||
static void flush(int descriptor);
|
static void flush(int descriptor);
|
||||||
|
|
||||||
|
static int available(int descriptor);
|
||||||
|
|
||||||
static bool has_descriptor(int descriptor);
|
static bool has_descriptor(int descriptor);
|
||||||
|
|
||||||
static bool is_readable(int descriptor);
|
static bool is_readable(int descriptor);
|
||||||
|
|
|
||||||
|
|
@ -397,6 +397,20 @@ static int l_flush_descriptor(lua::State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_available_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");
|
||||||
|
}
|
||||||
|
|
||||||
|
return lua::pushinteger(L, scripting::descriptors_manager::available(descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
static int l_close_descriptor(lua::State* L) {
|
static int l_close_descriptor(lua::State* L) {
|
||||||
int descriptor = lua::tointeger(L, 1);
|
int descriptor = lua::tointeger(L, 1);
|
||||||
|
|
||||||
|
|
@ -443,6 +457,7 @@ const luaL_Reg filelib[] = {
|
||||||
{"__write_descriptor", lua::wrap<l_write_descriptor>},
|
{"__write_descriptor", lua::wrap<l_write_descriptor>},
|
||||||
{"__seek_descriptor", lua::wrap<l_seek_descriptor>},
|
{"__seek_descriptor", lua::wrap<l_seek_descriptor>},
|
||||||
{"__flush_descriptor", lua::wrap<l_flush_descriptor>},
|
{"__flush_descriptor", lua::wrap<l_flush_descriptor>},
|
||||||
|
{"__available_descriptor", lua::wrap<l_available_descriptor>},
|
||||||
{"__close_descriptor", lua::wrap<l_close_descriptor>},
|
{"__close_descriptor", lua::wrap<l_close_descriptor>},
|
||||||
{"__close_all_descriptors", lua::wrap<l_close_all_descriptors>},
|
{"__close_all_descriptors", lua::wrap<l_close_all_descriptors>},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue