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).
This commit is contained in:
Gustavo Sverzut Barbieri 2016-12-19 16:49:29 -02:00
parent ecdf56de47
commit c2aedc117a
3 changed files with 132 additions and 6 deletions

View File

@ -343,7 +343,7 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
* One can change these to Efl_Io_File or event pipe to something
* else like Efl_Io_Stdin, Efl_Io_Stdout and it would just work.
*/
Eina_Slice slice;
static const Eina_Slice hello_world_slice = EINA_SLICE_STR_LITERAL("Hello World!");
Send_Recv_Data *d;
Eo *send_buffer, *recv_buffer;
@ -354,10 +354,8 @@ _server_client_add(void *data EINA_UNUSED, const Efl_Event *event)
return;
}
// TODO buffer constructor taking RO string
send_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL);
slice = (Eina_Slice)EINA_SLICE_STR("Hello World!");
efl_io_writer_write(send_buffer, &slice, NULL);
send_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL,
efl_io_buffer_adopt_readonly(efl_added, hello_world_slice));
/* Unlimited buffer to store the received data. */
recv_buffer = efl_add(EFL_IO_BUFFER_CLASS, NULL);

View File

@ -17,6 +17,7 @@ typedef struct _Efl_Io_Buffer_Data
Eina_Bool closed;
Eina_Bool can_read;
Eina_Bool can_write;
Eina_Bool readonly;
} Efl_Io_Buffer_Data;
static Eina_Bool
@ -25,6 +26,8 @@ _efl_io_buffer_realloc(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
void *tmp;
size_t limit = efl_io_buffer_limit_get(o);
EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, EINA_FALSE);
if ((limit > 0) && (size > limit))
size = limit;
@ -77,6 +80,7 @@ _efl_io_buffer_realloc_rounded(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
EOLIAN static void
_efl_io_buffer_preallocate(Eo *o, Efl_Io_Buffer_Data *pd, size_t size)
{
EINA_SAFETY_ON_TRUE_RETURN(pd->readonly);
EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
if (pd->allocated < size)
_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)
EOLIAN static void
_efl_io_buffer_limit_set(Eo *o, Efl_Io_Buffer_Data *pd, size_t limit)
{
EINA_SAFETY_ON_TRUE_RETURN(pd->readonly);
EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
if (pd->limit == limit) return;
@ -125,6 +130,7 @@ EOLIAN static Eina_Binbuf *
_efl_io_buffer_binbuf_steal(Eo *o, Efl_Io_Buffer_Data *pd)
{
Eina_Binbuf *ret;
EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, NULL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), NULL);
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)
if (pd->bytes)
{
free(pd->bytes);
if (!pd->readonly) free(pd->bytes);
pd->bytes = NULL;
pd->allocated = 0;
pd->used = 0;
@ -244,6 +250,7 @@ _efl_io_buffer_efl_io_writer_write(Eo *o, Efl_Io_Buffer_Data *pd, Eina_Slice *sl
size_t available, todo, write_pos, limit;
int err = EINVAL;
EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, EPERM);
EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINVAL);
EINA_SAFETY_ON_TRUE_GOTO(efl_io_closer_closed_get(o), error);
@ -362,6 +369,13 @@ _efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size)
if (efl_io_sizer_size_get(o) == size) return 0;
if (pd->readonly)
{
EINA_SAFETY_ON_TRUE_RETURN_VAL(size > pd->used, EPERM);
pd->used = size;
goto end;
}
old_size = pd->used;
pd->used = size;
@ -378,6 +392,7 @@ _efl_io_buffer_efl_io_sizer_resize(Eo *o, Efl_Io_Buffer_Data *pd, uint64_t size)
if (old_size < size)
memset(pd->bytes + old_size, 0, size - old_size);
end:
pos_read = efl_io_buffer_position_read_get(o);
if (pos_read > size)
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
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), EINA_FALSE);
size = efl_io_sizer_size_get(o);
if (position < size)
EINA_SAFETY_ON_TRUE_RETURN_VAL(pd->readonly, EINA_FALSE);
EINA_SAFETY_ON_TRUE_RETURN_VAL(position > size, EINA_FALSE);
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)
return pd->position_write;
}
EOLIAN static void
_efl_io_buffer_adopt_readonly(Eo *o, Efl_Io_Buffer_Data *pd, const Eina_Slice slice)
{
Eina_Bool changed_size;
EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
if (!pd->readonly) free(pd->bytes);
pd->readonly = EINA_TRUE;
pd->bytes = (uint8_t *)slice.bytes;
pd->allocated = slice.len;
changed_size = (pd->used != slice.len);
pd->used = slice.len;
efl_io_writer_can_write_set(o, EINA_FALSE);
if (pd->closed) return;
if (efl_io_buffer_position_read_get(o) > slice.len)
{
efl_io_buffer_position_read_set(o, slice.len);
if (pd->closed) return;
}
efl_io_buffer_position_write_set(o, slice.len);
if (pd->closed) return;
if (changed_size)
{
efl_event_callback_call(o, EFL_IO_SIZER_EVENT_SIZE_CHANGED, NULL);
if (pd->closed) return;
}
efl_event_callback_call(o, EFL_IO_BUFFER_EVENT_REALLOCATED, NULL);
}
EOLIAN static void
_efl_io_buffer_adopt_readwrite(Eo *o, Efl_Io_Buffer_Data *pd, Eina_Rw_Slice slice)
{
Eina_Bool changed_size;
EINA_SAFETY_ON_TRUE_RETURN(efl_io_closer_closed_get(o));
if (!pd->readonly) free(pd->bytes);
pd->readonly = EINA_FALSE;
pd->bytes = slice.bytes;
pd->allocated = slice.len;
changed_size = (pd->used != slice.len);
pd->used = slice.len;
efl_io_writer_can_write_set(o, (pd->limit == 0) ||
(efl_io_buffer_position_write_get(o) < pd->limit));
if (pd->closed) return;
if (efl_io_buffer_position_read_get(o) > slice.len)
{
efl_io_buffer_position_read_set(o, slice.len);
if (pd->closed) return;
}
if (efl_io_buffer_position_write_get(o) > slice.len)
{
efl_io_buffer_position_write_set(o, slice.len);
if (pd->closed) return;
}
if (changed_size)
{
efl_event_callback_call(o, EFL_IO_SIZER_EVENT_SIZE_CHANGED, NULL);
if (pd->closed) return;
}
efl_event_callback_call(o, EFL_IO_BUFFER_EVENT_REALLOCATED, NULL);
}
#include "interfaces/efl_io_buffer.eo.c"

