forked from enlightenment/efl
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:
parent
ecdf56de47
commit
c2aedc117a
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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]]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue