summaryrefslogtreecommitdiff
path: root/src/lib/ecore/efl_io_buffered_stream.eo
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ecore/efl_io_buffered_stream.eo')
-rw-r--r--src/lib/ecore/efl_io_buffered_stream.eo251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/lib/ecore/efl_io_buffered_stream.eo b/src/lib/ecore/efl_io_buffered_stream.eo
new file mode 100644
index 0000000..28049c4
--- /dev/null
+++ b/src/lib/ecore/efl_io_buffered_stream.eo
@@ -0,0 +1,251 @@
1class Efl.Io.Buffered_Stream (Efl.Loop_User, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer) {
2 [[A wrapper object offering an easy to use, buffered streams over existing I/O class.
3
4 The buffered stream encapsulates an actual @Efl.Io.Reader or
5 @Efl.Io.Writer, an input @Efl.Io.Queue, an output @Efl.Io.Queue
6 and these are linked using a input and a output
7 @Efl.Io.Copier.
8
9 The idea is that unlike traditional @Efl.Io.Writer that will
10 attempt to write directly and thus may take less data than
11 requested, this one will keep the pending data in its own
12 buffer, feeding to the actual output when it
13 @Efl.Io.Writer.can_write. That makes its operation much simpler
14 as @Efl.Io.Writer.write will always take the full data -- allows
15 "write and forget", if unlimited (see
16 @.max_queue_size_output). When finished writing data, the
17 @.eos_mark and then wait for "write,finished" event to know when all data
18 was sent.
19
20 Reading is also much simpler since incoming data is kept in an
21 @Efl.Io.Queue, thus its size can be queried with @.pending_read
22 and read with @Efl.Io.Reader.read or peeked with @.slice_get,
23 then discarded with @.discard or @.clear.
24
25 Then when waiting for a complete message, just peek at its
26 contents, if not complete do nothing and wait, if complete then
27 either @Efl.Io.Reader.read to get a copy or manipulate a
28 read-only reference from @.slice_get and then @.discard
29
30 The actual I/O is set with the constructor method @.inner_io.set
31 and can be retrieved with @.inner_io.get, which should be used
32 with care -- calling @Efl.Io.Reader.read and
33 @Efl.Io.Writer.write on it may produce unexpected results.
34
35 @since 1.19
36 ]]
37
38 methods {
39 @property inner_io {
40 [[The inner I/O this wrapper operates on.]]
41 get {
42 [[The internal input/output used for actual operations, use with care!]]
43 }
44 set {
45 [[Constructor-only property to set the inner_io.]]
46 }
47 values {
48 io: Efl.Object; [[The input (@Efl.Io.Reader) or output (@Efl.Io.Writer) instance]]
49 }
50 }
51
52 @property max_queue_size_input {
53 [[Limit how big the input queue can grow, in bytes.
54
55 If limited and @.line_delimiter is set, "line" events
56 may be emitted with partial contents, without the
57 trailing delimiter.
58 ]]
59 get { }
60 set {
61 [[Constructor-only property to set buffer limit. 0 is unlimited]]
62 }
63 values {
64 max_queue_size_input: size; [[Defines a maximum buffer size for incoming data, or 0 to allow unlimited amount of bytes]]
65 }
66 }
67
68 @property max_queue_size_output {
69 [[Limit how big the output queue can grow, in bytes.
70
71
72 If limited, @Efl.Io.Writer.write will take less data than requested!
73 ]]
74 get { }
75 set {
76 [[Constructor-only property to set buffer limit. 0 is unlimited]]
77 }
78 values {
79 max_queue_size_output: size; [[Defines a maximum buffer size for output data, or 0 to allow unlimited amount of bytes. If limited, @Efl.Io.Writer.write will take less data than requested!]]
80 }
81 }
82
83 @property line_delimiter {
84 [[If set, incoming data will be checked for the delimiter and "line" events are The line may include the delimiter, unless it's end-of-stream on @.max_queue_size_input was reached.]]
85 get { }
86 set {
87 [[Change line delimiter to use. If NULL or empty, no delimiter is to be used]]
88 }
89 values {
90 slice: ptr(const(Eina.Slice)); [[The contents may contain \0 and will be copied]]
91 }
92 }
93
94 @property inactivity_timeout {
95 [[Error as ETIMEDOUT if it becomes inactive for some time.
96
97 If no activity, that is no read or write in the given
98 amount of seconds, then the object will emit "error"
99 event with ETIMEDOUT value.
100
101 This is specified in seconds and is only active for
102 greater-than zero. Defaults to inactive.
103 ]]
104 values {
105 seconds: double; [[Number inactive seconds to timeout this object. If zero or less, it will be disabled.]]
106 }
107 }
108
109 @property read_chunk_size {
110 [[Read chunk size property, in bytes.
111
112 When reading the @.inner_io for data to be placed in
113 input queue, use this as chunk size.
114
115 Setting this value large enough may reduce number of
116 @Efl.Io.Reader.read, improving performance at the expense
117 of more memory consumption.
118
119 This value is bounded by @.max_queue_size_input if it's set.
120
121 By default it's 4096.
122 ]]
123 get {
124 }
125 set {
126 [[Set chunk size for each basic @Efl.Io.Reader.read operation.]]
127 }
128 values {
129 size: size; [[This is the chunk size to use for read operations]]
130 }
131 }
132
133 @property pending_write {
134 [[How many bytes are pending write to @.inner_io]]
135 get { }
136 values {
137 usage: size; [[Bytes available to write]]
138 }
139 }
140
141 @property pending_read {
142 [[How many bytes are pending (available) for read]]
143 get { }
144 values {
145 usage: size; [[Bytes available to read]]
146 }
147 }
148
149 slice_get { // TODO: property and return of Eina.Slice (not pointer)
150 [[Get a temporary access to input queue's internal read memory.
151
152 The memory pointed by slice may be changed by other
153 methods of this class. The event "slice,changed" will be
154 called in those situations.
155 ]]
156 params {
157 @out slice: Eina.Slice; [[Slice of the current buffer, may be invalidated if @Efl.Io.Writer.write, @Efl.Io.Closer.close or @Efl.Io.Reader.read are called. It is the full slice available for reading.]]
158 }
159 return: bool (false); [[$true on success, $false otherwise]]
160 }
161
162 discard {
163 [[Discard the given number of bytes.
164
165 This has the same effect as reading and discarding the
166 given amount of bytes, without executing the actual
167 copy.
168
169 It's often paired with @.slice_get, if users read the
170 information from the slice and once they're done, that
171 data must be discarded.
172
173 As an example, some protocols provide messages with a
174 "size" header, then @.slice_get is used to peek into the
175 available memory to see if there is a "size" and if the
176 rest of the slice is the full payload, in this case the
177 slice may be handled to some processing function. When
178 the function is done, that amount of data must be
179 discarded -- with this function.
180 ]]
181 params {
182 amount: size; [[Bytes to discard]]
183 }
184 }
185
186 clear {
187 [[Clear the incoming queue. Same as reading all data.
188
189 This is equivalent as calling @.discard with @.pending_read
190 amount of bytes.
191 ]]
192 }
193
194 eos_mark {
195 [[Mark this end-of-stream, signals nothing else will be written.
196
197 That will forbid any further writes.
198
199 Unlike @Efl.Io.Closer.close, this won't clear anything.
200
201 When all data is written, "write,finished" is emitted.
202 ]]
203 }
204
205 flush {
206 [[Forces writing all pending data to destination.
207
208 It will return $true if @.pending_read drops to zero, $false
209 otherwise and more calls to flush must be made.
210
211 If the @.inner_io is implements @Efl.Io.Closer and it
212 was closed, or the wrapper itself was closed, this
213 function will do nothing and returns $true.
214
215 \@note this function may block the main loop execution
216 until operations complete! This is bad for usability, as
217 user interface or other operations may freeze. A better
218 approach is to operate asynchronously and wait for
219 "write,finished" event.
220 ]]
221 params {
222 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.]]
223 ignore_line_delimiter: bool; [[Force flush ignoring line delimiters]]
224 }
225 return: bool(true); [[$true if all data was sent, $false otherwise]]
226 }
227 }
228
229 events {
230 write,finished; [[@.eos_mark was called and all available data was sent to destination]]
231 read,finished; [[Same as @Efl.Io.Reader "eos", for consistency.]]
232 finished; [[Both read and write are finished.]]
233 error: Eina.Error; [[An error happened and the I/O stopped]]
234 slice,changed; [[The read-slice returned by @.slice_get may have changed.]]
235 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. Note that the line slice may not be inside @.slice_get, don't assume that!]]
236 }
237
238 implements {
239 Efl.Object.finalize;
240 Efl.Object.destructor;
241 Efl.Io.Closer.close;
242 Efl.Io.Closer.closed.get;
243 Efl.Io.Closer.close_on_exec;
244 Efl.Io.Closer.close_on_destructor;
245 Efl.Io.Reader.read;
246 Efl.Io.Reader.can_read;
247 Efl.Io.Reader.eos;
248 Efl.Io.Writer.write;
249 Efl.Io.Writer.can_write;
250 }
251}