View File

@ -22,6 +22,39 @@ class Efl.Io.Buffer (Efl.Object, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Ef
}
}
adopt_readonly {
[[Adopt a read-only slice as buffer's backing store.
The slice memory will not be copied and must remain
alive during buffer's lifetime. Usually this is
guaranteed by some global static-const memory or some
parent object and this buffer being a view of that -- be
aware of parent memory remaining alive, such as
"slice,changed" events.
]]
params {
@in slice: const(Eina.Slice); [[Slice to adopt as read-only]]
}
}
adopt_readwrite {
[[Adopt a read-write slice as buffer's backing store.
The slice memory will not be copied and must remain
alive during buffer's lifetime. Usually this is
guaranteed by some global static memory or some
parent object and this buffer being a view of that -- be
aware of parent memory remaining alive, such as
"slice,changed" events.
The memory will be disposed using free() and reallocated
using realloc().
]]
params {
@in slice: Eina.Rw_Slice; [[Slice to adopt as read-write]]
}
}
@property limit {
[[Limit how big the buffer can grow.
@ -95,6 +128,9 @@ class Efl.Io.Buffer (Efl.Object, Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Ef
[[Steals the internal buffer memory and returns it as a binbuf.
The returned memory must be freed with eina_binbuf_free().
On failure, for example a read-only backing store was
adopted with @.adopt_readonly, NULL is returned.
]]
return: free(own(ptr(Eina.Binbuf)), eina_binbuf_free) @warn_unused; [[Binbuf]]
}