From 98b5aa4b363284f2c81f31a28a84928e9132f619 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 6 Sep 2011 10:58:53 +0000 Subject: [PATCH] Eina (u)strbuf: Added eina_(u)strbuf_manage_new. This lets us take a string and use it as the string buffer instead of copying and allocating. SVN revision: 63226 --- legacy/eina/ChangeLog | 6 ++ legacy/eina/src/include/eina_strbuf.h | 19 ++++++ legacy/eina/src/include/eina_ustrbuf.h | 19 ++++++ legacy/eina/src/lib/eina_strbuf_common.c | 64 ++++++++++++++++++++ legacy/eina/src/lib/eina_strbuf_common.h | 4 ++ legacy/eina/src/lib/eina_strbuf_template_c.x | 9 +++ legacy/eina/src/tests/eina_test_strbuf.c | 40 ++++++++++++ 7 files changed, 161 insertions(+) diff --git a/legacy/eina/ChangeLog b/legacy/eina/ChangeLog index c0063a42d0..1b00657235 100644 --- a/legacy/eina/ChangeLog +++ b/legacy/eina/ChangeLog @@ -130,3 +130,9 @@ 2011-09-05 Cedric Bail * Add eina_inlist_sorted_state_insert and helper. + +2011-09-06 Tom Hacohen + + * Strbuf + Ustrbuf: Added eina_(u)strbuf_manage_new. This lets us + take a string and use it as the string buffer instead of copying + and allocating. diff --git a/legacy/eina/src/include/eina_strbuf.h b/legacy/eina/src/include/eina_strbuf.h index ac92f975f3..d4f6b34f14 100644 --- a/legacy/eina/src/include/eina_strbuf.h +++ b/legacy/eina/src/include/eina_strbuf.h @@ -79,6 +79,25 @@ typedef struct _Eina_Strbuf Eina_Strbuf; */ EAPI Eina_Strbuf *eina_strbuf_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT; +/** + * @brief Create a new string buffer using the passed string. The passed + * string is used directly as the buffer, it's somehow the opposite function of + * @ref eina_strbuf_string_steal . The passed string must be malloced. + * + * @param str the string to manage + * @return Newly allocated string buffer instance. + * + * This function creates a new string buffer. On error, @c NULL is + * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To + * free the resources, use eina_strbuf_free(). + * + * @see eina_strbuf_free() + * @see eina_strbuf_append() + * @see eina_strbuf_string_get() + * @since 1.1.0 + */ +EAPI Eina_Strbuf *eina_strbuf_manage_new(char *str) EINA_MALLOC EINA_WARN_UNUSED_RESULT; + /** * @brief Free a string buffer. * diff --git a/legacy/eina/src/include/eina_ustrbuf.h b/legacy/eina/src/include/eina_ustrbuf.h index 9abe845910..f68cb7b219 100644 --- a/legacy/eina/src/include/eina_ustrbuf.h +++ b/legacy/eina/src/include/eina_ustrbuf.h @@ -48,6 +48,25 @@ typedef struct _Eina_Strbuf Eina_UStrbuf; */ EAPI Eina_UStrbuf *eina_ustrbuf_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT; +/** + * @brief Create a new string buffer using the passed string. The passed + * string is used directly as the buffer, it's somehow the opposite function of + * @ref eina_ustrbuf_string_steal . The passed string must be malloced. + * + * @param str the string to manage + * @return Newly allocated string buffer instance. + * + * This function creates a new string buffer. On error, @c NULL is + * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To + * free the resources, use eina_strbuf_free(). + * + * @see eina_ustrbuf_free() + * @see eina_ustrbuf_append() + * @see eina_ustrbuf_string_get() + * @since 1.1.0 + */ +EAPI Eina_Strbuf *eina_ustrbuf_manage_new(Eina_Unicode *str) EINA_MALLOC EINA_WARN_UNUSED_RESULT; + /** * @brief Free a string buffer. * diff --git a/legacy/eina/src/lib/eina_strbuf_common.c b/legacy/eina/src/lib/eina_strbuf_common.c index ad61766e84..abdd57c6d9 100644 --- a/legacy/eina/src/lib/eina_strbuf_common.c +++ b/legacy/eina/src/lib/eina_strbuf_common.c @@ -99,6 +99,30 @@ _eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf) return EINA_TRUE; } +/** + * @internal + * + * init the buffer without allocating the actual string (for managed) + * @param csize the character size + * @param buf the buffer to init + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + */ +static Eina_Bool +_eina_strbuf_common_manage_init(size_t csize __UNUSED__, + Eina_Strbuf *buf, + void *str, + size_t len) +{ + buf->len = len; + buf->size = len + 1; + buf->step = EINA_STRBUF_INIT_STEP; + buf->buf = str; + + return EINA_TRUE; +} + + /** * @internal * @@ -242,6 +266,46 @@ eina_strbuf_common_new(size_t csize) return buf; } +/** + * @internal + * @brief Create a new string buffer managing str. + * + * @param csize the character size + * @param str the string to manage + * @param len the length of the string to manage + * @return Newly allocated string buffer instance. + * + * This function creates a new string buffer. On error, @c NULL is + * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To + * free the resources, use eina_strbuf_common_free(). + * + * @see eina_strbuf_common_free() + * @see eina_strbuf_common_append() + * @see eina_strbuf_common_string_get() + * @since 1.1.0 + */ +Eina_Strbuf * +eina_strbuf_common_manage_new(size_t csize, + void *str, + size_t len) +{ + Eina_Strbuf *buf; + + eina_error_set(0); + buf = malloc(sizeof(Eina_Strbuf)); + if (EINA_UNLIKELY(!buf)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf, str, len))) + { + eina_strbuf_common_free(buf); + return NULL; + } + return buf; +} + /** * @internal * @brief Free a string buffer. diff --git a/legacy/eina/src/lib/eina_strbuf_common.h b/legacy/eina/src/lib/eina_strbuf_common.h index f729b89a08..06a13533ff 100644 --- a/legacy/eina/src/lib/eina_strbuf_common.h +++ b/legacy/eina/src/lib/eina_strbuf_common.h @@ -37,6 +37,10 @@ Eina_Bool eina_strbuf_common_shutdown(void); Eina_Strbuf * eina_strbuf_common_new(size_t csize); +Eina_Strbuf * +eina_strbuf_common_manage_new(size_t csize, + void *str, + size_t len); void eina_strbuf_common_free(Eina_Strbuf *buf); void diff --git a/legacy/eina/src/lib/eina_strbuf_template_c.x b/legacy/eina/src/lib/eina_strbuf_template_c.x index 123d4bed71..e8c3b617d3 100644 --- a/legacy/eina/src/lib/eina_strbuf_template_c.x +++ b/legacy/eina/src/lib/eina_strbuf_template_c.x @@ -22,6 +22,15 @@ * API * *============================================================================*/ +EAPI _STRBUF_STRUCT_NAME * +_FUNC_EXPAND(manage_new)(_STRBUF_DATA_TYPE *str) +{ + _STRBUF_STRUCT_NAME *buf = eina_strbuf_common_manage_new(_STRBUF_CSIZE, + (void *) str, _STRBUF_STRLEN_FUNC(str)); + EINA_MAGIC_SET(buf, _STRBUF_MAGIC); + return buf; +} + EAPI Eina_Bool _FUNC_EXPAND(append)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str) { diff --git a/legacy/eina/src/tests/eina_test_strbuf.c b/legacy/eina/src/tests/eina_test_strbuf.c index 87dfc56bf8..2205e3e53f 100644 --- a/legacy/eina/src/tests/eina_test_strbuf.c +++ b/legacy/eina/src/tests/eina_test_strbuf.c @@ -63,6 +63,45 @@ START_TEST(strbuf_simple) } END_TEST +START_TEST(strbuf_manage_simple) +{ + Eina_Strbuf *buf; + char *txt; +#define TEXT \ + "This test should be so long that it is longer than the initial size of strbuf" + + eina_init(); + + txt = strdup(TEXT); + + buf = eina_strbuf_manage_new(txt); + fail_if(!buf); + + fail_if(strcmp(eina_strbuf_string_get(buf), TEXT)); + fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); + eina_strbuf_append(buf, TEXT); + fail_if(strcmp(eina_strbuf_string_get(buf), TEXT TEXT)); + fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); + txt = eina_strbuf_string_steal(buf); + fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); + fail_if(strcmp(txt, TEXT TEXT)); + free(txt); + fail_if(eina_strbuf_length_get(buf) != 0); + fail_if(!strcmp(eina_strbuf_string_get(buf), TEXT TEXT)); + eina_strbuf_append(buf, TEXT); + fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); + eina_strbuf_reset(buf); + fail_if(strlen(eina_strbuf_string_get(buf)) != eina_strbuf_length_get(buf)); + fail_if(eina_strbuf_length_get(buf) != 0); + fail_if(!strcmp(eina_strbuf_string_get(buf), TEXT)); + + eina_strbuf_free(buf); + + eina_shutdown(); +#undef TEXT +} +END_TEST + START_TEST(strbuf_remove) { Eina_Strbuf *buf; @@ -406,4 +445,5 @@ eina_test_strbuf(TCase *tc) tcase_add_test(tc, strbuf_realloc); tcase_add_test(tc, strbuf_append_realloc); tcase_add_test(tc, strbuf_prepend_realloc); + tcase_add_test(tc, strbuf_manage_simple); }