From 297ea39a5cd11d1b0697ded2f46412ecddba63b7 Mon Sep 17 00:00:00 2001 From: Shilpa Singh Date: Tue, 3 Nov 2015 14:01:51 -0800 Subject: [PATCH] eina: add eina_tmpstr_manage_new, eina_tmpstr_manage_new_length APIs Summary: Add eina_tmpstr_manage_new, eina_tmpstr_manage_new_length APIs, these APIs create new tmpstr but reuse the input string memory. @feature Test Plan: Test case and example updated Reviewers: tasn, cedric Reviewed By: cedric Differential Revision: https://phab.enlightenment.org/D3178 Signed-off-by: Cedric BAIL --- src/examples/eina/eina_tmpstr_01.c | 14 +++++++- src/lib/eina/eina_tmpstr.c | 35 ++++++++++++++++++-- src/lib/eina/eina_tmpstr.h | 32 ++++++++++++++++++ src/tests/eina/eina_test_tmpstr.c | 67 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 3 deletions(-) diff --git a/src/examples/eina/eina_tmpstr_01.c b/src/examples/eina/eina_tmpstr_01.c index 36d8c62..68158ca 100644 --- a/src/examples/eina/eina_tmpstr_01.c +++ b/src/examples/eina/eina_tmpstr_01.c @@ -8,6 +8,9 @@ int main(int argc EINA_UNUSED, char **argv EINA_UNUSED) { const char *str; + char *str2; + const char *str3; + int len; const char *prologe = "The Cylons were created by man. They rebelled. They " "evolved."; @@ -15,9 +18,18 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED) str = eina_tmpstr_add_length(prologe, 31); printf("%s\n", str); - printf("length: %d\n", eina_tmpstr_len(str)); + len = eina_tmpstr_len(str); + printf("length: %d\n", len); eina_tmpstr_del(str); + str2 = (char *)calloc(61, sizeof(char)); + strcpy(str2, prologe); + str3 = eina_tmpstr_manage_new(str2); + printf("%s\n", str3); + len = eina_tmpstr_len(str3); + printf("length: %d\n", len); + eina_tmpstr_del(str3); + eina_shutdown(); return 0; diff --git a/src/lib/eina/eina_tmpstr.c b/src/lib/eina/eina_tmpstr.c index 43824b7..c7d26ee 100644 --- a/src/lib/eina/eina_tmpstr.c +++ b/src/lib/eina/eina_tmpstr.c @@ -47,6 +47,7 @@ struct _Str size_t length; Str *next; char *str; + Eina_Bool ma : 1; }; static Eina_Lock _mutex; @@ -78,6 +79,7 @@ eina_tmpstr_add_length(const char *str, size_t length) s->str = ((char *)s) + sizeof(Str); strncpy(s->str, str, length); s->str[length] = '\0'; + s->ma = EINA_FALSE; eina_lock_take(&_mutex); s->next = strs; strs = s; @@ -86,10 +88,38 @@ eina_tmpstr_add_length(const char *str, size_t length) } EAPI Eina_Tmpstr * +eina_tmpstr_manage_new_length(char *str, size_t length) +{ + Str *s; + + if (!str || !length) return NULL; + s = calloc(1, sizeof(Str)); + if (!s) return NULL; + s->length = length; + s->str = str; + s->ma = EINA_TRUE; + eina_lock_take(&_mutex); + s->next = strs; + strs = s; + eina_lock_release(&_mutex); + return s->str; +} + +EAPI Eina_Tmpstr * +eina_tmpstr_manage_new(char *str) +{ + size_t len; + + if (!str) return NULL; + len = strlen(str); + return eina_tmpstr_manage_new_length(str, len); +} + +EAPI Eina_Tmpstr * eina_tmpstr_add(const char *str) { size_t len; - + if (!str) return NULL; len = strlen(str); return eina_tmpstr_add_length(str, len); @@ -99,7 +129,7 @@ EAPI void eina_tmpstr_del(Eina_Tmpstr *tmpstr) { Str *s, *sp; - + if ((!strs) || (!tmpstr)) return; eina_lock_take(&_mutex); for (sp = NULL, s = strs; s; sp = s, s = s->next) @@ -108,6 +138,7 @@ eina_tmpstr_del(Eina_Tmpstr *tmpstr) { if (sp) sp->next = s->next; else strs = s->next; + if (s->ma) free(s->str); free(s); break; } diff --git a/src/lib/eina/eina_tmpstr.h b/src/lib/eina/eina_tmpstr.h index e516cfd..151fcd1 100644 --- a/src/lib/eina/eina_tmpstr.h +++ b/src/lib/eina/eina_tmpstr.h @@ -238,6 +238,38 @@ EAPI size_t eina_tmpstr_len(Eina_Tmpstr *tmpstr); EAPI void eina_tmpstr_del(Eina_Tmpstr *tmpstr) EINA_ARG_NONNULL(1); /** + * @brief Add a new temporary string using the passed string. The passed + * string is used directly as the buffer. The passed string must be malloced. + * + * @param str the input string to manage. + * @return A pointer to the tmp string that is a standard C string. + * + * This function creates a new temporary string. On error, @c NULL is + * returned. To free the resources, use eina_tmpstr_del(). + * + * @see eina_tmpstr_del() + * @since 1.17.0 + */ +EAPI Eina_Tmpstr *eina_tmpstr_manage_new(char *str) EINA_WARN_UNUSED_RESULT; + +/** + * @brief Add a new temporary string using the passed string. The passed + * string is used directly as the buffer. The passed string must be malloced. + * + * @param str the input string to manage. + * @param length the length of the string. + * @return A pointer to the tmp string that is a standard C string. + * + * This function creates a new temporary string. On error, @c NULL is + * returned. To free the resources, use eina_tmpstr_del(). + * + * @see eina_tmpstr_manage_new() + * @see eina_tmpstr_del() + * @since 1.17.0 + */ +EAPI Eina_Tmpstr *eina_tmpstr_manage_new_length(char *str, size_t length); + +/** * @} */ diff --git a/src/tests/eina/eina_test_tmpstr.c b/src/tests/eina/eina_test_tmpstr.c index 72fb7c8..4959dd3 100644 --- a/src/tests/eina/eina_test_tmpstr.c +++ b/src/tests/eina/eina_test_tmpstr.c @@ -60,6 +60,70 @@ START_TEST(tmpstr_simple) } END_TEST +START_TEST(tmpstr_simple_len) +{ + eina_init(); + + const int cnt_tmp_strings = 10; + const int max_str_len = 255; + char buf[max_str_len + 1]; + Eina_Tmpstr *tmp_strings[cnt_tmp_strings]; + + // Add several tmp strings + for (int i = 0; i != cnt_tmp_strings; ++i) + { + snprintf(buf, max_str_len, "Tmp string %d", (i + 1)); + tmp_strings[i] = eina_tmpstr_add_length(buf, (max_str_len + 1)); + + fail_if(strcmp(buf, tmp_strings[i])); + } + + // Delete these tmp strings + for (int i = 0; i != cnt_tmp_strings; ++i) + { + snprintf(buf, max_str_len, "Tmp string %d", (cnt_tmp_strings - i - 1 + 1)); + + fail_if(strcmp(buf, tmp_strings[cnt_tmp_strings - i - 1])); + + eina_tmpstr_del(tmp_strings[cnt_tmp_strings - i - 1]); + tmp_strings[cnt_tmp_strings - i - 1] = 0; + } + + // Delete non tmp string (should do nothing) + eina_tmpstr_del("Some non tmp string"); + + eina_shutdown(); +} +END_TEST + +START_TEST(tmpstr_manage) +{ + eina_init(); + + char *buf = malloc(7); + strcpy(buf, "tmpstr"); + Eina_Tmpstr *tstr1 = eina_tmpstr_manage_new(buf); + fail_if(strcmp(buf, tstr1)); + eina_tmpstr_del(tstr1); + + eina_shutdown(); +} +END_TEST + +START_TEST(tmpstr_manage_len) +{ + eina_init(); + + char *buf = malloc(10); + strcpy(buf, "tmpstr"); + Eina_Tmpstr *tstr1 = eina_tmpstr_manage_new_length(buf, 7); + fail_if(strcmp(buf, tstr1)); + eina_tmpstr_del(tstr1); + + eina_shutdown(); +} +END_TEST + START_TEST(tmpstr_len) { eina_init(); @@ -86,5 +150,8 @@ void eina_test_tmpstr(TCase *tc) { tcase_add_test(tc, tmpstr_simple); + tcase_add_test(tc, tmpstr_simple_len); + tcase_add_test(tc, tmpstr_manage); + tcase_add_test(tc, tmpstr_manage_len); tcase_add_test(tc, tmpstr_len); } -- 2.7.4