2 #ifndef UVCC_HANDLE_FS__HPP 3 #define UVCC_HANDLE_FS__HPP 5 #include "uvcc/utility.hpp" 6 #include "uvcc/handle-base.hpp" 7 #include "uvcc/handle-io.hpp" 8 #include "uvcc/loop.hpp" 32 friend class handle::uv_interface;
33 friend class handle::instance< file >;
38 using uv_t = ::uv_fs_t;
39 using on_open_t = std::function<
void(
file) >;
47 struct properties :
io::properties
52 ::uv_buf_t uv_buf_struct = { 0,};
53 ::uv_fs_t uv_req_struct = { 0,};
55 std::size_t write_queue_size = 0;
59 struct uv_interface :
handle::uv_fs_interface,
io::uv_interface
61 int is_closing(
void *_uv_fs)
const noexcept override 62 {
return instance::from(_uv_fs)->properties().is_closing; }
64 std::size_t write_queue_size(
void *_uv_handle)
const noexcept override 65 {
return instance::from(_uv_handle)->properties().write_queue_size; }
67 int read_start(
void *_uv_handle, int64_t _offset)
const noexcept override 69 auto instance_ptr = instance::from(_uv_handle);
70 auto &properties = instance_ptr->properties();
72 properties.rd.uv_req_struct.data = instance_ptr;
78 _offset = _telli64(instance_ptr->uv_handle_struct.result);
80 _offset = lseek64(instance_ptr->uv_handle_struct.result, 0, SEEK_CUR);
83 properties.rdoffset = _offset;
85 return file_read(instance_ptr);
88 int read_stop(
void *_uv_handle)
const noexcept override {
return 0; }
99 explicit file(
uv::
loop::uv_t *_loop, ::uv_file _fd,
const char *_path)
101 uv_handle = instance::create();
102 static_cast< uv_t* >(uv_handle)->loop = _loop;
103 static_cast< uv_t* >(uv_handle)->result = _fd;
104 static_cast< uv_t* >(uv_handle)->path = _path;
105 if (_fd < 0) instance::from(uv_handle)->properties().is_closing = 1;
106 instance::from(uv_handle)->book_loop();
109 explicit file(uv_t *_uv_handle) :
io(
static_cast<
io::uv_t* >(_uv_handle)) {}
115 file(
const file&) =
default;
116 file& operator =(
const file&) =
default;
118 file(
file&&)
noexcept =
default;
119 file& operator =(
file&&)
noexcept =
default;
129 file(
uv::
loop &_loop,
const char *_path,
int _flags,
int _mode)
131 uv_handle = instance::create();
133 auto uv_ret = uv_status(::uv_fs_open(
134 static_cast<
uv::
loop::uv_t* >(_loop),
static_cast< uv_t* >(uv_handle),
135 _path, _flags, _mode,
138 if (uv_ret >= 0) instance::from(uv_handle)->book_loop();
142 file(
uv::
loop &_loop,
const char *_path,
int _flags,
int _mode,
const on_open_t &_open_cb)
146 new (
this)
file(_loop
, _path
, _flags
, _mode
);
150 uv_handle = instance::create();
152 auto instance_ptr = instance::from(uv_handle);
155 instance_ptr->properties().open_cb = _open_cb;
158 auto uv_ret = ::uv_fs_open(
159 static_cast< uv::loop::uv_t* >(_loop),
static_cast< uv_t* >(uv_handle),
160 _path, _flags, _mode,
164 instance_ptr->book_loop();
168 instance_ptr->unref();
176 template<
typename =
void >
static void open_cb(::uv_fs_t*);
177 template<
typename =
void >
static void read_cb(::uv_fs_t*);
179 static int file_read(instance *_instance_ptr)
181 auto &properties = _instance_ptr->properties();
183 io_alloc_cb(&_instance_ptr->uv_handle_struct, 65536, &properties.rd.uv_buf_struct);
186 _instance_ptr->uv_handle_struct.loop, &properties.rd.uv_req_struct,
187 _instance_ptr->uv_handle_struct.result,
188 &properties.rd.uv_buf_struct, 1,
196 std::size_t
write_queue_size()
const noexcept {
return instance::from(uv_handle)->properties().write_queue_size; }
203 ::
uv_file fd()
const noexcept {
return static_cast< uv_t* >(uv_handle)->result; }
207 const char*
path()
const noexcept {
return static_cast< uv_t* >(uv_handle)->path; }
210 explicit operator
const uv_t*()
const noexcept {
return static_cast<
const uv_t* >(uv_handle); }
211 explicit operator uv_t*()
noexcept {
return static_cast< uv_t* >(uv_handle); }
215 void file::open_cb(::uv_fs_t *_uv_handle)
217 auto instance_ptr = instance::from(_uv_handle);
218 instance_ptr->uv_error = _uv_handle->result;
220 ref_guard< instance > unref_req(*instance_ptr, adopt_ref);
222 auto &open_cb = instance_ptr->properties().open_cb;
223 if (open_cb) open_cb(file(_uv_handle));
227 void file::read_cb(::uv_fs_t *_uv_req)
229 auto instance_ptr =
static_cast< instance* >(_uv_req->data);
230 auto &properties = instance_ptr->properties();
232 ssize_t nread = _uv_req->result == 0 ? UV_EOF : _uv_req->result;
235 buffer::instance::from(buffer::instance::uv_buf::from(properties.rd.uv_buf_struct.base))->unref();
236 properties.rd.uv_buf_struct = ::uv_buf_init(
nullptr, 0);
239 io_read_cb(&instance_ptr->uv_handle_struct, nread , &properties.rd.uv_buf_struct,
nullptr);
241 ::uv_fs_req_cleanup(_uv_req);
243 switch (properties.rdcmd_state)
252 instance_ptr->uv_error = 0;
253 auto uv_ret = file_read(instance_ptr);
254 if (uv_ret < 0) instance_ptr->uv_error = uv_ret;
268 friend class handle::uv_interface;
269 friend class handle::instance< fs_event >;
273 using uv_t = ::uv_fs_event_t;
274 using on_fs_event_t = std::function<
void(
fs_event _handle,
const char *_filename,
int _events) >;
284 enum class opcmd { UNKNOWN, STOP, START };
286 struct properties :
handle::properties
288 opcmd opcmd_state = opcmd::UNKNOWN;
291 on_fs_event_t fs_event_cb;
294 struct uv_interface :
handle::uv_handle_interface {};
303 template <
typename =
void >
static void fs_event_cb(::uv_fs_event_t*,
const char*,
int,
int);
307 explicit fs_event(uv_t *_uv_handle) :
handle(
reinterpret_cast<
handle::uv_t* >(_uv_handle)) {}
311 ~fs_event() =
default;
313 fs_event(
const fs_event&) =
default;
316 fs_event(
fs_event&&)
noexcept =
default;
322 uv_handle = instance::create();
324 auto uv_ret = ::uv_fs_event_init(
static_cast<
uv::
loop::uv_t* >(_loop),
static_cast< uv_t* >(uv_handle));
325 instance::from(uv_handle)->properties().event_flags = _event_flags;
327 if (uv_status(uv_ret) < 0)
return;
329 instance::from(uv_handle)->book_loop();
334 std::string&
path()
const noexcept {
return instance::from(uv_handle)->properties().path; }
337 on_fs_event_t&
on_fs_event()
const noexcept {
return instance::from(uv_handle)->properties().fs_event_cb; }
346 auto instance_ptr = instance::from(uv_handle);
347 auto &properties = instance_ptr->properties();
349 auto opcmd_state0 = properties.opcmd_state;
351 properties.opcmd_state = opcmd::START;
354 switch (opcmd_state0)
360 uv_status(::uv_fs_event_stop(
static_cast< uv_t* >(uv_handle)));
361 instance_ptr->unref();
366 auto uv_ret = ::uv_fs_event_start(
static_cast< uv_t* >(uv_handle), fs_event_cb, properties.path.c_str(), properties.event_flags);
370 properties.opcmd_state = opcmd::UNKNOWN;
371 instance_ptr->unref();
390 int start(_Cb_ &&_cb, _Args_&&... _args)
const 392 instance::from(uv_handle)->properties().fs_event_cb = std::bind(
393 std::forward< _Cb_ >(_cb), std::placeholders::_1, std::placeholders::_2, std::forward< _Args_ >(_args)...
412 int start(std::string _path, _Cb_ &&_cb, _Args_&&... _args)
const 414 instance::from(uv_handle)->properties().path = std::move(_path);
415 instance::from(uv_handle)->properties().fs_event_cb = std::bind(
416 std::forward< _Cb_ >(_cb), std::placeholders::_1, std::placeholders::_2, std::forward< _Args_ >(_args)...
424 auto instance_ptr = instance::from(uv_handle);
425 auto &opcmd_state = instance_ptr->properties().opcmd_state;
427 auto opcmd_state0 = opcmd_state;
428 opcmd_state = opcmd::STOP;
430 auto uv_ret = uv_status(::uv_fs_event_stop(
static_cast< uv_t* >(uv_handle)));
432 switch (opcmd_state0)
438 instance_ptr->unref();
446 explicit operator
const uv_t*()
const noexcept {
return static_cast<
const uv_t* >(uv_handle); }
447 explicit operator uv_t*()
noexcept {
return static_cast< uv_t* >(uv_handle); }
451 void fs_event::fs_event_cb(::uv_fs_event_t *_uv_handle,
const char *_filename,
int _events,
int _status)
453 auto instance_ptr = instance::from(_uv_handle);
454 instance_ptr->uv_error = _status;
455 auto &fs_event_cb = instance_ptr->properties().fs_event_cb;
456 if (fs_event_cb) fs_event_cb(fs_event(_uv_handle), _filename, _events);
Namespace for all uvcc definitions.
int start(std::string _path, _Cb_ &&_cb, _Args_ &&... _args) const
Start the handle with the given callback, watching for the specified FS path.
fs_event(uv::loop &_loop, int _event_flags)
Create an fs_event.
int stop() const noexcept
Stop the handle, the callback will no longer be called.
std::string & path() const noexcept
Set the FS path being monitored by this handle.
int start() const
Start the handle.
file(uv::loop &_loop, const char *_path, int _flags, int _mode)
Open and possibly create a file synchronously.
The base class for the libuv handles.
The I/O event loop class.
The base class for handles representing I/O endpoints: a file, TCP/UDP socket, pipe, TTY.
A scoped reference counting guard.
int start(_Cb_ &&_cb, _Args_ &&... _args) const
Start the handle with the given callback.
file(uv::loop &_loop, const char *_path, int _flags, int _mode, const on_open_t &_open_cb)
Open and possibly create a file asynchronously.
const char * path() const noexcept
The file path.
::uv_file fd() const noexcept
Get the cross platform representation of the file handle.
file(uv::loop &_loop, ::uv_file _fd)
Create a file object from an existing file descriptor.
on_fs_event_t & on_fs_event() const noexcept
Set the FS event callback.
std::size_t write_queue_size() const noexcept
The amount of bytes waiting to be written to the file.