diff --git a/legacy/eina/src/lib/eina_strbuf.c b/legacy/eina/src/lib/eina_strbuf.c index a28b9e91dd..ee5bd49f40 100644 --- a/legacy/eina/src/lib/eina_strbuf.c +++ b/legacy/eina/src/lib/eina_strbuf.c @@ -717,50 +717,34 @@ _eina_strbuf_grow(Eina_Strbuf *buf, size_t size) static inline Eina_Bool _eina_strbuf_resize(Eina_Strbuf *buf, size_t size) { + size_t new_size, new_step, delta; char *buffer; - size_t new_size; - size_t new_step; size += 1; // Add extra space for '\0' - new_size = buf->size; - new_step = buf->step; - - /* - * first we have to determine the new buffer size - */ if (size == buf->size) /* nothing to do */ return EINA_TRUE; else if (size > buf->size) - { - /* enlarge the buffer */ - while (size > new_size) - { - new_size += new_step; - if (new_step < EINA_STRBUF_MAX_STEP) - new_step *= 2; - if (new_step > EINA_STRBUF_MAX_STEP) - new_step = EINA_STRBUF_MAX_STEP; - } - } + delta = size - buf->size; + else + delta = buf->size - size; + + /* check if should keep the same step (just used while growing) */ + if ((delta <= buf->step) && (size > buf->size)) + new_step = buf->step; else { - /* shrink the buffer */ - if (new_step > EINA_STRBUF_INIT_STEP) - new_step /= 2; - while (new_size - new_step > size) - { - new_size -= new_step; - if (new_step > EINA_STRBUF_INIT_STEP) - new_step /= 2; - if (new_step < EINA_STRBUF_INIT_STEP) - new_step = EINA_STRBUF_INIT_STEP; - } + new_step = (((delta / EINA_STRBUF_INIT_STEP) + 1) + * EINA_STRBUF_INIT_STEP); + + if (new_step > EINA_STRBUF_MAX_STEP) + new_step = EINA_STRBUF_MAX_STEP; } + new_size = (((size / new_step) + 1) * new_step); + /* reallocate the buffer to the new size */ - eina_error_set(0); buffer = realloc(buf->buf, new_size); if (EINA_UNLIKELY(!buffer)) { @@ -771,6 +755,7 @@ _eina_strbuf_resize(Eina_Strbuf *buf, size_t size) buf->buf = buffer; buf->size = new_size; buf->step = new_step; + eina_error_set(0); return EINA_TRUE; } diff --git a/legacy/eina/src/tests/eina_test_strbuf.c b/legacy/eina/src/tests/eina_test_strbuf.c index 9c8ae59807..a2ad749824 100644 --- a/legacy/eina/src/tests/eina_test_strbuf.c +++ b/legacy/eina/src/tests/eina_test_strbuf.c @@ -252,6 +252,74 @@ START_TEST(strbuf_replace) } END_TEST +START_TEST(strbuf_realloc) +{ + Eina_Strbuf *buf; + char pattern[1024 * 16]; + unsigned int i; + size_t sz; + + for (i = 0; i < sizeof(pattern) - 1; i++) + pattern[i] = 'a' + (i % 26); + pattern[i] = '\0'; + + eina_init(); + + buf = eina_strbuf_new(); + fail_if(!buf); + + sz = 0; + + eina_strbuf_append_length(buf, pattern, 1); + fail_if(eina_strbuf_length_get(buf) != sz + 1); + fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 1)); + sz += 1; + + eina_strbuf_append_length(buf, pattern, 32); + fail_if(eina_strbuf_length_get(buf) != sz + 32); + fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 32)); + sz += 32; + + eina_strbuf_append_length(buf, pattern, 64); + fail_if(eina_strbuf_length_get(buf) != sz + 64); + fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 64)); + sz += 64; + + eina_strbuf_append_length(buf, pattern, 128); + fail_if(eina_strbuf_length_get(buf) != sz + 128); + fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 128)); + sz += 128; + + eina_strbuf_append_length(buf, pattern, 4096); + fail_if(eina_strbuf_length_get(buf) != sz + 4096); + fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, 4096)); + sz += 4096; + + eina_strbuf_append_length(buf, pattern, sizeof(pattern) - 1); + fail_if(eina_strbuf_length_get(buf) != sz + sizeof(pattern) - 1); + fail_if(memcmp(eina_strbuf_string_get(buf) + sz, pattern, sizeof(pattern) - 1)); + sz += sizeof(pattern) - 1; + + + eina_strbuf_remove(buf, 1024, 1024 + 1234); + fail_if(eina_strbuf_length_get(buf) != sz - 1234); + sz -= 1234; + + eina_strbuf_remove(buf, 0, 0 + 8192); + fail_if(eina_strbuf_length_get(buf) != sz - 8192); + sz -= 8192; + + eina_strbuf_remove(buf, 0, 0 + 32); + fail_if(eina_strbuf_length_get(buf) != sz - 32); + sz -= 32; + + + eina_strbuf_free(buf); + + eina_shutdown(); +} +END_TEST + START_TEST(strbuf_append_realloc) { Eina_Strbuf *buf; @@ -330,6 +398,7 @@ eina_test_strbuf(TCase *tc) tcase_add_test(tc, strbuf_append); tcase_add_test(tc, strbuf_insert); tcase_add_test(tc, strbuf_replace); + tcase_add_test(tc, strbuf_realloc); tcase_add_test(tc, strbuf_append_realloc); tcase_add_test(tc, strbuf_prepend_realloc); }