Hi!
I've been wondering why there are ways to append to a strbuf but no way to
create one from scratch providing a format string and arguments. Actually,
I've found a few places where a strbuf is created (with its default size) and
then appended to, possibly causing a reallocation. I think the code overhead
of doing it in two steps and the runtime overhead for the reallocation are
unnecessary. They are even dangerous in out-of-memory situations if not done
correctly.
Please have a look at the attached patch. It provides two new functions,
eina_strbuf_new_printf() and eina_strbuf_new_vprintf(). I'm aware that the
implementation is far from ideal, since it doesn't avoid the useless double
allocation. Also, the version for wide character strings is missing. Still, I
wanted to ask if there is any interest in such an eina extension and whether
the interface is acceptable.
Cheers!
Uli
Index: src/tests/eina_test_strbuf.c
===================================================================
--- src/tests/eina_test_strbuf.c (revision 63441)
+++ src/tests/eina_test_strbuf.c (working copy)
@@ -375,7 +375,7 @@
eina_init();
buf = eina_strbuf_new();
- fail_if(!buf);
+ fail_if(!buf);
for (i = 0; i < runs; i++)
{
@@ -428,12 +428,35 @@
for (i = 0; i < runs; i++, str += target_pattern_size)
fail_if(memcmp(str, target_pattern, target_pattern_size));
- eina_strbuf_free(buf);
+ eina_strbuf_free(buf);
eina_shutdown();
}
END_TEST
+START_TEST(strbuf_new_printf)
+{
+ Eina_Strbuf *buf;
+
+ eina_init();
+
+ // simple case, nothing to format, just copy the string
+ buf = eina_strbuf_new_printf("abc");
+ fail_if(!buf);
+ fail_if(strcmp(eina_strbuf_string_get(buf), "abc"));
+ eina_strbuf_free(buf);
+
+ // format an int and a string
+ buf = eina_strbuf_new_printf("abc(%d)%s", 20, "xyz");
+ fail_if(!buf);
+ fail_if(strcmp(eina_strbuf_string_get(buf), "abc(20)xyz"));
+ eina_strbuf_free(buf);
+
+ eina_shutdown();
+}
+END_TEST
+
+
void
eina_test_strbuf(TCase *tc)
{
@@ -446,4 +469,5 @@
tcase_add_test(tc, strbuf_append_realloc);
tcase_add_test(tc, strbuf_prepend_realloc);
tcase_add_test(tc, strbuf_manage_simple);
+ tcase_add_test(tc, strbuf_new_printf);
}
Index: src/include/eina_strbuf.h
===================================================================
--- src/include/eina_strbuf.h (revision 63441)
+++ src/include/eina_strbuf.h (working copy)
@@ -80,6 +80,43 @@
EAPI Eina_Strbuf *eina_strbuf_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
/**
+ * @brief Create a new string buffer
+ *
+ * @param fmt The format string.
+ * @return Newly allocated string buffer instance.
+ *
+ * This function creates a new string buffer and formats it according to the
+ * format specifier given in printf() format. 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_new()
+ * @see eina_strbuf_new_vprintf()
+ * @since 1.1
+ */
+EAPI Eina_Strbuf *eina_strbuf_new_printf(char const* fmt, ...) EINA_PRINTF(1, 2);
+
+/**
+ * @brief Create a new string buffer
+ *
+ * @param fmt The format string.
+ * @param args The variable arguments.
+ * @return Newly allocated string buffer instance.
+ *
+ * This function creates a new string buffer and formats it according to the
+ * format specifier given in printf() format. 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_new()
+ * @see eina_strbuf_new_vprintf()
+ * @since 1.1
+ */
+EAPI Eina_Strbuf *eina_strbuf_new_vprintf(char const* fmt, va_list args);
+
+/**
* @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.
Index: src/lib/eina_strbuf.c
===================================================================
--- src/lib/eina_strbuf.c (revision 63441)
+++ src/lib/eina_strbuf.c (working copy)
@@ -81,6 +81,38 @@
*============================================================================*/
+EAPI Eina_Strbuf*
+eina_strbuf_new_printf(const char *fmt, ...)
+{
+ va_list args;
+ Eina_Strbuf *buf;
+
+ va_start(args, fmt);
+ buf = eina_strbuf_new_vprintf(fmt, args);
+ va_end(args);
+
+ return buf;
+}
+
+EAPI Eina_Strbuf*
+eina_strbuf_new_vprintf(const char *fmt, va_list args)
+{
+ Eina_Strbuf *buf;
+
+ /* TODO: Instead of default-allocating a stringbuffer here, we could
+ use vasprintf() and then create the stringbuffer with the exact size
+ that we need. */
+ buf = eina_strbuf_new();
+ if (buf == NULL)
+ return NULL;
+
+ if (eina_strbuf_append_vprintf(buf, fmt, args))
+ return buf;
+
+ eina_strbuf_free(buf);
+ return NULL;
+}
+
EAPI Eina_Bool
eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...)
{
------------------------------------------------------------------------------
BlackBerry® DevCon Americas, Oct. 18-20, San Francisco, CA
http://p.sf.net/sfu/rim-devcon-copy2
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel