2016-08-13 00:50:29 -07:00
import eina_types;
2018-04-12 04:56:02 -07:00
class Efl.Io.Copier (Efl.Loop_Consumer, Efl.Io.Closer) {
2016-08-13 00:50:29 -07:00
[[Copy from an @Efl.Io.Reader source to @Efl.Io.Writer destination.
During usage it will keep reference to @.source and
@.destination objects, automatically relasing them on
2017-12-20 01:41:41 -08:00
destruction.
2016-08-13 00:50:29 -07:00
By default the read-write process is done based on fixed-size
2017-12-20 01:41:41 -08:00
chunks (@.read_chunk_size) but if @.line_delimiter is set,
the behavior changes to wait for said delimiter or until a maximum
2016-08-13 00:50:29 -07:00
buffer limit is reached (@.buffer_limit).
2016-11-24 09:22:45 -08:00
While a @.source is mandatory for the copier to operate
2017-12-20 01:41:41 -08:00
properly the @.destination is optional: if it's not provided,
2016-11-24 09:22:45 -08:00
all read data is stored in an internal buffer that can be
retrieved using @.binbuf_steal, usually called when one of
"data", "line" or "done" events are emitted.
Most important events:
- The "data" event is general and notifies some data was
written to @.destination (if any, otherwise it will be
2017-12-20 01:41:41 -08:00
reported as data when it's read from @.source).
2016-11-24 09:22:45 -08:00
- The "line" event is only emitted when @.line_delimiter is
set and not empty. It's simiar to "data".
- The "done" event is emitted if @.source is
@Efl.Io.Reader.eos $true and all data was written to
@.destination (if any, otherwise it will be reported when
2017-12-20 01:41:41 -08:00
all data is read from @.source).
2016-11-24 09:22:45 -08:00
- The "error" event is reported if the @Efl.Io.Reader.read,
2017-12-20 01:41:41 -08:00
@Efl.Io.Writer.write or some other internal error occurs,
such as being out of memory. Another common error is ETIMEDOUT if
2016-12-11 07:19:46 -08:00
@.timeout_inactivity is set.
2016-11-24 09:22:45 -08:00
2017-12-20 01:41:41 -08:00
A copier is handy for simplifying common I/O use cases, such as:
2016-11-24 09:22:45 -08:00
2017-12-20 01:41:41 -08:00
- Reading a file or download content to memory: provide only the
2016-11-24 09:22:45 -08:00
source and wait for "done" event, calling @.binbuf_steal
afterwards.
2017-12-20 01:41:41 -08:00
- Downloading content to disk: provide a network socket as source
2016-11-24 09:22:45 -08:00
and use @Efl.Io.File as destination, then wait for "done"
event.
2017-12-20 01:41:41 -08:00
- Linking two I/O streams: provide both source and destination
2016-11-24 09:22:45 -08:00
streams, such as @Efl.Io.Stdin and @Efl.Io.Stdout, or some
network socket. As data is received from source it will be
copied to destination in an endless (asynchronous) loop. You
2017-12-20 01:41:41 -08:00
may monitor for "done" if the source is closed.
2016-11-24 09:22:45 -08:00
2016-08-13 00:50:29 -07:00
If @Efl.Io.Closer.close is called, then it will be called on
@.source and @.destination if they implement those interfaces.
2016-09-12 08:23:29 -07:00
@Efl.Io.Closer.close_on_exec and
2018-04-17 16:17:29 -07:00
@Efl.Io.Closer.close_on_invalidate are respected and applied to
2016-09-12 08:23:29 -07:00
both source and destination. Both default to $true.
2016-08-13 00:50:29 -07:00
@since 1.19
]]
methods {
@property source {
2016-11-24 09:22:45 -08:00
[[Copier source object.
The source object must implement the @Efl.Io.Reader
interface and will provide data to the copier, thus it
must be provided in order for the copier to work.
The copier will monitor @Efl.Io.Reader.can_read property
2017-12-20 01:41:41 -08:00
and "can_read,changed" event. When $true a
chunk (limited by @.read_chunk_size) is read using
2016-11-24 09:22:45 -08:00
@Efl.Io.Reader.read into an intermediate storage buffer
2017-12-20 01:41:41 -08:00
which can grow up to the @.buffer_limit.
2016-11-24 09:22:45 -08:00
2017-12-20 01:41:41 -08:00
If there's a @.destination, the read data is written
2016-11-24 09:22:45 -08:00
there and afterwards "data" and "line" events are
dispatched. If no destination, it's accumulated in the
internal storage and "data" and "line" events are
dispatched immediately.
If there is a @.line_delimiter set, then copier will use
that in order to attempt to write a full line at a time,
including the delimiter. Exceptions may be if the
@.source object emitted "eos" and there is no trailing
2017-12-20 01:41:41 -08:00
delimiter (ie: missing trailing newline in files) or if the
@.buffer_limit is reached.
2016-11-24 09:22:45 -08:00
Once @Efl.Io.Reader.eos is $true or "eos" event happen,
then the read process is over. If there is no
@.destination set, then the process is over and "done"
2017-12-20 01:41:41 -08:00
event is called. If there's a @.destination, then all
2016-11-24 09:22:45 -08:00
data must be flushed to it, draining the internal
2017-12-20 01:41:41 -08:00
intermediate storage before "done" event is emitted.
2016-11-24 09:22:45 -08:00
If the source object implements @Efl.Io.Sizer interface,
then the @.progress will report the total size. If the
2017-12-20 01:41:41 -08:00
destination object also implements @Efl.Io.Sizer then it
will be resized to match the source size/ It also offers
hints to enhance performance such as pre-allocating
the total amount and avoid dynamic resize.
2016-11-24 09:22:45 -08:00
If the source object implements @Efl.Io.Closer and it's
not closed, it will be closed when the copier itself
is. This may happen, for example, when the copier is
2018-04-17 16:17:29 -07:00
deleted and @Efl.Io.Closer.close_on_invalidate is $true
2016-11-24 09:22:45 -08:00
(the default).
Common source classes are @Efl.Io.Buffer (if fixed data
exists in memory), @Efl.Io.Queue (used to stream
in-memory data) and @Efl.Io.File (data is present in the
file system). Networking classes are also common source
objects.
]]
2016-08-13 00:50:29 -07:00
get {
}
set {
[[Constructor-only property to set where to read data from]]
}
values {
2016-11-24 09:22:45 -08:00
source: Efl.Io.Reader; [[@Efl.Io.Reader source]]
2016-08-13 00:50:29 -07:00
}
}
@property destination {
2016-11-24 09:22:45 -08:00
[[Copier destination object.
If set it must implement @Efl.Io.Writer interface and
will receive read data once @Efl.Io.Writer.can_write
2017-12-20 01:41:41 -08:00
reports $true, this is monitored using the
2016-11-24 09:22:45 -08:00
"can_write,changed" event.
The copier will attempt to write all internal
intermediate storage data at once, however the
destination object may consume less. The actual data
written is emitted in the "data" and "line" events.
2017-12-20 01:41:41 -08:00
If there is an @.line_delimiter set then copier will use
it in order to attempt to write one full line at a time,
2016-11-24 09:22:45 -08:00
including the delimiter. Exceptions may be if the
@.source object emitted "eos" and there is no trailing
delimiter (ie: missing trailing newline in files), or the
2017-12-20 01:41:41 -08:00
@.buffer_limit is reached.
2016-11-24 09:22:45 -08:00
2017-12-20 01:41:41 -08:00
If @.source is flagged "eos" and all data is written to the
destination then the "done" event is emitted.
2016-11-24 09:22:45 -08:00
2017-12-20 01:41:41 -08:00
If the destination is not set (ie: NULL) then data is kept
in a internal @Eina.Binbuf, which can be stolen with
2016-11-24 09:22:45 -08:00
@.binbuf_steal once "data" or "line" events are
2017-12-20 01:41:41 -08:00
emitted. It exists as a useful shortcut to easily drain
readers and store all data in memory with no need to use an
@Efl.Io.Buffer or @Efl.Io.Copier -- a source
and copier are enough.
2016-11-24 09:22:45 -08:00
If both source and destination object implements
2017-12-20 01:41:41 -08:00
@Efl.Io.Sizer, then the destination will be resized to match
the source size. It also offers hints to enhance
performance such as pre-allocating the total amount and
avoid dynamic resize.
2016-11-24 09:22:45 -08:00
If the destination object implements @Efl.Io.Closer and it's
not closed, it will be closed when the copier itself
is. This may happen, for example, when the copier is
2018-04-17 16:17:29 -07:00
deleted and @Efl.Io.Closer.close_on_invalidate is $true
2016-11-24 09:22:45 -08:00
(the default).
Common destination classes are @Efl.Io.Buffer (better to
wait for all data in memory), @Efl.Io.Queue (to handle
streaming protocols) and @Efl.Io.File (stores data to
disk). Networking classes are also common destination
objects.
]]
2016-08-13 00:50:29 -07:00
get {
}
set {
[[Constructor-only property to set where to write data to]]
}
values {
2016-11-24 09:22:45 -08:00
destination: Efl.Io.Writer; [[@Efl.Io.Writer destination]]
2016-08-13 00:50:29 -07:00
}
}
@property line_delimiter {
2017-12-20 01:41:41 -08:00
[[If there is a line delimiter, reads will buffer/queue up to the line delimiter before calling @Efl.Io.Writer.write on the @.destination and the event line is emitted with the current line. The line may include the delimiter unless it's end-of-stream on @.source or @.buffer_limit was reached.]]
2016-08-13 00:50:29 -07:00
get { }
set {
docs: Fix typos and some wrong expressions in Ecore, Ecore_Audio, Ecore_Cocoa, Ecore_Con, and Ector API reference doxygen.
Summary: I had fixed some typos and wrong expressions, such as capital letters, $simbols in .eo and singulars in Ecore, Ecore_Audio, Ecore_Cocoa, Ecore_Con, and Ector API reference doxygen.
Test Plan: Doxygen Revision
Reviewers: Jaehyun_Cho, stefan, jpeg, cedric, raster
Reviewed By: Jaehyun_Cho
Differential Revision: https://phab.enlightenment.org/D4943
2017-06-06 21:01:13 -07:00
[[Changes line delimiter to use. If empty, no delimiter is to be used]]
2016-08-13 00:50:29 -07:00
}
values {
2017-08-10 03:53:14 -07:00
slice: const(Eina.Slice); [[The contents may contain \0 and will be copied]]
2016-08-13 00:50:29 -07:00
}
}
@property buffer_limit {
2016-11-24 09:22:45 -08:00
[[Copier buffer limit property, in bytes.
During the read-write cycle, an intermediate storage
2017-12-20 01:41:41 -08:00
buffer is used. By default it's zero -- unlimited and
2016-11-24 09:22:45 -08:00
will grow as needed if @.source provides data and
@.destination do not consume it (or if there is no
@.destination).
2017-12-20 01:41:41 -08:00
However when reading data from untrusted sources like
network system memory can be exhausted by flooding
the copier. In these cases using a buffer limit is
2016-11-24 09:22:45 -08:00
recommended.
2017-12-20 01:41:41 -08:00
When the buffer limit is reached the copier will pause
2016-11-24 09:22:45 -08:00
reading data from @.source until @.destination consumes
it. If there is no @.destination set, user should call
@.binbuf_steal to consume data and reset buffer usage.
Setting a buffer limit smaller than current
@.read_chunk_size will automatically change
@.read_chunk_size to the new buffer limit.
]]
2016-08-13 00:50:29 -07:00
get {
}
set {
[[Constructor-only property to set buffer limit. 0 is unlimited]]
}
values {
size: size; [[Defines a maximum buffer limit, or 0 to allow unlimited amount of bytes]]
}
}
@property read_chunk_size {
2016-11-24 09:22:45 -08:00
[[Copier read chunk size property, in bytes.
When a @.source is flagged with @Efl.Io.Reader.can_read
$true, data will be read using @Efl.Io.Reader.read into
an intermediate buffer of this size.
Setting this value large enough may reduce number of
@Efl.Io.Reader.read, improving performance at the expense
of more memory consumption.
This value is bounded by @.buffer_limit if it's set.
By default it's 4096.
]]
2016-08-13 00:50:29 -07:00
get {
}
set {
[[Set chunk size for each basic @Efl.Io.Reader.read operation.]]
}
values {
size: size; [[This is the chunk size to use for read operations]]
}
}
@property progress {
2016-11-24 09:22:45 -08:00
[[Progress for read and write.
Reports value read from @.source, written to
@.destination and the total, if the source implements
@Efl.Io.Sizer.
]]
2016-08-13 00:50:29 -07:00
get {
}
values {
2016-11-11 01:58:22 -08:00
read: uint64 @optional; [[Amount of bytes read from source]]
written: uint64 @optional; [[Amount of bytes written to destination]]
2016-08-13 00:50:29 -07:00
total: uint64 @optional; [[If @.source is an Efl.Io.Sizer, its total size. Otherwise 0 to report unknown size]]
}
}
2016-12-11 07:19:46 -08:00
@property timeout_inactivity {
docs: Fix typos and some wrong expressions in Ecore, Ecore_Audio, Ecore_Cocoa, Ecore_Con, and Ector API reference doxygen.
Summary: I had fixed some typos and wrong expressions, such as capital letters, $simbols in .eo and singulars in Ecore, Ecore_Audio, Ecore_Cocoa, Ecore_Con, and Ector API reference doxygen.
Test Plan: Doxygen Revision
Reviewers: Jaehyun_Cho, stefan, jpeg, cedric, raster
Reviewed By: Jaehyun_Cho
Differential Revision: https://phab.enlightenment.org/D4943
2017-06-06 21:01:13 -07:00
[[Terminates the copier with ETIMEDOUT if it becomes inactive for some time.
2016-10-22 05:52:22 -07:00
2017-12-20 01:41:41 -08:00
If the copier cannot perform any reads or writes in the given
amount of seconds then the copier will emit "error"
2016-10-22 05:52:22 -07:00
event with ETIMEDOUT value.
This is specified in seconds and is only active for
greater-than zero. Defaults to inactive.
]]
values {
seconds: double; [[Number inactive seconds to timeout this copier. If zero or less, it will be disabled.]]
}
}
2016-11-25 08:22:13 -08:00
@property done {
[[Reports if copier is done.
A copier is done if source reached "eos" and all data
2017-12-20 01:41:41 -08:00
is written to "destination".
2016-11-25 08:22:13 -08:00
The copier is also done when it's @Efl.Io.Closer.closed.
]]
get { }
set @protected { }
values {
done: bool; [[If $true, source is "eos" and all data was written to "destination". If $false, it's still pending some more copies]]
}
}
2016-08-13 00:50:29 -07:00
binbuf_steal {
2017-12-20 01:41:41 -08:00
[[Steals the internal binbuf and returns it to caller.
2016-08-13 00:50:29 -07:00
2017-12-20 01:41:41 -08:00
The buffer is then owned by caller which should call
2016-08-13 00:50:29 -07:00
eina_binbuf_free() when it's done.
2016-11-24 09:22:45 -08:00
Usually call this method when no @.destination is set, in
2017-12-20 01:41:41 -08:00
which case you should wait for "done", "data" or "line"
events and then call it to retrieve and own the data.
2016-08-13 00:50:29 -07:00
]]
2017-09-22 07:08:56 -07:00
return: ptr(Eina.Binbuf) @owned @warn_unused; [[Binbuf]]
2016-08-13 00:50:29 -07:00
}
2016-11-22 21:11:26 -08:00
2016-12-07 11:31:48 -08:00
@property pending_size {
[[Returns the size of the pending buffer.
The pending buffer is an intermediate buffer where data
is read from @.source before it's written to
@.destination, if any.
This is the equivalent of the size of returned by
2017-12-20 01:41:41 -08:00
@.binbuf_steal however it doesn't steal or modify the
buffer at all, just queries its internal size.
2016-12-07 11:31:48 -08:00
]]
get { }
values {
size: size; [[The pending buffer size, in bytes.]]
}
}
2016-11-22 21:11:26 -08:00
flush {
[[Forces reading from source and writing to destination.
2017-12-20 01:41:41 -08:00
This executes a single read->write cycle if more data
can be read from source (ie: not EOS) or not all data
is written to destination, then $false is
returned. To forcefully drain source and write all
2016-11-22 21:11:26 -08:00
contents to destination, use in a loop until it returns
$true.
2017-12-20 01:41:41 -08:00
The return value matches the "done" event: that is, when
2016-11-22 21:11:26 -08:00
$true is returned, the "done" event is emitted.
This function may also emit "progress" and "error"
events.
\@note this function may block the main loop execution
2017-12-20 01:41:41 -08:00
until operations are complete! This is bad for usability as
2016-11-22 21:11:26 -08:00
user interface or other operations may freeze. A better
2017-12-20 01:41:41 -08:00
approach is to operate asynchronously and wait for the
2016-11-22 21:11:26 -08:00
"done" event.
]]
2016-11-25 10:48:45 -08:00
params {
may_block: bool; [[If $true, then @Efl.Io.Reader.can_read and @Efl.Io.Writer.can_write are not checked and the call may block.]]
docs: Fix typos and some wrong expressions in Ecore, Ecore_Audio, Ecore_Cocoa, Ecore_Con, and Ector API reference doxygen.
Summary: I had fixed some typos and wrong expressions, such as capital letters, $simbols in .eo and singulars in Ecore, Ecore_Audio, Ecore_Cocoa, Ecore_Con, and Ector API reference doxygen.
Test Plan: Doxygen Revision
Reviewers: Jaehyun_Cho, stefan, jpeg, cedric, raster
Reviewed By: Jaehyun_Cho
Differential Revision: https://phab.enlightenment.org/D4943
2017-06-06 21:01:13 -07:00
ignore_line_delimiter: bool; [[Forces flush ignoring line delimiters]]
2016-11-25 10:48:45 -08:00
}
2016-11-24 06:16:59 -08:00
return: bool(true); [[$true on success, $false otherwise]]
2016-11-22 21:11:26 -08:00
}
2016-08-13 00:50:29 -07:00
}
events {
efl: Add missing event types
Summary:
All events must have a type now, otherwise bindings don't know how to handle
the event_info field.
Most of the missing event types were actually "void" (no event_info present).
Some struct definitions had to be moved to eo instead of h files, so they
are available to bindings. Some have not, and are marked with FIXME.
Some namespaces have been fixed (like Efl_Event_Cb -> Efl.Event_Cb).
In general, there are hundreds of changed files, but mostly to add a type which
was not present before, so there's no harm done.
Also, A lot of FIXMEs have been added which should be, like, fixed.
For example, some events can send different types of event_info, which is
very inconvenient (and error prone).
Test Plan: make with c# bindings works, make check and make examples work too.
Reviewers: cedric, q66, lauromoura
Subscribers: zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6169
2018-05-11 08:20:40 -07:00
done: void; [[All available data was copied from source to destination]]
2016-08-13 00:50:29 -07:00
error: Eina.Error; [[An error happened and the copy stopped]]
efl: Add missing event types
Summary:
All events must have a type now, otherwise bindings don't know how to handle
the event_info field.
Most of the missing event types were actually "void" (no event_info present).
Some struct definitions had to be moved to eo instead of h files, so they
are available to bindings. Some have not, and are marked with FIXME.
Some namespaces have been fixed (like Efl_Event_Cb -> Efl.Event_Cb).
In general, there are hundreds of changed files, but mostly to add a type which
was not present before, so there's no harm done.
Also, A lot of FIXMEs have been added which should be, like, fixed.
For example, some events can send different types of event_info, which is
very inconvenient (and error prone).
Test Plan: make with c# bindings works, make check and make examples work too.
Reviewers: cedric, q66, lauromoura
Subscribers: zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6169
2018-05-11 08:20:40 -07:00
progress: void; [[Total size changed or Data was read/written]]
2016-11-03 09:02:24 -07:00
data: ptr(const(Eina.Slice)); [[When data is read to internal buffer, it's emitted in this event. The memory is only valid during event callback dispatched and should not be modified.]]
line: ptr(const(Eina.Slice)); [[If @.line_delimiter is set, will be emitted with current line. The memory is only valid during event callback dispatched and should not be modified.]]
2016-08-13 00:50:29 -07:00
}
implements {
Efl.Object.constructor;
Efl.Object.finalize;
2018-04-17 16:17:29 -07:00
Efl.Object.invalidate;
Efl.Object.destructor;
2016-08-13 00:50:29 -07:00
Efl.Io.Closer.close;
2016-12-27 07:19:06 -08:00
Efl.Io.Closer.closed { get; }
2017-01-11 07:35:03 -08:00
Efl.Io.Closer.close_on_exec { get; set; }
2018-04-17 16:17:29 -07:00
Efl.Io.Closer.close_on_invalidate { get; set; }
2016-08-13 00:50:29 -07:00
}
}