On Thu, Aug 11, 2016 at 3:29 AM, Carsten Haitzler <[email protected]> wrote:
> On Tue, 9 Aug 2016 18:31:37 -0300 Gustavo Sverzut Barbieri 
> <[email protected]>
> said:
>
> i think we should re-use binbuf/strbuf here and add whatever is missing to
> them...
>
> in fact at a raw level they have everything needed even to point to mmaped
> memory and use multiple binbufs to point to slices of it without any memcpy's
> etc.
>
> we have a lot of api in efl. let's not add more if we don't NEED it. it's
> complex enough to learn! :)

Well, the purpose of Slice can indeed be satisfied with Eina_Binbuf,
but I'd still keep the slice for the following reasons:

 - super-lightweight: no need to alloc, we can pass value, not
pointer. (see my examples in the original email)

 - type independent: if we have a string or a strbuf and we expect
binbuf, we'd need to convert to them (which results in an alloc/free).
With slice we can have "_slice_get()" methods in most functions that
used to return memory+size, like binbuf/strbuf (string_get() +
length_get()), or stringshare (it's the memory and offers
eina_stringshare_strlen()).

 - easily usable in tokenization/parsers, like how to split "a:b:c" at
":" without alloc? you can create a slice for "a:b:c" and then on each
loop fill the proper segment.

 - clear purpose that memory is pre-defined in content and length. Say
the "Efl.Io.Reader.read()" method, if we give a slice, it's clear that
will read up to slice.len. If you receive 'Eina_Binbuf', do I need to
pre-allocate its size (no binbuf_resize(), would need to add)? If it
will grow dynamically, how do I limit that amount? By using
yet-another parameter?

With slices one can easily use the stack buffers as Tasn mentioned or
binbuf. We can still add binbuf_resize()/grow() so we can later use a
slice from within that new memory and read straight into it, like:

    size_t oldlen = eina_binbuf_length_get(buf);
    eina_binbuf_grow(buf, 4096); // you control how much you want to
grow at once
    Eina_Rw_Slice rw_slice = eina_binbuf_rw_slice_get(buf);
    rw_slice.mem = (uint8_t *)rw_slice.mem + oldlen; // these 2 lines
can be an eina_rw_slice static inline helper
    rw_slice.len -= oldlen;
    size_t used;
    Eina_Error error = efl_io_reader_read(obj, rw_slice, &used); //
reads straight into buffer, no copies
    eina_binbuf_length_set(buf, oldlen + used);

Or in more common code:

    char buf[4096];
    Eina_Rw_Slice rw_slice = {.mem = buf, .len = sizeof(buf) - 1}; //
these 2 lines can be made easier with a macro
    size_t used;
    Eina_Error error = efl_io_reader_read(obj, rw_slice, &used);
    buf[used] = '\0';
    printf("got: %s\n", buf);

RDONLY slices used for Write are even easier:


    size_t used;
    Eina_Error error = efl_io_writer_write(obj,
eina_slice_from_str("hello world"), &used);


You could do these with Eina_Binbuf by using the managed version and
setting "ro" flag, but you always need to allocate the binbuf and free
it, even for a simple operation like the one above.

Did you change your mind or should I go with solely Eina_Binbuf?

-- 
Gustavo Sverzut Barbieri
--------------------------------------
Mobile: +55 (16) 99354-9890

------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity 
planning reports. http://sdm.link/zohodev2dev
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to