From 0d96ba973471f03f4d38f1764019751a4a3044ff Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Fri, 12 Aug 2016 18:55:37 -0300 Subject: [PATCH] binbuf, strbuf and ustrbuf: add slice_get() and rw_slice_get(). --- src/lib/eina/eina_binbuf.h | 47 ++++++++++++++++++++++++++ src/lib/eina/eina_binbuf_template_c.x | 30 +++++++++++++++++ src/lib/eina/eina_strbuf.h | 48 +++++++++++++++++++++++++++ src/lib/eina/eina_strbuf_common.c | 34 +++++++++++++++++++ src/lib/eina/eina_strbuf_common.h | 5 +++ src/lib/eina/eina_ustrbuf.h | 47 ++++++++++++++++++++++++++ src/tests/eina/eina_test_binbuf.c | 16 +++++++-- src/tests/eina/eina_test_strbuf.c | 20 +++++++++-- 8 files changed, 243 insertions(+), 4 deletions(-) diff --git a/src/lib/eina/eina_binbuf.h b/src/lib/eina/eina_binbuf.h index 3c68ff683e..051c5d172d 100644 --- a/src/lib/eina/eina_binbuf.h +++ b/src/lib/eina/eina_binbuf.h @@ -150,6 +150,18 @@ EAPI void eina_binbuf_reset(Eina_Binbuf *buf) EINA_ARG_NONNULL(1); */ EAPI Eina_Bool eina_binbuf_append_length(Eina_Binbuf *buf, const unsigned char *str, size_t length) EINA_ARG_NONNULL(1, 2); +/** + * @brief Append a slice to a buffer, reallocating as necessary. + * + * @param buf The string buffer to append to. + * @param slice The slice to append. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function appends @p slice to @p buf. If @p buf can't append + * it, #EINA_FALSE is returned, otherwise #EINA_TRUE is returned. + */ +EAPI Eina_Bool eina_binbuf_append_slice(Eina_Binbuf *buf, const Eina_Slice slice) EINA_ARG_NONNULL(1); + /** * @brief Append an Eina_Binbuf to a buffer, reallocating as necessary. * @@ -204,6 +216,20 @@ EAPI Eina_Bool eina_binbuf_append_char(Eina_Binbuf *buf, unsigned char c) EINA_A */ EAPI Eina_Bool eina_binbuf_insert_length(Eina_Binbuf *buf, const unsigned char *str, size_t length, size_t pos) EINA_ARG_NONNULL(1, 2); +/** + * @brief Insert a slice to a buffer, reallocating as necessary. + * + * @param buf The string buffer to insert to. + * @param slice The slice to insert. + * @param pos The position to insert the string. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p slice to @p buf at position @p pos. If @p + * buf can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE + * is returned. + */ +EAPI Eina_Bool eina_binbuf_insert_slice(Eina_Binbuf *buf, const Eina_Slice slice, size_t pos) EINA_ARG_NONNULL(1); + /** * @brief Insert a character to a string buffer, reallocating as * necessary. @@ -286,6 +312,27 @@ EAPI void eina_binbuf_string_free(Eina_Binbuf *buf) EINA_ARG_NONNULL(1); */ EAPI size_t eina_binbuf_length_get(const Eina_Binbuf *buf) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; +/** + * @brief Get a read-only slice representing the current binbuf contents. + * + * @param buf the src buffer. + * @return a read-only slice for the current contents. It may become + * invalid as soon as the @a buf is changed. + * + * @since 1.19 + */ +EAPI Eina_Slice eina_binbuf_slice_get(const Eina_Binbuf *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); + +/** + * @brief Get a read-write slice representing the current binbuf contents. + * + * @param buf the src buffer. + * @return a read-write slice for the current contents. It may become + * invalid as soon as the @a buf is changed with calls such as + * eina_binbuf_append(), eina_binbuf_remove() + */ +EAPI Eina_Rw_Slice eina_binbuf_rw_slice_get(const Eina_Binbuf *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); + /** * @} */ diff --git a/src/lib/eina/eina_binbuf_template_c.x b/src/lib/eina/eina_binbuf_template_c.x index b9f5c5abf3..f074f04525 100644 --- a/src/lib/eina/eina_binbuf_template_c.x +++ b/src/lib/eina/eina_binbuf_template_c.x @@ -107,6 +107,13 @@ _FUNC_EXPAND(append_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *s return eina_strbuf_common_append_length(_STRBUF_CSIZE, buf, (const void *) str, length); } +EAPI Eina_Bool +_FUNC_EXPAND(append_slice)(_STRBUF_STRUCT_NAME *buf, const Eina_Slice slice) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_append_length(_STRBUF_CSIZE, buf, slice.mem, slice.len); +} + EAPI Eina_Bool _FUNC_EXPAND(append_buffer)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_STRUCT_NAME *data) { @@ -123,6 +130,13 @@ _FUNC_EXPAND(insert_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *s return eina_strbuf_common_insert_length(_STRBUF_CSIZE, buf, (const void *) str, length, pos); } +EAPI Eina_Bool +_FUNC_EXPAND(insert_slice)(_STRBUF_STRUCT_NAME *buf, const Eina_Slice slice, size_t pos) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_insert_length(_STRBUF_CSIZE, buf, slice.mem, slice.len, pos); +} + EAPI Eina_Bool _FUNC_EXPAND(append_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c) { @@ -171,3 +185,19 @@ _FUNC_EXPAND(length_get)(const _STRBUF_STRUCT_NAME *buf) EINA_MAGIC_CHECK_STRBUF(buf, 0); return eina_strbuf_common_length_get(buf); } + +EAPI Eina_Slice +_FUNC_EXPAND(slice_get)(const _STRBUF_STRUCT_NAME *buf) +{ + Eina_Slice ret = {.len = 0, .mem = NULL}; + EINA_MAGIC_CHECK_STRBUF(buf, ret); + return eina_strbuf_common_slice_get(buf); +} + +EAPI Eina_Rw_Slice +_FUNC_EXPAND(rw_slice_get)(const _STRBUF_STRUCT_NAME *buf) +{ + Eina_Rw_Slice ret = {.len = 0, .mem = NULL}; + EINA_MAGIC_CHECK_STRBUF(buf, ret); + return eina_strbuf_common_rw_slice_get(buf); +} diff --git a/src/lib/eina/eina_strbuf.h b/src/lib/eina/eina_strbuf.h index df3ca8e80e..94d16f8c3a 100644 --- a/src/lib/eina/eina_strbuf.h +++ b/src/lib/eina/eina_strbuf.h @@ -5,6 +5,7 @@ #include #include "eina_types.h" +#include "eina_slice.h" /** @@ -225,6 +226,18 @@ EAPI Eina_Bool eina_strbuf_append_n(Eina_Strbuf *buf, const char *str, size_t ma */ EAPI Eina_Bool eina_strbuf_append_length(Eina_Strbuf *buf, const char *str, size_t length) EINA_ARG_NONNULL(1, 2); +/** + * @brief Append a slice to a buffer, reallocating as necessary. + * + * @param buf The string buffer to append to. + * @param slice The slice to append. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function appends @p slice to @p buf. If @p buf can't append + * it, #EINA_FALSE is returned, otherwise #EINA_TRUE is returned. + */ +EAPI Eina_Bool eina_strbuf_append_slice(Eina_Strbuf *buf, const Eina_Slice slice) EINA_ARG_NONNULL(1); + /** * @brief Append an Eina_Strbuf to a buffer, reallocating as necessary. * @@ -357,6 +370,20 @@ EAPI Eina_Bool eina_strbuf_insert_n(Eina_Strbuf *buf, const char *str, size_t ma */ EAPI Eina_Bool eina_strbuf_insert_length(Eina_Strbuf *buf, const char *str, size_t length, size_t pos) EINA_ARG_NONNULL(1, 2); +/** + * @brief Insert a slice to a buffer, reallocating as necessary. + * + * @param buf The string buffer to insert to. + * @param slice The slice to insert. + * @param pos The position to insert the string. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p slice to @p buf at position @p pos. If @p + * buf can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE + * is returned. + */ +EAPI Eina_Bool eina_strbuf_insert_slice(Eina_Strbuf *buf, const Eina_Slice slice, size_t pos) EINA_ARG_NONNULL(1); + /** * @brief Insert a character to a string buffer, reallocating as * necessary. @@ -670,6 +697,27 @@ EAPI void eina_strbuf_tolower(Eina_Strbuf *buf) EINA_ARG_NONNULL(1); */ EAPI Eina_Strbuf * eina_strbuf_substr_get(Eina_Strbuf *buf, size_t pos, size_t len) EINA_MALLOC EINA_WARN_UNUSED_RESULT; +/** + * @brief Get a read-only slice representing the current strbuf contents. + * + * @param buf the source string. + * @return a read-only slice for the current contents. It may become + * invalid as soon as the @a buf is changed. + * + * @since 1.19 + */ +EAPI Eina_Slice eina_strbuf_slice_get(const Eina_Strbuf *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); + +/** + * @brief Get a read-write slice representing the current strbuf contents. + * + * @param buf the source string. + * @return a read-write slice for the current contents. It may become + * invalid as soon as the @a buf is changed with calls such as + * eina_strbuf_append(), eina_strbuf_remove() + */ +EAPI Eina_Rw_Slice eina_strbuf_rw_slice_get(const Eina_Strbuf *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); + /** * @} */ diff --git a/src/lib/eina/eina_strbuf_common.c b/src/lib/eina/eina_strbuf_common.c index 1a53c9058f..7b9aa9f0d7 100644 --- a/src/lib/eina/eina_strbuf_common.c +++ b/src/lib/eina/eina_strbuf_common.c @@ -787,6 +787,40 @@ eina_strbuf_common_length_get(const Eina_Strbuf *buf) return buf->len; } +/** + * @internal + * @brief Get a read-only slice representing the current strbuf contents. + * + * @param buf The string buffer. + * @return The current memory read-only slice of the string, in bytes, + * without the trailing null byte. + */ +Eina_Slice +eina_strbuf_common_slice_get(const Eina_Strbuf *buf) +{ + Eina_Slice ret; + ret.len = buf->len; + ret.mem = buf->buf; + return ret; +} + +/** + * @internal + * @brief Get a read-write slice representing the current strbuf contents. + * + * @param buf The string buffer. + * @return The current memory read-write slice of the string, in + * bytes, without the trailing null byte. + */ +Eina_Rw_Slice +eina_strbuf_common_rw_slice_get(const Eina_Strbuf *buf) +{ + Eina_Rw_Slice ret; + ret.len = buf->len; + ret.mem = buf->buf; + return ret; +} + /** * @cond LOCAL */ diff --git a/src/lib/eina/eina_strbuf_common.h b/src/lib/eina/eina_strbuf_common.h index 47fbe9e3aa..ec86f25e51 100644 --- a/src/lib/eina/eina_strbuf_common.h +++ b/src/lib/eina/eina_strbuf_common.h @@ -117,6 +117,11 @@ void eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf); size_t eina_strbuf_common_length_get(const Eina_Strbuf *buf); +Eina_Slice +eina_strbuf_common_slice_get(const Eina_Strbuf *buf); +Eina_Rw_Slice +eina_strbuf_common_rw_slice_get(const Eina_Strbuf *buf); + Eina_Bool _eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size); diff --git a/src/lib/eina/eina_ustrbuf.h b/src/lib/eina/eina_ustrbuf.h index 888d8a2989..b0c6799772 100644 --- a/src/lib/eina/eina_ustrbuf.h +++ b/src/lib/eina/eina_ustrbuf.h @@ -177,6 +177,18 @@ EAPI Eina_Bool eina_ustrbuf_append_n(Eina_UStrbuf *buf, const Eina_Unicode *str, */ EAPI Eina_Bool eina_ustrbuf_append_length(Eina_UStrbuf *buf, const Eina_Unicode *str, size_t length) EINA_ARG_NONNULL(1, 2); +/** + * @brief Append a slice to a buffer, reallocating as necessary. + * + * @param buf The string buffer to append to. + * @param slice The slice to append. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function appends @p slice to @p buf. If @p buf can't append + * it, #EINA_FALSE is returned, otherwise #EINA_TRUE is returned. + */ +EAPI Eina_Bool eina_ustrbuf_append_slice(Eina_UStrbuf *buf, const Eina_Slice slice) EINA_ARG_NONNULL(1); + /** * @brief Append a character to a string buffer, reallocating as * necessary. @@ -263,6 +275,20 @@ EAPI Eina_Bool eina_ustrbuf_insert_n(Eina_UStrbuf *buf, const Eina_Unicode *str, */ EAPI Eina_Bool eina_ustrbuf_insert_length(Eina_UStrbuf *buf, const Eina_Unicode *str, size_t length, size_t pos) EINA_ARG_NONNULL(1, 2); +/** + * @brief Insert a slice to a buffer, reallocating as necessary. + * + * @param buf The string buffer to insert to. + * @param slice The slice to insert. + * @param pos The position to insert the string. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p slice to @p buf at position @p pos. If @p + * buf can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE + * is returned. + */ +EAPI Eina_Bool eina_ustrbuf_insert_slice(Eina_UStrbuf *buf, const Eina_Slice slice, size_t pos) EINA_ARG_NONNULL(1); + /** * @brief Insert a character to a string buffer, reallocating as * necessary. @@ -421,6 +447,27 @@ eina_ustrbuf_string_free(Eina_UStrbuf *buf) EINA_ARG_NONNULL(1); EAPI size_t eina_ustrbuf_length_get(const Eina_UStrbuf *buf) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; +/** + * @brief Get a read-only slice representing the current ustrbuf contents. + * + * @param buf the source string. + * @return a read-only slice for the current contents. It may become + * invalid as soon as the @a buf is changed. + * + * @since 1.19 + */ +EAPI Eina_Slice eina_ustrbuf_slice_get(const Eina_UStrbuf *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); + +/** + * @brief Get a read-write slice representing the current ustrbuf contents. + * + * @param buf the source string. + * @return a read-write slice for the current contents. It may become + * invalid as soon as the @a buf is changed with calls such as + * eina_ustrbuf_append(), eina_ustrbuf_remove() + */ +EAPI Eina_Rw_Slice eina_ustrbuf_rw_slice_get(const Eina_UStrbuf *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); + /** * @} */ diff --git a/src/tests/eina/eina_test_binbuf.c b/src/tests/eina/eina_test_binbuf.c index af8f4699b9..653d9ae617 100644 --- a/src/tests/eina/eina_test_binbuf.c +++ b/src/tests/eina/eina_test_binbuf.c @@ -31,7 +31,8 @@ START_TEST(binbuf_simple) unsigned char *txt; const unsigned char cbuf[] = "Null in the middle \0 and more text afterwards and \0 anotehr null just there and another one \0 here."; size_t size = sizeof(cbuf) - 1; /* We don't care about the real NULL */ - + Eina_Slice ro_slice; + Eina_Rw_Slice rw_slice; eina_init(); @@ -42,13 +43,24 @@ START_TEST(binbuf_simple) fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size)); fail_if(size != eina_binbuf_length_get(buf)); + ro_slice = eina_binbuf_slice_get(buf); + fail_if(ro_slice.len != size); + fail_if(ro_slice.mem != eina_binbuf_string_get(buf)); + + rw_slice = eina_binbuf_rw_slice_get(buf); + fail_if(rw_slice.len != size); + fail_if(rw_slice.mem != eina_binbuf_string_get(buf)); + test_buf = eina_binbuf_new(); fail_if(!test_buf); fail_if(!eina_binbuf_append_buffer(test_buf, buf)); fail_if(memcmp(eina_binbuf_string_get(test_buf), cbuf, size)); fail_if(size != eina_binbuf_length_get(test_buf)); - eina_binbuf_append_length(buf, cbuf, size); + ro_slice.mem = cbuf; + ro_slice.len = size; + + eina_binbuf_append_slice(buf, ro_slice); fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size)); fail_if(memcmp(eina_binbuf_string_get(buf) + size, cbuf, size)); fail_if(2 * size != eina_binbuf_length_get(buf)); diff --git a/src/tests/eina/eina_test_strbuf.c b/src/tests/eina/eina_test_strbuf.c index 3b2fe33b9a..297177d7cc 100644 --- a/src/tests/eina/eina_test_strbuf.c +++ b/src/tests/eina/eina_test_strbuf.c @@ -30,6 +30,8 @@ START_TEST(strbuf_simple) { Eina_Strbuf *buf; char *txt; + Eina_Slice ro_slice; + Eina_Rw_Slice rw_slice; #define TEST_TEXT \ "This test should be so long that it is longer than the initial size of strbuf" @@ -57,6 +59,14 @@ START_TEST(strbuf_simple) fail_if(eina_strbuf_length_get(buf) != 0); fail_if(!strcmp(eina_strbuf_string_get(buf), TEST_TEXT)); + ro_slice = eina_strbuf_slice_get(buf); + fail_if(ro_slice.len != eina_strbuf_length_get(buf)); + fail_if(ro_slice.mem != eina_strbuf_string_get(buf)); + + rw_slice = eina_strbuf_rw_slice_get(buf); + fail_if(rw_slice.len != eina_strbuf_length_get(buf)); + fail_if(rw_slice.mem != eina_strbuf_string_get(buf)); + eina_strbuf_string_free(buf); fail_if(eina_strbuf_length_get(buf)); eina_strbuf_append(buf, TEST_TEXT); @@ -168,6 +178,9 @@ END_TEST START_TEST(strbuf_append) { Eina_Strbuf *buf; + Eina_Slice ro_slice = EINA_SLICE_STR_LITERAL("somethingELSE"); + + ro_slice.len -= strlen("ELSE"); eina_init(); @@ -204,7 +217,7 @@ START_TEST(strbuf_append) fail_if(strcmp(eina_strbuf_string_get(buf), "something")); eina_strbuf_reset(buf); - eina_strbuf_append_length(buf, "somethingELSE", strlen("something")); + eina_strbuf_append_slice(buf, ro_slice); fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); fail_if(strcmp(eina_strbuf_string_get(buf), "something")); eina_strbuf_reset(buf); @@ -218,6 +231,9 @@ END_TEST START_TEST(strbuf_insert) { Eina_Strbuf *buf; + Eina_Slice ro_slice = EINA_SLICE_STR_LITERAL("EINA"); + + ro_slice.len = 2; eina_init(); @@ -244,7 +260,7 @@ START_TEST(strbuf_insert) fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); fail_if(strcmp(eina_strbuf_string_get(buf), "1ABxyz23abcxyz")); - eina_strbuf_insert_n(buf, "EINA", 2, 3); + eina_strbuf_insert_slice(buf, ro_slice, 3); fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); fail_if(strcmp(eina_strbuf_string_get(buf), "1ABEIxyz23abcxyz"));