summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-12-19 16:49:29 -0200
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-12-19 16:50:58 -0200
commitc2aedc117ad9271c0ef4e68bbfd3873d9137ed2d (patch)
treeec63072ba79521f90baa3ef96dae0953b8dd3e18 /src
parentecdf56de47d5c96711619e7c8dc1586a0dee7f90 (diff)
efl_io_buffer: adopt read-only and read-write buffers.
todo--, allow buffer backing store to be provided by Eina_Slice (rdonly) or Eina_Rw_Slice (rdwr).
Diffstat (limited to 'src')
-rw-r--r--src/examples/ecore/efl_net_server_example.c8
-rw-r--r--src/lib/efl/interfaces/efl_io_buffer.c94
-rw-r--r--src/lib/efl/interfaces/efl_io_buffer.eo36
3 files changed, 132 insertions, 6 deletions
diff --git a/src/examples/ecore/efl_net_server_example.c b/src/examples/ecore/efl_net_server_example.c
index 22efdd0719..3a9598e2cb 100644
--- a/src/examples/ecore/efl_net_server_example.c
+++ b/src/examples/ecore/efl_net_server_example.c
@@ -343,7 +343,7 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
343 * One can change these to Efl_Io_File or event pipe to something 343 * One can change these to Efl_Io_File or event pipe to something
344 * else like Efl_Io_Stdin, Efl_Io_Stdout and it would just work. 344 * else like Efl_Io_Stdin, Efl_Io_Stdout and it would just work.
345 */ 345 */
346 Eina_Slice slice; 346 static const Eina_Slice hello_world_slice = EINA_SLICE_STR_LITERAL("Hello World!");
347 Send_Recv_Data *d; 347 Send_Recv_Data *d;
348 Eo *send_buffer, *recv_buffer; 348 Eo *send_buffer, *recv_buffer;
349 349
@@ -354,10 +354,8 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
354 return; 354 return;
355 } 355 }
356 356
357 // TODO buffer constructor taking RO string 357 send_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL,
358 send_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL); 358 efl_io_buffer_adopt_readonly(efl_added, hello_world_slice));
359 slice = (Eina_Slice)EINA_SLICE_STR("Hello World!");
360 efl_io_writer_write(send_buffer, &slice, NULL);
361 359
362 /* Unlimited buffer to store the received data. */ 360 /* Unlimited buffer to store the received data. */
363 recv_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL); 361 recv_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL);
diff --git a/src/lib/efl/interfaces/efl_io_buffer.c b/src/lib/efl/interfaces/efl_io_buffer.c
index 66b5338e2f..299fb56bb7 100644
--- a/src/lib/efl/interfaces/efl_io_buffer.c
+++ b/src/lib/efl/interfaces/efl_io_buffer.c
@@ -17,6 +17,7 @@ typedef struct _Efl_Io_Buffer_Data
17 Eina_Bool closed; 17 Eina_Bool closed;
18 Eina_Bool can_read; 18 Eina_Bool can_read;
19 Eina_Bool can_write; 19 Eina_Bool can_write;
20 Eina_Bool readonly;
20} Efl_Io_Buffer_Data; 21} Efl_Io_Buffer_Data;
21 22
22static Eina_Bool 23static Eina_Bool
@@ -25,6 +26,8 @@ _efl_io_buffer_realloc(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
25 void *tmp; 26 void *tmp;
26 size_t limit = efl_io_buffer_limit_get(o); 27 size_t limit = efl_io_buffer_limit_get(o);
27 28
29 EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, EINA_FALSE);
30
28 if ((limit > 0) && (size > limit)) 31 if ((limit > 0) && (size > limit))
29 size = limit; 32 size = limit;
30 33
@@ -77,6 +80,7 @@ _efl_io_buffer_realloc_rounded(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
77EOLIAN static void 80EOLIAN static void
78_efl_io_buffer_preallocate(Eo *o, Efl_Io_Buffer_Data *pd, size_t size) 81_efl_io_buffer_preallocate(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
79{ 82{
83 EINA_SAFETY_ON_TRUE_RETURN(pd->readonly);
80 EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o)); 84 EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
81 if (pd->allocated < size) 85 if (pd->allocated < size)
82 _efl_io_buffer_realloc_rounded(o, pd, size); 86 _efl_io_buffer_realloc_rounded(o, pd, size);
@@ -85,6 +89,7 @@ _efl_io_buffer_preallocate(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
85EOLIAN static void 89EOLIAN static void
86_efl_io_buffer_limit_set(Eo *o, Efl_Io_Buffer_Data *pd, size_t limit) 90_efl_io_buffer_limit_set(Eo *o, Efl_Io_Buffer_Data *pd, size_t limit)
87{ 91{
92 EINA_SAFETY_ON_TRUE_RETURN(pd->readonly);
88 EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o)); 93 EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
89 94
90 if (pd->limit == limit) return; 95 if (pd->limit == limit) return;
@@ -125,6 +130,7 @@ EOLIAN static Eina_Binbuf *
125_efl_io_buffer_binbuf_steal(Eo *o, Efl_Io_Buffer_Data *pd) 130_efl_io_buffer_binbuf_steal(Eo *o, Efl_Io_Buffer_Data *pd)
126{ 131{
127 Eina_Binbuf *ret; 132 Eina_Binbuf *ret;
133 EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, NULL);
128 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), NULL); 134 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), NULL);
129 135
130 ret = eina_binbuf_manage_new(pd->bytes, efl_io_sizer_size_get(o), EINA_FALSE); 136 ret = eina_binbuf_manage_new(pd->bytes, efl_io_sizer_size_get(o), EINA_FALSE);
@@ -166,7 +172,7 @@ _efl_io_buffer_efl_object_destructor(Eo *o, Efl_Io_Buffer_Data *pd)
166 172
167 if (pd->bytes) 173 if (pd->bytes)
168 { 174 {
169 free(pd->bytes); 175 if (!pd->readonly) free(pd->bytes);
170 pd->bytes = NULL; 176 pd->bytes = NULL;
171 pd->allocated = 0; 177 pd->allocated = 0;
172 pd->used = 0; 178 pd->used = 0;
@@ -244,6 +250,7 @@ _efl_io_buffer_efl_io_writer_write(Eo *o, Efl_Io_Buffer_Data *pd, Eina_Slice *sl
244 size_t available, todo, write_pos, limit; 250 size_t available, todo, write_pos, limit;
245 int err = EINVAL; 251 int err = EINVAL;
246 252
253 EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, EPERM);
247 EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINVAL); 254 EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINVAL);
248 EINA_SAFETY_ON_TRUE_GOTO(efl_io_closer_closed_get(o), error); 255 EINA_SAFETY_ON_TRUE_GOTO(efl_io_closer_closed_get(o), error);
249 256
@@ -362,6 +369,13 @@ _efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size)
362 369
363 if (efl_io_sizer_size_get(o) == size) return 0; 370 if (efl_io_sizer_size_get(o) == size) return 0;
364 371
372 if (pd->readonly)
373 {
374 EINA_SAFETY_ON_TRUE_RETURN_VAL(size > pd->used, EPERM);
375 pd->used = size;
376 goto end;
377 }
378
365 old_size = pd->used; 379 old_size = pd->used;
366 pd->used = size; 380 pd->used = size;
367 381
@@ -378,6 +392,7 @@ _efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size)
378 if (old_size < size) 392 if (old_size < size)
379 memset(pd->bytes + old_size, 0, size - old_size); 393 memset(pd->bytes + old_size, 0, size - old_size);
380 394
395 end:
381 pos_read = efl_io_buffer_position_read_get(o); 396 pos_read = efl_io_buffer_position_read_get(o);
382 if (pos_read > size) 397 if (pos_read > size)
383 efl_io_buffer_position_read_set(o, size); 398 efl_io_buffer_position_read_set(o, size);
@@ -500,6 +515,8 @@ _efl_io_buffer_position_write_set(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t positi
500 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), EINA_FALSE); 515 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), EINA_FALSE);
501 516
502 size = efl_io_sizer_size_get(o); 517 size = efl_io_sizer_size_get(o);
518 if (position < size)
519 EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, EINA_FALSE);
503 EINA_SAFETY_ON_TRUE_RETURN_VAL(position > size, EINA_FALSE); 520 EINA_SAFETY_ON_TRUE_RETURN_VAL(position > size, EINA_FALSE);
504 521
505 if (pd->position_write == position) return EINA_TRUE; 522 if (pd->position_write == position) return EINA_TRUE;
@@ -524,4 +541,79 @@ _efl_io_buffer_position_write_get(Eo *o EINA_UNUSED, Efl_Io_Buffer_Data *pd)
524 return pd->position_write; 541 return pd->position_write;
525} 542}
526 543
544EOLIAN static void
545_efl_io_buffer_adopt_readonly(Eo *o, Efl_Io_Buffer_Data *pd, const Eina_Slice slice)
546{
547 Eina_Bool changed_size;
548
549 EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
550
551 if (!pd->readonly) free(pd->bytes);
552 pd->readonly = EINA_TRUE;
553 pd->bytes = (uint8_t *)slice.bytes;
554 pd->allocated = slice.len;
555
556 changed_size = (pd->used != slice.len);
557 pd->used = slice.len;
558 efl_io_writer_can_write_set(o, EINA_FALSE);
559 if (pd->closed) return;
560
561 if (efl_io_buffer_position_read_get(o) > slice.len)
562 {
563 efl_io_buffer_position_read_set(o, slice.len);
564 if (pd->closed) return;
565 }
566
567 efl_io_buffer_position_write_set(o, slice.len);
568 if (pd->closed) return;
569
570 if (changed_size)
571 {
572 efl_event_callback_call(o, EFL_IO_SIZER_EVENT_SIZE_CHANGED, NULL);
573 if (pd->closed) return;
574 }
575
576 efl_event_callback_call(o, EFL_IO_BUFFER_EVENT_REALLOCATED, NULL);
577}
578
579EOLIAN static void
580_efl_io_buffer_adopt_readwrite(Eo *o, Efl_Io_Buffer_Data *pd, Eina_Rw_Slice slice)
581{
582 Eina_Bool changed_size;
583
584 EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
585
586 if (!pd->readonly) free(pd->bytes);
587 pd->readonly = EINA_FALSE;
588 pd->bytes = slice.bytes;
589 pd->allocated = slice.len;
590
591 changed_size = (pd->used != slice.len);
592 pd->used = slice.len;
593
594 efl_io_writer_can_write_set(o, (pd->limit == 0) ||
595 (efl_io_buffer_position_write_get(o) < pd->limit));
596 if (pd->closed) return;
597
598 if (efl_io_buffer_position_read_get(o) > slice.len)
599 {
600 efl_io_buffer_position_read_set(o, slice.len);
601 if (pd->closed) return;
602 }
603
604 if (efl_io_buffer_position_write_get(o) > slice.len)
605 {
606 efl_io_buffer_position_write_set(o, slice.len);
607 if (pd->closed) return;
608 }
609
610 if (changed_size)
611 {
612 efl_event_callback_call(o, EFL_IO_SIZER_EVENT_SIZE_CHANGED, NULL);
613 if (pd->closed) return;
614 }
615
616 efl_event_callback_call(o, EFL_IO_BUFFER_EVENT_REALLOCATED, NULL);
617}
618
527#include "interfaces/efl_io_buffer.eo.c" 619#include "interfaces/efl_io_buffer.eo.c"
diff --git a/src/lib/efl/interfaces/efl_io_buffer.eo b/src/lib/efl/interfaces/efl_io_buffer.eo
index 30b75d2341..ee4d52c6e1 100644
--- a/src/lib/efl/interfaces/efl_io_buffer.eo
+++ b/src/lib/efl/interfaces/efl_io_buffer.eo
@@ -22,6 +22,39 @@ class Efl.Io.Buffer (Efl.Object, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Ef
22 } 22 }
23 } 23 }
24 24
25 adopt_readonly {
26 [[Adopt a read-only slice as buffer's backing store.
27
28 The slice memory will not be copied and must remain
29 alive during buffer's lifetime. Usually this is
30 guaranteed by some global static-const memory or some
31 parent object and this buffer being a view of that -- be
32 aware of parent memory remaining alive, such as
33 "slice,changed" events.
34 ]]
35 params {
36 @in slice: const(Eina.Slice); [[Slice to adopt as read-only]]
37 }
38 }
39
40 adopt_readwrite {
41 [[Adopt a read-write slice as buffer's backing store.
42
43 The slice memory will not be copied and must remain
44 alive during buffer's lifetime. Usually this is
45 guaranteed by some global static memory or some
46 parent object and this buffer being a view of that -- be
47 aware of parent memory remaining alive, such as
48 "slice,changed" events.
49
50 The memory will be disposed using free() and reallocated
51 using realloc().
52 ]]
53 params {
54 @in slice: Eina.Rw_Slice; [[Slice to adopt as read-write]]
55 }
56 }
57
25 @property limit { 58 @property limit {
26 [[Limit how big the buffer can grow. 59 [[Limit how big the buffer can grow.
27 60
@@ -95,6 +128,9 @@ class Efl.Io.Buffer (Efl.Object, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Ef
95 [[Steals the internal buffer memory and returns it as a binbuf. 128 [[Steals the internal buffer memory and returns it as a binbuf.
96 129
97 The returned memory must be freed with eina_binbuf_free(). 130 The returned memory must be freed with eina_binbuf_free().
131
132 On failure, for example a read-only backing store was
133 adopted with @.adopt_readonly, NULL is returned.
98 ]] 134 ]]
99 return: free(own(ptr(Eina.Binbuf)), eina_binbuf_free) @warn_unused; [[Binbuf]] 135 return: free(own(ptr(Eina.Binbuf)), eina_binbuf_free) @warn_unused; [[Binbuf]]
100 } 136 }