Eina: Added Eina_UStrbuf.
authortasn <tasn>
Tue, 27 Jul 2010 09:05:41 +0000 (09:05 +0000)
committertasn <tasn@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 27 Jul 2010 09:05:41 +0000 (09:05 +0000)
Same as Eina_Strbuf but for Eina_Unicode strings.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@50534 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/include/Eina.h
src/include/Makefile.am
src/include/eina_strbuf.h
src/include/eina_ustrbuf.h [new file with mode: 0644]
src/lib/Makefile.am
src/lib/eina_main.c
src/lib/eina_strbuf.c
src/lib/eina_strbuf_common.c [new file with mode: 0644]
src/lib/eina_strbuf_common.h [new file with mode: 0644]
src/lib/eina_strbuf_template_c.i [new file with mode: 0644]
src/lib/eina_ustrbuf.c [new file with mode: 0644]

index 2cc7f5d..f44d184 100644 (file)
@@ -152,6 +152,7 @@ extern "C" {
 #include "eina_matrixsparse.h"
 #include "eina_str.h"
 #include "eina_strbuf.h"
+#include "eina_ustrbuf.h"
 #include "eina_unicode.h"
 #include "eina_quadtree.h"
 
index 52eed11..ee8ce46 100644 (file)
@@ -49,6 +49,7 @@ eina_inline_tiler.x \
 eina_str.h \
 eina_inline_str.x \
 eina_strbuf.h \
+eina_ustrbuf.h \
 eina_unicode.h \
 eina_quadtree.h
 
index 07c2741..d425fd5 100644 (file)
@@ -2,6 +2,7 @@
 #define EINA_STRBUF_H
 
 #include <stddef.h>
+#include <stdarg.h>
 
 #include "eina_types.h"
 
  *
  * @{
  */
-
 /**
- * @defgroup Eina_String_Buffer_Group String Buffer
+ * @addtogroup Eina_String_Buffer_Group String Buffer
+ *
+ * @brief These functions provide string buffers management.
+ *
+ * The String Buffer data type is designed to be a mutable string,
+ * allowing to append, prepend or insert a string to a buffer. 
  *
  * @{
  */
-
 /**
  * @typedef Eina_Strbuf
  * Type for a string buffer.
  */
 typedef struct _Eina_Strbuf Eina_Strbuf;
 
+/**
+ * @brief Create a new string buffer.
+ *
+ * @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()
+ */
 EAPI Eina_Strbuf *eina_strbuf_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
+/**
+ * @brief Free a string buffer.
+ *
+ * @param buf The string buffer to free.
+ *
+ * This function frees the memory of @p buf. @p buf must have been
+ * created by eina_strbuf_new().
+ */
 EAPI void eina_strbuf_free(Eina_Strbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @brief Reset a string buffer.
+ *
+ * @param buf The string buffer to reset.
+ *
+ * This function reset @p buf: the buffer len is set to 0, and the
+ * string is set to '\\0'. No memory is free'd.
+ */
 EAPI void eina_strbuf_reset(Eina_Strbuf *buf) EINA_ARG_NONNULL(1);
 
+/**
+ * @brief Append a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends @p str to @p buf. It computes the length of
+ * @p str, so is slightly slower than eina_strbuf_append_length(). If
+ * the length is known beforehand, consider using that variant. If
+ * @p buf can't append it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ *
+ * @see eina_strbuf_append()
+ * @see eina_strbuf_append_length()
+ */
 EAPI Eina_Bool eina_strbuf_append(Eina_Strbuf *buf, const char *str) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append an escaped string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends the escaped string @p str to @p buf. If @p
+ * str can not be appended, #EINA_FALSE is returned, otherwise,
+ * #EINA_TRUE is returned.
+ */
 EAPI Eina_Bool eina_strbuf_append_escaped(Eina_Strbuf *buf, const char *str) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append a string to a buffer, reallocating as necessary,
+ * limited by the given length.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @param maxlen The maximum number of characters to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends at most @p maxlen characters of @p str to
+ * @p buf. It can't appends more than the length of @p str. It
+ * computes the length of @p str, so is slightly slower than
+ * eina_strbuf_append_length(). If the length is known beforehand,
+ * consider using that variant (@p maxlen should then be checked so
+ * that it is greater than the size of @p str). If @p str can not be
+ * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_strbuf_append()
+ * @see eina_strbuf_append_length()
+ */
 EAPI Eina_Bool eina_strbuf_append_n(Eina_Strbuf *buf, const char *str, size_t maxlen) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append a string of exact length to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @param length The exact length to use.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends @p str to @p buf. @p str must be of size at
+ * most @p length. It is slightly faster than eina_strbuf_append() as
+ * it does not compute the size of @p str. It is useful when dealing
+ * with strings of known size, such as eina_strngshare. If @p buf
+ * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_stringshare_length()
+ * @see eina_strbuf_append()
+ * @see eina_strbuf_append_n()
+ */
 EAPI Eina_Bool eina_strbuf_append_length(Eina_Strbuf *buf, const char *str, size_t length) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append a character to a string buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param c The char to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p c to @p buf. If it can not insert it,
+ * #EINA_FALSE is returned, otherwise #EINA_TRUE is returned.
+ */
 EAPI Eina_Bool eina_strbuf_append_char(Eina_Strbuf *buf, char c) EINA_ARG_NONNULL(1);
+/**
+ * @brief Append a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param fmt The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * @see eina_strbuf_append()
+ */
 EAPI Eina_Bool eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...) EINA_ARG_NONNULL(1, 2) EINA_PRINTF(2, 3);
+/**
+ * @brief Append a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param fmt The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * @see eina_strbuf_append()
+ */
 EAPI Eina_Bool eina_strbuf_append_vprintf(Eina_Strbuf *buf, const char *fmt, va_list args) EINA_ARG_NONNULL(1, 2);
-
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert.
+ * @param str The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str to @p buf at position @p pos. It
+ * computes the length of @p str, so is slightly slower than
+ * eina_strbuf_insert_length(). If  the length is known beforehand,
+ * consider using that variant. If @p buf can't insert it, #EINA_FALSE
+ * is returned, otherwise #EINA_TRUE is returned.
+ */
 EAPI Eina_Bool eina_strbuf_insert(Eina_Strbuf *buf, const char *str, size_t pos) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Insert an escaped string to a buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts the escaped string @p str to @p buf at
+ * position @p pos. If @p buf can't insert @p str, #EINA_FALSE is
+ * returned, otherwise #EINA_TRUE is returned.
+ */
 EAPI Eina_Bool eina_strbuf_insert_escaped(Eina_Strbuf *buf, const char *str, size_t pos) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param maxlen The maximum number of chars to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str ot @p buf at position @p pos, with at
+ * most @p maxlen bytes. The number of inserted characters can not be
+ * greater than the length of @p str. It computes the length of
+ * @p str, so is slightly slower than eina_strbuf_insert_length(). If the
+ * length is known beforehand, consider using that variant (@p maxlen
+ * should then be checked so that it is greater than the size of
+ * @p str). If @p str can not be inserted, #EINA_FALSE is returned,
+ * otherwise, #EINA_TRUE is returned.
+ */
 EAPI Eina_Bool eina_strbuf_insert_n(Eina_Strbuf *buf, const char *str, size_t maxlen, size_t pos) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Insert a string of exact length to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param length The exact length to use.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str to @p buf. @p str must be of size at
+ * most @p length. It is slightly faster than eina_strbuf_insert() as
+ * it does not compute the size of @p str. It is useful when dealing
+ * with strings of known size, such as eina_strngshare. If @p buf
+ * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_stringshare_length()
+ * @see eina_strbuf_insert()
+ * @see eina_strbuf_insert_n()
+ */
 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 character to a string buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param c The char to insert.
+ * @param pos The position to insert the char.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p c to @p buf at position @p pos. If @p buf
+ * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ */
 EAPI Eina_Bool eina_strbuf_insert_char(Eina_Strbuf *buf, char c, size_t pos) EINA_ARG_NONNULL(1);
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert.
+ * @param fmt The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ */
 EAPI Eina_Bool eina_strbuf_insert_printf(Eina_Strbuf *buf, const char *fmt, size_t pos, ...) EINA_ARG_NONNULL(1, 2) EINA_PRINTF(2, 4);
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert.
+ * @param fmt The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ */
 EAPI Eina_Bool eina_strbuf_insert_vprintf(Eina_Strbuf *buf, const char *fmt, size_t pos, va_list args) EINA_ARG_NONNULL(1, 2);
 
 /**
@@ -143,11 +365,67 @@ EAPI Eina_Bool eina_strbuf_insert_vprintf(Eina_Strbuf *buf, const char *fmt, siz
  */
 #define eina_strbuf_prepend_vprintf(buf, fmt, args) eina_strbuf_insert_vprintf(buf, fmt, 0, args)
 
+/**
+ * @brief Remove a slice of the given string buffer.
+ *
+ * @param buf The string buffer to remove a slice.
+ * @param start The initial (inclusive) slice position to start
+ *        removing, in bytes.
+ * @param end The final (non-inclusive) slice position to finish
+ *        removing, in bytes.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function removes a slice of @p buf, starting at @p start
+ * (inclusive) and ending at @p end (non-inclusive). Both values are
+ * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
+ */
 
 EAPI Eina_Bool eina_strbuf_remove(Eina_Strbuf *buf, size_t start, size_t end) EINA_ARG_NONNULL(1);
+/**
+ * @brief Retrieve a pointer to the contents of a string buffer
+ *
+ * @param buf The string buffer.
+ * @return The current string in the string buffer.
+ *
+ * This function returns the string contained in @p buf. The returned
+ * value must not be modified and will no longer be valid if @p buf is
+ * modified. In other words, any eina_strbuf_append() or similar will
+ * make that pointer invalid.
+ *
+ * @see eina_strbuf_string_steal()
+ */
 EAPI const char *eina_strbuf_string_get(const Eina_Strbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @brief Steal the contents of a string buffer.
+ *
+ * @param buf The string buffer to steal.
+ * @return The current string in the string buffer.
+ *
+ * This function returns the string contained in @p buf. @p buf is
+ * then initialized and does not own the returned string anymore. The
+ * caller must release the memory of the returned string by calling
+ * free(). 
+ *
+ * @see eina_strbuf_string_get()
+ */
 EAPI char *eina_strbuf_string_steal(Eina_Strbuf *buf) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+/**
+ * @brief Free the contents of a string buffer but not the buffer.
+ *
+ * @param buf The string buffer to free the string of.
+  *
+ * This function frees the string contained in @p buf without freeing
+ * @p buf.
+ */
 EAPI void eina_strbuf_string_free(Eina_Strbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @brief Retrieve the length of the string buffer content.
+ *
+ * @param buf The string buffer.
+ * @return The current length of the string, in bytes.
+ *
+ * This function returns the length of @p buf.
+ */
 EAPI size_t eina_strbuf_length_get(const Eina_Strbuf *buf) EINA_ARG_NONNULL(1);
 EAPI Eina_Bool eina_strbuf_replace(Eina_Strbuf *buf, const char *str, const char *with, unsigned int n) EINA_ARG_NONNULL(1, 2, 3);
 
@@ -171,9 +449,7 @@ EAPI int eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *
 /**
  * @}
  */
-
 /**
  * @}
  */
-
 #endif /* EINA_STRBUF_H */
diff --git a/src/include/eina_ustrbuf.h b/src/include/eina_ustrbuf.h
new file mode 100644 (file)
index 0000000..c5f16bd
--- /dev/null
@@ -0,0 +1,401 @@
+#ifndef EINA_USTRBUF_H
+#define EINA_USTRBUF_H
+
+#include <stddef.h>
+
+#include "eina_types.h"
+#include "eina_unicode.h"
+
+/**
+ * @addtogroup Eina_Data_Types_Group Data Types
+ *
+ * @{
+ */
+/**
+ * @addtogroup Eina_Unicode_String_Buffer_Group Unicode String Buffer
+ *
+ * @brief These functions provide unicode string buffers management.
+ *
+ * The Unicode String Buffer data type is designed to be a mutable string,
+ * allowing to append, prepend or insert a string to a buffer. 
+ *
+ * @{
+ */
+
+/**
+ * @typedef Eina_UStrbuf
+ * Type for a string buffer.
+ */
+typedef struct _Eina_Strbuf Eina_UStrbuf;
+
+/**
+ * @brief Create a new string buffer.
+ *
+ * @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_ustrbuf_free().
+ *
+ * @see eina_ustrbuf_free()
+ * @see eina_ustrbuf_append()
+ * @see eina_ustrbuf_string_get()
+ */
+EAPI Eina_UStrbuf *eina_ustrbuf_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Free a string buffer.
+ *
+ * @param buf The string buffer to free.
+ *
+ * This function frees the memory of @p buf. @p buf must have been
+ * created by eina_ustrbuf_new().
+ */
+EAPI void eina_ustrbuf_free(Eina_UStrbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @brief Reset a string buffer.
+ *
+ * @param buf The string buffer to reset.
+ *
+ * This function reset @p buf: the buffer len is set to 0, and the
+ * string is set to '\\0'. No memory is free'd.
+ */
+EAPI void eina_ustrbuf_reset(Eina_UStrbuf *buf) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Append a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends @p str to @p buf. It computes the length of
+ * @p str, so is slightly slower than eina_ustrbuf_append_length(). If
+ * the length is known beforehand, consider using that variant. If
+ * @p buf can't append it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ *
+ * @see eina_ustrbuf_append()
+ * @see eina_ustrbuf_append_length()
+ */
+EAPI Eina_Bool eina_ustrbuf_append(Eina_UStrbuf *buf, const Eina_Unicode *str) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append an escaped string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends the escaped string @p str to @p buf. If @p
+ * str can not be appended, #EINA_FALSE is returned, otherwise,
+ * #EINA_TRUE is returned.
+ */
+EAPI Eina_Bool eina_ustrbuf_append_escaped(Eina_UStrbuf *buf, const Eina_Unicode *str) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append a string to a buffer, reallocating as necessary,
+ * limited by the given length.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @param maxlen The maximum number of characters to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends at most @p maxlen characters of @p str to
+ * @p buf. It can't appends more than the length of @p str. It
+ * computes the length of @p str, so is slightly slower than
+ * eina_ustrbuf_append_length(). If the length is known beforehand,
+ * consider using that variant (@p maxlen should then be checked so
+ * that it is greater than the size of @p str). If @p str can not be
+ * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_ustrbuf_append()
+ * @see eina_ustrbuf_append_length()
+ */
+EAPI Eina_Bool eina_ustrbuf_append_n(Eina_UStrbuf *buf, const Eina_Unicode *str, size_t maxlen) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Append a string of exact length to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @param length The exact length to use.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends @p str to @p buf. @p str must be of size at
+ * most @p length. It is slightly faster than eina_ustrbuf_append() as
+ * it does not compute the size of @p str. It is useful when dealing
+ * with strings of known size, such as eina_strngshare. If @p buf
+ * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_stringshare_length()
+ * @see eina_ustrbuf_append()
+ * @see eina_ustrbuf_append_n()
+ */
+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 character to a string buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param c The char to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p c to @p buf. If it can not insert it,
+ * #EINA_FALSE is returned, otherwise #EINA_TRUE is returned.
+ */
+EAPI Eina_Bool eina_ustrbuf_append_char(Eina_UStrbuf *buf, Eina_Unicode c) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert.
+ * @param str The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str to @p buf at position @p pos. It
+ * computes the length of @p str, so is slightly slower than
+ * eina_ustrbuf_insert_length(). If  the length is known beforehand,
+ * consider using that variant. If @p buf can't insert it, #EINA_FALSE
+ * is returned, otherwise #EINA_TRUE is returned.
+ */
+EAPI Eina_Bool eina_ustrbuf_insert(Eina_UStrbuf *buf, const Eina_Unicode *str, size_t pos) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Insert an escaped string to a buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts the escaped string @p str to @p buf at
+ * position @p pos. If @p buf can't insert @p str, #EINA_FALSE is
+ * returned, otherwise #EINA_TRUE is returned.
+ */
+EAPI Eina_Bool eina_ustrbuf_insert_escaped(Eina_UStrbuf *buf, const Eina_Unicode *str, size_t pos) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param maxlen The maximum number of chars to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str ot @p buf at position @p pos, with at
+ * most @p maxlen bytes. The number of inserted characters can not be
+ * greater than the length of @p str. It computes the length of
+ * @p str, so is slightly slower than eina_ustrbuf_insert_length(). If the
+ * length is known beforehand, consider using that variant (@p maxlen
+ * should then be checked so that it is greater than the size of
+ * @p str). If @p str can not be inserted, #EINA_FALSE is returned,
+ * otherwise, #EINA_TRUE is returned.
+ */
+EAPI Eina_Bool eina_ustrbuf_insert_n(Eina_UStrbuf *buf, const Eina_Unicode *str, size_t maxlen, size_t pos) EINA_ARG_NONNULL(1, 2);
+/**
+ * @brief Insert a string of exact length to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param length The exact length to use.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str to @p buf. @p str must be of size at
+ * most @p length. It is slightly faster than eina_ustrbuf_insert() as
+ * it does not compute the size of @p str. It is useful when dealing
+ * with strings of known size, such as eina_strngshare. If @p buf
+ * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_stringshare_length()
+ * @see eina_ustrbuf_insert()
+ * @see eina_ustrbuf_insert_n()
+ */
+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 character to a string buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param c The char to insert.
+ * @param pos The position to insert the char.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p c to @p buf at position @p pos. If @p buf
+ * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ */
+EAPI Eina_Bool eina_ustrbuf_insert_char(Eina_UStrbuf *buf, Eina_Unicode c, size_t pos) EINA_ARG_NONNULL(1);
+
+/**
+ * @def eina_ustrbuf_prepend(buf, str)
+ * @brief Prepend the given string to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param str The string to prepend.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert() at position 0.If @p buf
+ * can't prepend it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ */
+#define eina_ustrbuf_prepend(buf, str) eina_ustrbuf_insert(buf, str, 0)
+
+/**
+ * @def eina_ustrbuf_prepend_escaped(buf, str)
+ * @brief Prepend the given escaped string to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param str The string to prepend.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert_escaped() at position 0. If
+ * @p buf can't prepend it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ */
+#define eina_ustrbuf_prepend_escaped(buf, str) eina_ustrbuf_insert_escaped(buf, str, 0)
+
+/**
+ * @def eina_ustrbuf_prepend_n(buf, str)
+ * @brief Prepend the given escaped string to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param str The string to prepend.
+ * @param maxlen The maximum number of Eina_Unicode *s to prepend.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert_n() at position 0. If
+ * @p buf can't prepend it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ */
+#define eina_ustrbuf_prepend_n(buf, str, maxlen) eina_ustrbuf_insert_n(buf, str, maxlen, 0)
+
+/**
+ * @def eina_ustrbuf_prepend_length(buf, str)
+ * @brief Prepend the given escaped string to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param str The string to prepend.
+ * @param length The exact length to use.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert_length() at position 0. If
+ * @p buf can't prepend it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ */
+#define eina_ustrbuf_prepend_length(buf, str, length) eina_ustrbuf_insert_length(buf, str, length, 0)
+
+/**
+ * @def eina_ustrbuf_prepend_Eina_Unicode *(buf, str)
+ * @brief Prepend the given Eina_Unicode *acter to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param c The Eina_Unicode *acter to prepend.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert_Eina_Unicode *() at position 0. If
+ * @p buf can't prepend it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ */
+#define eina_ustrbuf_prepend_Eina_Unicode *(buf, c) eina_ustrbuf_insert_Eina_Unicode *(buf, c, 0)
+
+/**
+ * @def eina_ustrbuf_prepend_printf(buf, fmt, ...)
+ * @brief Prepend the given string to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param str The string to prepend.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert_printf() at position 0.If @p buf
+ * can't prepend it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ */
+#define eina_ustrbuf_prepend_printf(buf, fmt, ...) eina_ustrbuf_insert_printf(buf, fmt, 0, ##__VA_ARGS__)
+
+/**
+ * @def eina_ustrbuf_prepend_vprintf(buf, fmt, args)
+ * @brief Prepend the given string to the given buffer
+ *
+ * @param buf The string buffer to prepend to.
+ * @param fmt The string to prepend.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This macro is calling eina_ustrbuf_insert_vprintf() at position 0.If @p buf
+ * can't prepend it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ */
+#define eina_ustrbuf_prepend_vprintf(buf, fmt, args) eina_ustrbuf_insert_vprintf(buf, fmt, 0, args)
+
+/**
+ * @brief Remove a slice of the given string buffer.
+ *
+ * @param buf The string buffer to remove a slice.
+ * @param start The initial (inclusive) slice position to start
+ *        removing, in bytes.
+ * @param end The final (non-inclusive) slice position to finish
+ *        removing, in bytes.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function removes a slice of @p buf, starting at @p start
+ * (inclusive) and ending at @p end (non-inclusive). Both values are
+ * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
+ */
+EAPI Eina_Bool eina_ustrbuf_remove(Eina_UStrbuf *buf, size_t start, size_t end) EINA_ARG_NONNULL(1);
+/**
+ * @brief Retrieve a pointer to the contents of a string buffer
+ *
+ * @param buf The string buffer.
+ * @return The current string in the string buffer.
+ *
+ * This function returns the string contained in @p buf. The returned
+ * value must not be modified and will no longer be valid if @p buf is
+ * modified. In other words, any eina_ustrbuf_append() or similar will
+ * make that pointer invalid.
+ *
+ * @see eina_ustrbuf_string_steal()
+ */
+EAPI const Eina_Unicode *eina_ustrbuf_string_get(const Eina_UStrbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @brief Steal the contents of a string buffer.
+ *
+ * @param buf The string buffer to steal.
+ * @return The current string in the string buffer.
+ *
+ * This function returns the string contained in @p buf. @p buf is
+ * then initialized and does not own the returned string anymore. The
+ * caller must release the memory of the returned string by calling
+ * free(). 
+ *
+ * @see eina_ustrbuf_string_get()
+ */
+EAPI Eina_Unicode *eina_ustrbuf_string_steal(Eina_UStrbuf *buf) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+/**
+ * @brief Free the contents of a string buffer but not the buffer.
+ *
+ * @param buf The string buffer to free the string of.
+  *
+ * This function frees the string contained in @p buf without freeing
+ * @p buf.
+ */
+EAPI void eina_ustrbuf_string_free(Eina_UStrbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @brief Retrieve the length of the string buffer content.
+ *
+ * @param buf The string buffer.
+ * @return The current length of the string, in bytes.
+ *
+ * This function returns the length of @p buf.
+ */
+EAPI size_t eina_ustrbuf_length_get(const Eina_UStrbuf *buf) EINA_ARG_NONNULL(1);
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+#endif /* EINA_STRBUF_H */
index 740a3d4..35519c6 100644 (file)
@@ -42,6 +42,8 @@ eina_hamster.c \
 eina_safety_checks.c \
 eina_str.c \
 eina_strbuf.c \
+eina_strbuf_common.c \
+eina_ustrbuf.c \
 eina_unicode.c \
 eina_quadtree.c
 
index d1c62dc..88949ae 100644 (file)
@@ -118,6 +118,7 @@ S(counter);
 S(benchmark);
 S(rectangle);
 S(strbuf);
+S(ustrbuf);
 S(quadtree);
 #undef S
 
@@ -148,6 +149,7 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
   S(benchmark),
   S(rectangle),
   S(strbuf),
+  S(ustrbuf),
   S(quadtree)
 #undef S
 };
index 8a90096..feafea4 100644 (file)
-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
+#define _STRBUF_DATA_TYPE         char
+#define _STRBUF_CSIZE             sizeof(_STRBUF_DATA_TYPE)
+#define _STRBUF_STRUCT_NAME       Eina_Strbuf
+#define _STRBUF_STRLEN_FUNC(x)    strlen(x)
+#define _STRBUF_STRESCAPE_FUNC(x) eina_str_escape(x)
+#define _STRBUF_MAGIC             EINA_MAGIC_STRBUF
+static const char _STRBUF_MAGIC_STR[] = "Eina Strbuf";
 
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#define _FUNC_EXPAND(y) eina_strbuf_##y
 
+#define _GNU_SOURCE
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 
-#ifdef _WIN32
-# include <Evil.h>
-#endif
 
-#include "eina_private.h"
-#include "eina_str.h"
-#include "eina_magic.h"
-#include "eina_error.h"
-#include "eina_safety_checks.h"
 #include "eina_strbuf.h"
+#include "eina_strbuf_common.h"
+#include "eina_unicode.h"
+#include "eina_private.h"
 
-/*============================================================================*
- *                                  Local                                     *
- *============================================================================*/
-
-/**
- * @cond LOCAL
- */
-
-static const char EINA_MAGIC_STRBUF_STR[] = "Eina Strbuf";
-
-#define EINA_MAGIC_CHECK_STRBUF(d, ...)                                \
-   do {                                                                \
-       if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_STRBUF))          \
-         {                                                     \
-            EINA_MAGIC_FAIL((d), EINA_MAGIC_STRBUF);           \
-            return __VA_ARGS__;                                \
-         }                                                     \
-   } while (0)
-
-#define EINA_STRBUF_INIT_SIZE 32
-#define EINA_STRBUF_INIT_STEP 32
-#define EINA_STRBUF_MAX_STEP 4096
-
-struct _Eina_Strbuf
-{
-   char *buf;
-   size_t len;
-   size_t size;
-   size_t step;
-
-   EINA_MAGIC
-};
-
-/**
- * @internal
- *
- * init the buffer
- * @param buf the buffer to init
- *
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- */
-static Eina_Bool
-_eina_strbuf_init(Eina_Strbuf *buf)
-{
-   buf->len = 0;
-   buf->size = EINA_STRBUF_INIT_SIZE;
-   buf->step = EINA_STRBUF_INIT_STEP;
-
-   eina_error_set(0);
-   buf->buf = malloc(buf->size);
-   if (EINA_UNLIKELY(!buf->buf))
-     {
-       eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
-       return EINA_FALSE;
-     }
-   buf->buf[0] = '\0';
-   return EINA_TRUE;
-}
-
-/**
- * @internal
- *
- * resize the buffer
- * @param buf the buffer to resize
- * @param size the minimum size of the buffer
- *
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- */
-static inline Eina_Bool
-_eina_strbuf_resize(Eina_Strbuf *buf, size_t size)
-{
-   size_t new_size, new_step, delta;
-   char *buffer;
-
-   size += 1; // Add extra space for '\0'
-
-   if (size == buf->size)
-     /* nothing to do */
-     return EINA_TRUE;
-   else if (size > buf->size)
-     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
-     {
-       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 */
-   buffer = realloc(buf->buf, new_size);
-   if (EINA_UNLIKELY(!buffer))
-     {
-       eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
-       return EINA_FALSE;
-     }
-
-   buf->buf = buffer;
-   buf->size = new_size;
-   buf->step = new_step;
-   eina_error_set(0);
-   return EINA_TRUE;
-}
-
-/**
- * @internal
- *
- * If required, enlarge the buffer to fit the new size.
- *
- * @param buf the buffer to resize
- * @param size the minimum size of the buffer
- *
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- */
-static inline Eina_Bool
-_eina_strbuf_grow(Eina_Strbuf *buf, size_t size)
-{
-   if ((size + 1) < buf->size)
-     return EINA_TRUE;
-   return _eina_strbuf_resize(buf, size);
-}
-
-/**
- * @internal
- *
- * insert string of known length at random within existing strbuf limits.
- *
- * @param buf the buffer to resize, must be valid.
- * @param str the string to copy, must be valid (!NULL and smaller than @a len)
- * @param len the amount of bytes in @a str to copy, must be valid.
- * @param pos the position inside buffer to insert, must be valid (smaller
- *        than eina_strbuf_length_get())
- *
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- */
-static inline Eina_Bool
-_eina_strbuf_insert_length(Eina_Strbuf *buf, const char *str, size_t len, size_t pos)
-{
-   if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len + len)))
-     return EINA_FALSE;
-
-   /* move the existing text */
-   memmove(buf->buf + len + pos, buf->buf + pos, buf->len - pos);
-
-   /* and now insert the given string */
-   memcpy(buf->buf + pos, str, len);
-
-   buf->len += len;
-   buf->buf[buf->len] = '\0';
-   return EINA_TRUE;
-}
-
-/**
- * @endcond
- */
-
-/*============================================================================*
- *                                 Global                                     *
- *============================================================================*/
-
-/**
- * @cond LOCAL
- */
-
-/**
- * @internal
- * @brief Initialize the strbuf module.
- *
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function sets up the strbuf module of Eina. It is called by
- * eina_init().
- *
- * @see eina_init()
- */
-Eina_Bool
-eina_strbuf_init(void)
-{
-   eina_magic_string_static_set(EINA_MAGIC_STRBUF, EINA_MAGIC_STRBUF_STR);
-   return EINA_TRUE;
-}
-
-/**
- * @internal
- * @brief Shut down the strbuf module.
- *
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function shuts down the strbuf module set up by
- * eina_strbuf_init(). It is called by eina_shutdown().
- *
- * @see eina_shutdown()
- */
-Eina_Bool
-eina_strbuf_shutdown(void)
-{
-   return EINA_TRUE;
-}
-
-/**
- * @endcond
- */
-
-/*============================================================================*
- *                                   API                                      *
- *============================================================================*/
-
-/**
- * @addtogroup Eina_String_Buffer_Group String Buffer
- *
- * @brief These functions provide string buffers management.
- *
- * The String Buffer data type is designed to be a mutable string,
- * allowing to append, prepend or insert a string to a buffer. 
- *
- * @{
- */
-
-/**
- * @brief Create a new string buffer.
- *
- * @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()
- */
-EAPI Eina_Strbuf *
-eina_strbuf_new(void)
-{
-   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;
-     }
-   EINA_MAGIC_SET(buf, EINA_MAGIC_STRBUF);
-
-   if (EINA_UNLIKELY(!_eina_strbuf_init(buf)))
-     {
-       eina_strbuf_free(buf);
-       return NULL;
-     }
-
-   return buf;
-}
-
-/**
- * @brief Free a string buffer.
- *
- * @param buf The string buffer to free.
- *
- * This function frees the memory of @p buf. @p buf must have been
- * created by eina_strbuf_new().
- */
-EAPI void
-eina_strbuf_free(Eina_Strbuf *buf)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf);
-   EINA_MAGIC_SET(buf, EINA_MAGIC_NONE);
-
-   free(buf->buf);
-   free(buf);
-}
-
-/**
- * @brief Reset a string buffer.
- *
- * @param buf The string buffer to reset.
- *
- * This function reset @p buf: the buffer len is set to 0, and the
- * string is set to '\\0'. No memory is free'd.
- */
-EAPI void
-eina_strbuf_reset(Eina_Strbuf *buf)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf);
-   buf->len = 0;
-   buf->step = EINA_STRBUF_INIT_STEP;
-
-   buf->buf[0] = '\0';
-}
-
-/**
- * @brief Append a string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to append to.
- * @param str The string to append.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function appends @p str to @p buf. It computes the length of
- * @p str, so is slightly slower than eina_strbuf_append_length(). If
- * the length is known beforehand, consider using that variant. If
- * @p buf can't append it, #EINA_FALSE is returned, otherwise
- * #EINA_TRUE is returned.
- *
- * @see eina_strbuf_append()
- * @see eina_strbuf_append_length()
- */
-EAPI Eina_Bool
-eina_strbuf_append(Eina_Strbuf *buf, const char *str)
-{
-   size_t len;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   len = strlen(str);
-   if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len + len)))
-     return EINA_FALSE;
-   memcpy(buf->buf + buf->len, str, len + 1);
-   buf->len += len;
-   return EINA_TRUE;
-}
-
-/**
- * @brief Append an escaped string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to append to.
- * @param str The string to append.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function appends the escaped string @p str to @p buf. If @p
- * str can not be appended, #EINA_FALSE is returned, otherwise,
- * #EINA_TRUE is returned.
- */
-EAPI Eina_Bool
-eina_strbuf_append_escaped(Eina_Strbuf *buf, const char *str)
-{
-   size_t len;
-   char *esc;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   esc = eina_str_escape(str);
-   if (EINA_UNLIKELY(!esc))
-     return EINA_FALSE;
-   len = strlen(esc);
-   if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len + len)))
-     {
-       free(esc);
-       return EINA_FALSE;
-     }
-   memcpy(buf->buf + buf->len, esc, len + 1);
-   buf->len += len;
-   free(esc);
-   return EINA_TRUE;
-}
-
-/**
- * @brief Append a string to a buffer, reallocating as necessary,
- * limited by the given length.
- *
- * @param buf The string buffer to append to.
- * @param str The string to append.
- * @param maxlen The maximum number of characters to append.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function appends at most @p maxlen characters of @p str to
- * @p buf. It can't appends more than the length of @p str. It
- * computes the length of @p str, so is slightly slower than
- * eina_strbuf_append_length(). If the length is known beforehand,
- * consider using that variant (@p maxlen should then be checked so
- * that it is greater than the size of @p str). If @p str can not be
- * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is
- * returned.
- *
- * @see eina_strbuf_append()
- * @see eina_strbuf_append_length()
- */
-EAPI Eina_Bool
-eina_strbuf_append_n(Eina_Strbuf *buf, const char *str, size_t maxlen)
-{
-   size_t len;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   len = strlen(str);
-   if (len > maxlen) len = maxlen;
-   if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len + len)))
-     return EINA_FALSE;
-
-   memcpy(buf->buf + buf->len, str, len);
-   buf->len += len;
-   buf->buf[buf->len] = '\0';
-   return EINA_TRUE;
-}
-
-/**
- * @brief Append a string of exact length to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to append to.
- * @param str The string to append.
- * @param length The exact length to use.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function appends @p str to @p buf. @p str must be of size at
- * most @p length. It is slightly faster than eina_strbuf_append() as
- * it does not compute the size of @p str. It is useful when dealing
- * with strings of known size, such as eina_strngshare. If @p buf
- * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
- * returned.
- *
- * @see eina_stringshare_length()
- * @see eina_strbuf_append()
- * @see eina_strbuf_append_n()
- */
-EAPI Eina_Bool
-eina_strbuf_append_length(Eina_Strbuf *buf, const char *str, size_t length)
-{
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+#include "eina_strbuf_template_c.i"
 
-   if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len + length)))
-     return EINA_FALSE;
 
-   memcpy(buf->buf + buf->len, str, length);
-   buf->len += length;
-   buf->buf[buf->len] = '\0';
-   return EINA_TRUE;
-}
 
-/**
- * @brief Append a string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to append to.
- * @param fmt The string to append.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * @see eina_strbuf_append()
- */
 EAPI Eina_Bool
 eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...)
 {
@@ -480,9 +29,6 @@ eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...)
    size_t len;
    Eina_Bool ret;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(fmt, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
    va_start(args, fmt);
    len = vasprintf(&str, fmt, args);
    va_end(args);
@@ -495,15 +41,6 @@ eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...)
    return ret;
 }
 
-/**
- * @brief Append a string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to append to.
- * @param fmt The string to append.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * @see eina_strbuf_append()
- */
 EAPI Eina_Bool
 eina_strbuf_append_vprintf(Eina_Strbuf *buf, const char *fmt, va_list args)
 {
@@ -511,9 +48,6 @@ eina_strbuf_append_vprintf(Eina_Strbuf *buf, const char *fmt, va_list args)
    size_t len;
    Eina_Bool ret;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(fmt, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
    len = vasprintf(&str, fmt, args);
 
    if (len <= 0 || !str)
@@ -524,188 +58,6 @@ eina_strbuf_append_vprintf(Eina_Strbuf *buf, const char *fmt, va_list args)
    return ret;
 }
 
-/**
- * @brief Insert a string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to insert.
- * @param str The string to insert.
- * @param pos The position to insert the string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function inserts @p str to @p buf at position @p pos. It
- * computes the length of @p str, so is slightly slower than
- * eina_strbuf_insert_length(). If  the length is known beforehand,
- * consider using that variant. If @p buf can't insert it, #EINA_FALSE
- * is returned, otherwise #EINA_TRUE is returned.
- */
-EAPI Eina_Bool
-eina_strbuf_insert(Eina_Strbuf *buf, const char *str, size_t pos)
-{
-   size_t len;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   if (pos >= buf->len)
-     return eina_strbuf_append(buf, str);
-
-   len = strlen(str);
-   return _eina_strbuf_insert_length(buf, str, len, pos);
-}
-
-/**
- * @brief Insert an escaped string to a buffer, reallocating as
- * necessary.
- *
- * @param buf The string buffer to insert to.
- * @param str The string to insert.
- * @param pos The position to insert the string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function inserts the escaped string @p str to @p buf at
- * position @p pos. If @p buf can't insert @p str, #EINA_FALSE is
- * returned, otherwise #EINA_TRUE is returned.
- */
-EAPI Eina_Bool
-eina_strbuf_insert_escaped(Eina_Strbuf *buf, const char *str, size_t pos)
-{
-   Eina_Bool ret;
-   size_t len;
-   char *esc;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   esc = eina_str_escape(str);
-   if (EINA_UNLIKELY(!esc))
-     return EINA_FALSE;
-   len = strlen(esc);
-   ret = _eina_strbuf_insert_length(buf, esc, len, pos);
-   free(esc);
-   return ret;
-}
-
-/**
- * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen.
- *
- * @param buf The string buffer to insert to.
- * @param str The string to insert.
- * @param maxlen The maximum number of chars to insert.
- * @param pos The position to insert the string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function inserts @p str ot @p buf at position @p pos, with at
- * most @p maxlen bytes. The number of inserted characters can not be
- * greater than the length of @p str. It computes the length of
- * @p str, so is slightly slower than eina_strbuf_insert_length(). If the
- * length is known beforehand, consider using that variant (@p maxlen
- * should then be checked so that it is greater than the size of
- * @p str). If @p str can not be inserted, #EINA_FALSE is returned,
- * otherwise, #EINA_TRUE is returned.
- */
-EAPI Eina_Bool
-eina_strbuf_insert_n(Eina_Strbuf *buf, const char *str, size_t maxlen, size_t pos)
-{
-   size_t len;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   if (pos >= buf->len)
-     return eina_strbuf_append_n(buf, str, maxlen);
-
-   len = strlen(str);
-   if (len > maxlen) len = maxlen;
-   return _eina_strbuf_insert_length(buf, str, len, pos);
-}
-
-/**
- * @brief Insert a string of exact length to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to insert to.
- * @param str The string to insert.
- * @param length The exact length to use.
- * @param pos The position to insert the string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function inserts @p str to @p buf. @p str must be of size at
- * most @p length. It is slightly faster than eina_strbuf_insert() as
- * it does not compute the size of @p str. It is useful when dealing
- * with strings of known size, such as eina_strngshare. If @p buf
- * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
- * returned.
- *
- * @see eina_stringshare_length()
- * @see eina_strbuf_insert()
- * @see eina_strbuf_insert_n()
- */
-EAPI Eina_Bool
-eina_strbuf_insert_length(Eina_Strbuf *buf, const char *str, size_t length, size_t pos)
-{
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   if (pos >= buf->len)
-     return eina_strbuf_append_length(buf, str, length);
-
-   return _eina_strbuf_insert_length(buf, str, length, pos);
-}
-
-/**
- * @brief Append a character to a string buffer, reallocating as
- * necessary.
- *
- * @param buf The string buffer to append to.
- * @param c The char to append.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function inserts @p c to @p buf. If it can not insert it,
- * #EINA_FALSE is returned, otherwise #EINA_TRUE is returned.
- */
-EAPI Eina_Bool
-eina_strbuf_append_char(Eina_Strbuf *buf, char c)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len + 1)))
-     return EINA_FALSE;
-   buf->buf[(buf->len)++] = c;
-   buf->buf[buf->len] = '\0';
-   return EINA_TRUE;
-}
-
-/**
- * @brief Insert a character to a string buffer, reallocating as
- * necessary.
- *
- * @param buf The string buffer to insert to.
- * @param c The char to insert.
- * @param pos The position to insert the char.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function inserts @p c to @p buf at position @p pos. If @p buf
- * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
- * returned.
- */
-EAPI Eina_Bool
-eina_strbuf_insert_char(Eina_Strbuf *buf, char c, size_t pos)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   if (pos >= buf->len)
-     return eina_strbuf_append_char(buf, c);
-
-   return _eina_strbuf_insert_length(buf, &c, 1, pos);
-}
-
-/**
- * @brief Insert a string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to insert.
- * @param fmt The string to insert.
- * @param pos The position to insert the string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- */
 EAPI Eina_Bool
 eina_strbuf_insert_printf(Eina_Strbuf *buf, const char *fmt, size_t pos, ...)
 {
@@ -714,9 +66,6 @@ eina_strbuf_insert_printf(Eina_Strbuf *buf, const char *fmt, size_t pos, ...)
    size_t len;
    Eina_Bool ret;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(fmt, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
    va_start(args, pos);
    len = vasprintf(&str, fmt, args);
    va_end(args);
@@ -729,14 +78,6 @@ eina_strbuf_insert_printf(Eina_Strbuf *buf, const char *fmt, size_t pos, ...)
    return ret;
 }
 
-/**
- * @brief Insert a string to a buffer, reallocating as necessary.
- *
- * @param buf The string buffer to insert.
- * @param fmt The string to insert.
- * @param pos The position to insert the string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- */
 EAPI Eina_Bool
 eina_strbuf_insert_vprintf(Eina_Strbuf *buf, const char *fmt, size_t pos, va_list args)
 {
@@ -744,9 +85,6 @@ eina_strbuf_insert_vprintf(Eina_Strbuf *buf, const char *fmt, size_t pos, va_lis
    size_t len;
    Eina_Bool ret;
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(fmt, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
    len = vasprintf(&str, fmt, args);
 
    if (len <= 0 || !str)
@@ -755,278 +93,4 @@ eina_strbuf_insert_vprintf(Eina_Strbuf *buf, const char *fmt, size_t pos, va_lis
    ret = eina_strbuf_insert(buf, str, pos);
    free(str);
    return ret;
-}
-
-/**
- * @brief Remove a slice of the given string buffer.
- *
- * @param buf The string buffer to remove a slice.
- * @param start The initial (inclusive) slice position to start
- *        removing, in bytes.
- * @param end The final (non-inclusive) slice position to finish
- *        removing, in bytes.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function removes a slice of @p buf, starting at @p start
- * (inclusive) and ending at @p end (non-inclusive). Both values are
- * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
- */
-EAPI Eina_Bool
-eina_strbuf_remove(Eina_Strbuf *buf, size_t start, size_t end)
-{
-   size_t remove_len, tail_len;
-
-   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
-
-   if (end >= buf->len)
-     end = buf->len;
-
-   if (end <= start)
-     return EINA_TRUE;
-
-   remove_len = end - start;
-   if (remove_len == buf->len)
-     {
-       free(buf->buf);
-       return _eina_strbuf_init(buf);
-     }
-
-   tail_len = buf->len - end + 1; /* includes '\0' */
-   memmove(buf->buf + start, buf->buf + end, tail_len);
-   buf->len -= remove_len;
-   return _eina_strbuf_resize(buf, buf->len);
-}
-
-/**
- * @brief Retrieve a pointer to the contents of a string buffer
- *
- * @param buf The string buffer.
- * @return The current string in the string buffer.
- *
- * This function returns the string contained in @p buf. The returned
- * value must not be modified and will no longer be valid if @p buf is
- * modified. In other words, any eina_strbuf_append() or similar will
- * make that pointer invalid.
- *
- * @see eina_strbuf_string_steal()
- */
-EAPI const char *
-eina_strbuf_string_get(const Eina_Strbuf *buf)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf, NULL);
-
-   return buf->buf;
-}
-
-/**
- * @brief Steal the contents of a string buffer.
- *
- * @param buf The string buffer to steal.
- * @return The current string in the string buffer.
- *
- * This function returns the string contained in @p buf. @p buf is
- * then initialized and does not own the returned string anymore. The
- * caller must release the memory of the returned string by calling
- * free(). 
- *
- * @see eina_strbuf_string_get()
- */
-EAPI char *
-eina_strbuf_string_steal(Eina_Strbuf *buf)
-{
-   char *ret;
-
-   EINA_MAGIC_CHECK_STRBUF(buf, NULL);
-
-   ret = buf->buf;
-   // TODO: Check return value and do something clever
-   _eina_strbuf_init(buf);
-   return ret;
-}
-
-/**
- * @brief Free the contents of a string buffer but not the buffer.
- *
- * @param buf The string buffer to free the string of.
-  *
- * This function frees the string contained in @p buf without freeing
- * @p buf.
- */
-EAPI void
-eina_strbuf_string_free(Eina_Strbuf *buf)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf);
-
-   free(buf->buf);
-   _eina_strbuf_init(buf);
-}
-
-/**
- * @brief Retrieve the length of the string buffer content.
- *
- * @param buf The string buffer.
- * @return The current length of the string, in bytes.
- *
- * This function returns the length of @p buf.
- */
-EAPI size_t
-eina_strbuf_length_get(const Eina_Strbuf *buf)
-{
-   EINA_MAGIC_CHECK_STRBUF(buf, 0);
-
-   return buf->len;
-}
-
-/**
- * @ brief Replace the n-th string with an other string.
- *
- * @param buf The string buffer to work with.
- * @param str The string to replace.
- * @param with The replaceing string.
- * @param n The number of the fitting string.
- * @return #EINA_TRUE on success, #EINA_FALSE on failure.
- *
- * This function replaces the n-th occurence of @p str in @p buf with
- * @p with. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
- */
-EAPI Eina_Bool
-eina_strbuf_replace(Eina_Strbuf *buf, const char *str, const char *with, unsigned int n)
-{
-   size_t len1, len2;
-   char *spos;
-   size_t pos;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(with, EINA_FALSE);
-   EINA_MAGIC_CHECK_STRBUF(buf, 0);
-
-   if (n == 0)
-     return EINA_FALSE;
-
-   spos = buf->buf;
-   while (n--)
-     {
-       spos = strstr(spos, str);
-       if (!spos || *spos == '\0')
-         return EINA_FALSE;
-       if (n) spos++;
-     }
-
-   pos = spos - buf->buf;
-   len1 = strlen(str);
-   len2 = strlen(with);
-   if (len1 != len2)
-     {
-       /* resize the buffer if necessary */
-       if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, buf->len - len1 + len2)))
-         return EINA_FALSE;
-       /* move the existing text */
-       memmove(buf->buf + pos + len2, buf->buf + pos + len1,
-             buf->len - pos - len1);
-     }
-   /* and now insert the given string */
-   memcpy(buf->buf + pos, with, len2);
-   buf->len += len2 - len1;
-   buf->buf[buf->len] = 0;
-
-   return EINA_TRUE;
-}
-
-/**
- * @brief Replace all strings with an other string.
-
- * @param buf the string buffer to work with.
- * @param str The string to replace.
- * @param with The replaceing string.
- * @return How often the string was replaced.
- *
- * This function replaces all the occurences of @p str in @ buf with
- * the string @p with. This function returns the number of times @p str
- * has been replaced. On failure, it returns 0.
- */
-EAPI int
-eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *with)
-{
-   size_t len1, len2, len;
-   char *tmp_buf = NULL;
-   char *spos;
-   size_t pos, start;
-   size_t pos_tmp, start_tmp;
-   int n = 0;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(str, 0);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(with, 0);
-   EINA_MAGIC_CHECK_STRBUF(buf, 0);
-
-   spos = strstr(buf->buf, str);
-   if (!spos || *spos == '\0')
-     return 0;
-
-   len1 = strlen(str);
-   len2 = strlen(with);
-
-   /* if the size of the two string is equal, it is fairly easy to replace them
-    * we don't need to resize the buffer or doing other calculations */
-   if (len1 == len2)
-     {
-       while (spos)
-         {
-            memcpy(spos, with, len2);
-            spos = strstr(spos + len2, str);
-            n++;
-         }
-       return n;
-     }
-
-   pos = pos_tmp = spos - buf->buf;
-   tmp_buf = buf->buf;
-   buf->buf = malloc(buf->size);
-   if (EINA_UNLIKELY(!buf->buf))
-     {
-       buf->buf = tmp_buf;
-       return 0;
-     }
-   start = start_tmp = 0;
-   len = buf->len;
-
-   while (spos)
-     {
-       n++;
-       len = (len + len2) - len1;
-       /* resize the buffer if necessary */
-       if (EINA_UNLIKELY(!_eina_strbuf_grow(buf, len)))
-         {
-            /* we have to stop replacing here, because we haven't enough
-             * memory to go on */
-            len = (len + len1) - len2;
-            break;
-         }
-
-       /* copy the untouched text */
-       memcpy(buf->buf + start, tmp_buf + start_tmp, pos - start);
-       /* copy the new string */
-       memcpy(buf->buf + pos, with, len2);
-
-       /* calculate the next positions */
-       start_tmp = pos_tmp + len1;
-       start = pos + len2;
-       spos = strstr(tmp_buf + start_tmp, str);
-       /* this calculations don't make sense if spos == NULL, but the
-        * calculated values won't be used, because the loop will stop
-        * then */
-       pos_tmp = spos - tmp_buf;
-       pos = start + pos_tmp - start_tmp;
-     }
-   /* and now copy the rest of the text */
-   memcpy(buf->buf + start, tmp_buf + start_tmp, len - start);
-   buf->len = len;
-   buf->buf[buf->len] = 0;
-
-   free(tmp_buf);
-
-   return n;
-}
-
-/**
- * @}
- */
+}
\ No newline at end of file
diff --git a/src/lib/eina_strbuf_common.c b/src/lib/eina_strbuf_common.c
new file mode 100644 (file)
index 0000000..4ce3348
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+# include <Evil.h>
+#endif
+
+#include "eina_private.h"
+#include "eina_str.h"
+#include "eina_magic.h"
+#include "eina_error.h"
+#include "eina_safety_checks.h"
+#include "eina_strbuf.h"
+#include "eina_strbuf_common.h"
+
+/*============================================================================*
+ *                                  Local                                     *
+ *============================================================================*/
+
+/**
+ * @cond LOCAL
+ */
+
+#define EINA_STRBUF_INIT_SIZE 32
+#define EINA_STRBUF_INIT_STEP 32
+#define EINA_STRBUF_MAX_STEP 4096
+
+/**
+ * @internal
+ *
+ * init the buffer
+ * @param buf the buffer to init
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ */
+static Eina_Bool
+_eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf)
+{
+   buf->len = 0;
+   buf->size = EINA_STRBUF_INIT_SIZE;
+   buf->step = EINA_STRBUF_INIT_STEP;
+
+   eina_error_set(0);
+   buf->buf = calloc(csize, buf->size);
+   if (EINA_UNLIKELY(!buf->buf))
+     {
+       eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+       return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
+/**
+ * @internal
+ *
+ * resize the buffer
+ * @param buf the buffer to resize
+ * @param size the minimum size of the buffer
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ */
+static inline Eina_Bool
+_eina_strbuf_common_resize(size_t csize, Eina_Strbuf *buf, size_t size)
+{
+   size_t new_size, new_step, delta;
+   void *buffer;
+
+   size += 1; // Add extra space for '\0'
+
+   if (size == buf->size)
+     /* nothing to do */
+     return EINA_TRUE;
+   else if (size > buf->size)
+     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
+     {
+       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 */
+   buffer = realloc(buf->buf, new_size * csize);
+   if (EINA_UNLIKELY(!buffer))
+     {
+       eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+       return EINA_FALSE;
+     }
+
+   buf->buf = buffer;
+   buf->size = new_size;
+   buf->step = new_step;
+   eina_error_set(0);
+   return EINA_TRUE;
+}
+
+/**
+ * @internal
+ *
+ * If required, enlarge the buffer to fit the new size.
+ *
+ * @param buf the buffer to resize
+ * @param size the minimum size of the buffer
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ */
+Eina_Bool
+_eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size)
+{
+   if ((size + 1) < buf->size)
+     return EINA_TRUE;
+   return _eina_strbuf_common_resize(csize, buf, size);
+}
+
+/**
+ * @internal
+ *
+ * insert string of known length at random within existing strbuf limits.
+ *
+ * @param buf the buffer to resize, must be valid.
+ * @param str the string to copy, must be valid (!NULL and smaller than @a len)
+ * @param len the amount of bytes in @a str to copy, must be valid.
+ * @param pos the position inside buffer to insert, must be valid (smaller
+ *        than eina_strbuf_common_length_get())
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ */
+static inline Eina_Bool
+_eina_strbuf_common_insert_length(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t pos)
+{
+   if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
+     return EINA_FALSE;
+
+   /* move the existing text */
+   memmove(buf->buf + ((len + pos) * csize), buf->buf + (pos * csize), (buf->len - pos) * csize);
+
+   /* and now insert the given string */
+   memcpy(buf->buf + (pos * csize), str, len * csize);
+
+   buf->len += len;
+   memset(buf->buf + (buf->len * csize), 0, csize);
+   return EINA_TRUE;
+}
+
+/**
+ * @endcond
+ */
+
+/*============================================================================*
+ *                                 Global                                     *
+ *============================================================================*/
+
+/**
+ * @cond LOCAL
+ */
+
+/**
+ * @internal
+ * @brief Initialize the strbuf module.
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function sets up the strbuf module of Eina. It is called by
+ * eina_init().
+ *
+ * @see eina_init()
+ */
+Eina_Bool
+eina_strbuf_common_init(void)
+{
+   return EINA_TRUE;
+}
+
+/**
+ * @internal
+ * @brief Shut down the strbuf module.
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function shuts down the strbuf module set up by
+ * eina_strbuf_common_init(). It is called by eina_shutdown().
+ *
+ * @see eina_shutdown()
+ */
+Eina_Bool
+eina_strbuf_common_shutdown(void)
+{
+   return EINA_TRUE;
+}
+
+/*============================================================================*
+ *                                   API                                      *
+ *============================================================================*/
+
+/**
+ * @brief Create a new string buffer.
+ *
+ * @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()
+ */
+Eina_Strbuf *
+eina_strbuf_common_new(size_t csize)
+{
+   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_init(csize, buf)))
+     {
+       eina_strbuf_common_free(buf);
+       return NULL;
+     }
+
+   return buf;
+}
+
+/**
+ * @brief Free a string buffer.
+ *
+ * @param buf The string buffer to free.
+ *
+ * This function frees the memory of @p buf. @p buf must have been
+ * created by eina_strbuf_common_new().
+ */
+void
+eina_strbuf_common_free(Eina_Strbuf *buf)
+{
+   free(buf->buf);
+   free(buf);
+}
+
+/**
+ * @brief Reset a string buffer.
+ *
+ * @param buf The string buffer to reset.
+ *
+ * This function reset @p buf: the buffer len is set to 0, and the
+ * string is set to '\\0'. No memory is free'd.
+ */
+void
+eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf)
+{
+   buf->len = 0;
+   buf->step = EINA_STRBUF_INIT_STEP;
+
+   memset(buf->buf, 0, csize);
+}
+
+/**
+ * @brief Append a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends @p str to @p buf. It computes the length of
+ * @p str, so is slightly slower than eina_strbuf_common_append_length(). If
+ * the length is known beforehand, consider using that variant. If
+ * @p buf can't append it, #EINA_FALSE is returned, otherwise
+ * #EINA_TRUE is returned.
+ *
+ * @see eina_strbuf_common_append()
+ * @see eina_strbuf_common_append_length()
+ */
+Eina_Bool
+eina_strbuf_common_append(size_t csize, Eina_Strbuf *buf, const void *str, size_t len)
+{
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+
+   if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
+     return EINA_FALSE;
+   memcpy(buf->buf + (buf->len * csize), str, (len + 1) * csize);
+   buf->len += len;
+   return EINA_TRUE;
+}
+
+/**
+ * @brief Append a string to a buffer, reallocating as necessary,
+ * limited by the given length.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @param maxlen The maximum number of characters to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends at most @p maxlen characters of @p str to
+ * @p buf. It can't appends more than the length of @p str. It
+ * computes the length of @p str, so is slightly slower than
+ * eina_strbuf_common_append_length(). If the length is known beforehand,
+ * consider using that variant (@p maxlen should then be checked so
+ * that it is greater than the size of @p str). If @p str can not be
+ * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_strbuf_common_append()
+ * @see eina_strbuf_common_append_length()
+ */
+Eina_Bool
+eina_strbuf_common_append_n(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t maxlen)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+
+   if (len > maxlen) len = maxlen;
+   if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len)))
+     return EINA_FALSE;
+
+   memcpy(buf->buf + (buf->len * csize), str, len * csize);
+   buf->len += len;
+   memset(buf->buf + (buf->len * csize), 0, csize);
+   return EINA_TRUE;
+}
+
+/**
+ * @brief Append a string of exact length to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param str The string to append.
+ * @param length The exact length to use.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function appends @p str to @p buf. @p str must be of size at
+ * most @p length. It is slightly faster than eina_strbuf_common_append() as
+ * it does not compute the size of @p str. It is useful when dealing
+ * with strings of known size, such as eina_strngshare. If @p buf
+ * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_stringshare_length()
+ * @see eina_strbuf_common_append()
+ * @see eina_strbuf_common_append_n()
+ */
+Eina_Bool
+eina_strbuf_common_append_length(size_t csize, Eina_Strbuf *buf, const void *str, size_t length)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+
+   if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + length)))
+     return EINA_FALSE;
+
+   memcpy(buf->buf + (buf->len * csize), str, length * csize);
+   buf->len += length;
+   memset(buf->buf + (buf->len * csize), 0, csize);
+   return EINA_TRUE;
+}
+
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert.
+ * @param str The string to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str to @p buf at position @p pos. It
+ * computes the length of @p str, so is slightly slower than
+ * eina_strbuf_common_insert_length(). If  the length is known beforehand,
+ * consider using that variant. If @p buf can't insert it, #EINA_FALSE
+ * is returned, otherwise #EINA_TRUE is returned.
+ */
+Eina_Bool
+eina_strbuf_common_insert(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t pos)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+
+   if (pos >= buf->len)
+     return eina_strbuf_common_append(csize, buf, str, len);
+
+   return _eina_strbuf_common_insert_length(csize, buf, str, len, pos);
+}
+
+/**
+ * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param maxlen The maximum number of chars to insert.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str ot @p buf at position @p pos, with at
+ * most @p maxlen bytes. The number of inserted characters can not be
+ * greater than the length of @p str. It computes the length of
+ * @p str, so is slightly slower than eina_strbuf_common_insert_length(). If the
+ * length is known beforehand, consider using that variant (@p maxlen
+ * should then be checked so that it is greater than the size of
+ * @p str). If @p str can not be inserted, #EINA_FALSE is returned,
+ * otherwise, #EINA_TRUE is returned.
+ */
+Eina_Bool
+eina_strbuf_common_insert_n(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t maxlen, size_t pos)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+
+   if (pos >= buf->len)
+     return eina_strbuf_common_append_n(csize, buf, str, len, maxlen);
+
+   if (len > maxlen) len = maxlen;
+   return _eina_strbuf_common_insert_length(csize, buf, str, len, pos);
+}
+
+/**
+ * @brief Insert a string of exact length to a buffer, reallocating as necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param str The string to insert.
+ * @param length The exact length to use.
+ * @param pos The position to insert the string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p str to @p buf. @p str must be of size at
+ * most @p length. It is slightly faster than eina_strbuf_common_insert() as
+ * it does not compute the size of @p str. It is useful when dealing
+ * with strings of known size, such as eina_strngshare. If @p buf
+ * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ *
+ * @see eina_stringshare_length()
+ * @see eina_strbuf_common_insert()
+ * @see eina_strbuf_common_insert_n()
+ */
+Eina_Bool
+eina_strbuf_common_insert_length(size_t csize, Eina_Strbuf *buf, const void *str, size_t length, size_t pos)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+
+   if (pos >= buf->len)
+     return eina_strbuf_common_append_length(csize, buf, str, length);
+
+   return _eina_strbuf_common_insert_length(csize, buf, str, length, pos);
+}
+
+/**
+ * @brief Append a character to a string buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to append to.
+ * @param c The char to append.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p c to @p buf. If it can not insert it,
+ * #EINA_FALSE is returned, otherwise #EINA_TRUE is returned.
+ */
+Eina_Bool
+eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c)
+{
+
+   if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + 1)))
+     return EINA_FALSE;
+   memcpy(buf->buf + ((buf->len)++ * csize), c, csize);
+   memset(buf->buf + (buf->len * csize), 0, csize);
+   return EINA_TRUE;
+}
+
+/**
+ * @brief Insert a character to a string buffer, reallocating as
+ * necessary.
+ *
+ * @param buf The string buffer to insert to.
+ * @param c The char to insert.
+ * @param pos The position to insert the char.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function inserts @p c to @p buf at position @p pos. If @p buf
+ * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is
+ * returned.
+ */
+Eina_Bool
+eina_strbuf_common_insert_char(size_t csize, Eina_Strbuf *buf, const void *c, size_t pos)
+{
+
+   if (pos >= buf->len)
+     return eina_strbuf_common_append_char(csize, buf, c);
+
+   return _eina_strbuf_common_insert_length(csize, buf, c, 1, pos);
+}
+
+/**
+ * @brief Remove a slice of the given string buffer.
+ *
+ * @param buf The string buffer to remove a slice.
+ * @param start The initial (inclusive) slice position to start
+ *        removing, in bytes.
+ * @param end The final (non-inclusive) slice position to finish
+ *        removing, in bytes.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function removes a slice of @p buf, starting at @p start
+ * (inclusive) and ending at @p end (non-inclusive). Both values are
+ * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
+ */
+Eina_Bool
+eina_strbuf_common_remove(size_t csize, Eina_Strbuf *buf, size_t start, size_t end)
+{
+   size_t remove_len, tail_len;
+
+   if (end >= buf->len)
+     end = buf->len;
+
+   if (end <= start)
+     return EINA_TRUE;
+
+   remove_len = end - start;
+   if (remove_len == buf->len)
+     {
+       free(buf->buf);
+       return _eina_strbuf_common_init(csize, buf);
+     }
+
+   tail_len = buf->len - end + 1; /* includes '\0' */
+   memmove(buf->buf + (start * csize), buf->buf + (end * csize), tail_len * csize);
+   buf->len -= remove_len;
+   return _eina_strbuf_common_resize(csize, buf, buf->len);
+}
+
+/**
+ * @brief Retrieve a pointer to the contents of a string buffer
+ *
+ * @param buf The string buffer.
+ * @return The current string in the string buffer.
+ *
+ * This function returns the string contained in @p buf. The returned
+ * value must not be modified and will no longer be valid if @p buf is
+ * modified. In other words, any eina_strbuf_common_append() or similar will
+ * make that pointer invalid.
+ *
+ * @see eina_strbuf_common_string_steal()
+ */
+const void *
+eina_strbuf_common_string_get(const Eina_Strbuf *buf)
+{
+   return buf->buf;
+}
+
+/**
+ * @brief Steal the contents of a string buffer.
+ *
+ * @param buf The string buffer to steal.
+ * @return The current string in the string buffer.
+ *
+ * This function returns the string contained in @p buf. @p buf is
+ * then initialized and does not own the returned string anymore. The
+ * caller must release the memory of the returned string by calling
+ * free(). 
+ *
+ * @see eina_strbuf_common_string_get()
+ */
+void *
+eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf)
+{
+   void *ret;
+
+   ret = buf->buf;
+   // TODO: Check return value and do something clever
+   _eina_strbuf_common_init(csize, buf);
+   return ret;
+}
+
+/**
+ * @brief Free the contents of a string buffer but not the buffer.
+ *
+ * @param buf The string buffer to free the string of.
+  *
+ * This function frees the string contained in @p buf without freeing
+ * @p buf.
+ */
+void
+eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf)
+{
+   free(buf->buf);
+   _eina_strbuf_common_init(csize, buf);
+}
+
+/**
+ * @brief Retrieve the length of the string buffer content.
+ *
+ * @param buf The string buffer.
+ * @return The current length of the string, in bytes.
+ *
+ * This function returns the length of @p buf.
+ */
+size_t
+eina_strbuf_common_length_get(const Eina_Strbuf *buf)
+{
+   return buf->len;
+}
+/**
+ * @endcond
+ */
+
+/**
+ * @addtogroup Eina_Data_Types_Group Data Types
+ *
+ * @{
+ */
+/**
+ * @addtogroup Eina_String_Buffer_Group String Buffer
+ *
+ * @brief These functions provide string buffers management.
+ *
+ * The String Buffer data type is designed to be a mutable string,
+ * allowing to append, prepend or insert a string to a buffer. 
+ *
+ * @{
+ */
+/*FIXME: Implementing them here is a hack! */
+#define _STRBUF_CSIZE 1
+#define _STRBUF_MAGIC             EINA_MAGIC_STRBUF
+static const char _STRBUF_MAGIC_STR[] = "Eina Strbuf";
+
+/**
+ * @ brief Replace the n-th string with an other string.
+ *
+ * @param buf The string buffer to work with.
+ * @param str The string to replace.
+ * @param with The replaceing string.
+ * @param n The number of the fitting string.
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function replaces the n-th occurence of @p str in @p buf with
+ * @p with. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise.
+ */
+EAPI Eina_Bool
+eina_strbuf_replace(Eina_Strbuf *buf, const char *str, const char *with, unsigned int n)
+{
+   size_t len1, len2;
+   char *spos;
+   size_t pos;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(with, EINA_FALSE);
+   EINA_MAGIC_CHECK_STRBUF(buf, 0);
+
+   if (n == 0)
+     return EINA_FALSE;
+
+   spos = buf->buf;
+   while (n--)
+     {
+       spos = strstr(spos, str);
+       if (!spos || *spos == '\0')
+         return EINA_FALSE;
+       if (n) spos++;
+     }
+
+   pos = spos - (const char *) buf->buf;
+   len1 = strlen(str);
+   len2 = strlen(with);
+   if (len1 != len2)
+     {
+       /* resize the buffer if necessary */
+       if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, buf->len - len1 + len2)))
+         return EINA_FALSE;
+       /* move the existing text */
+       memmove(buf->buf + pos + len2, buf->buf + pos + len1,
+             buf->len - pos - len1);
+     }
+   /* and now insert the given string */
+   memcpy(buf->buf + pos, with, len2);
+   buf->len += len2 - len1;
+   memset((char *) buf->buf + buf->len, 0, 1);
+
+   return EINA_TRUE;
+}
+
+/**
+ * @brief Replace all strings with an other string.
+
+ * @param buf the string buffer to work with.
+ * @param str The string to replace.
+ * @param with The replaceing string.
+ * @return How often the string was replaced.
+ *
+ * This function replaces all the occurences of @p str in @ buf with
+ * the string @p with. This function returns the number of times @p str
+ * has been replaced. On failure, it returns 0.
+ */
+EAPI int
+eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *with)
+{
+   size_t len1, len2, len;
+   char *tmp_buf = NULL;
+   char *spos;
+   size_t pos, start;
+   size_t pos_tmp, start_tmp;
+   int n = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(str, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(with, 0);
+   EINA_MAGIC_CHECK_STRBUF(buf, 0);
+
+   spos = strstr(buf->buf, str);
+   if (!spos || *spos == '\0')
+     return 0;
+
+   len1 = strlen(str);
+   len2 = strlen(with);
+
+   /* if the size of the two string is equal, it is fairly easy to replace them
+    * we don't need to resize the buffer or doing other calculations */
+   if (len1 == len2)
+     {
+       while (spos)
+         {
+            memcpy(spos, with, len2);
+            spos = strstr(spos + len2, str);
+            n++;
+         }
+       return n;
+     }
+
+   pos = pos_tmp = spos - (const char *) buf->buf;
+   tmp_buf = buf->buf;
+   buf->buf = malloc(buf->size);
+   if (EINA_UNLIKELY(!buf->buf))
+     {
+       buf->buf = tmp_buf;
+       return 0;
+     }
+   start = start_tmp = 0;
+   len = buf->len;
+
+   while (spos)
+     {
+       n++;
+       len = (len + len2) - len1;
+       /* resize the buffer if necessary */
+       if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, len)))
+         {
+            /* we have to stop replacing here, because we haven't enough
+             * memory to go on */
+            len = (len + len1) - len2;
+            break;
+         }
+
+       /* copy the untouched text */
+       memcpy(buf->buf + start, tmp_buf + start_tmp, pos - start);
+       /* copy the new string */
+       memcpy(buf->buf + pos, with, len2);
+
+       /* calculate the next positions */
+       start_tmp = pos_tmp + len1;
+       start = pos + len2;
+       spos = strstr(tmp_buf + start_tmp, str);
+       /* this calculations don't make sense if spos == NULL, but the
+        * calculated values won't be used, because the loop will stop
+        * then */
+       pos_tmp = spos - tmp_buf;
+       pos = start + pos_tmp - start_tmp;
+     }
+   /* and now copy the rest of the text */
+   memcpy(buf->buf + start, tmp_buf + start_tmp, len - start);
+   buf->len = len;
+   memset((char *) buf->buf + buf->len, 0, 1);
+
+   free(tmp_buf);
+
+   return n;
+}
+
+/**
+ * @}
+ */
+/**
+ * @}
+ */
diff --git a/src/lib/eina_strbuf_common.h b/src/lib/eina_strbuf_common.h
new file mode 100644 (file)
index 0000000..0b205ae
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef EINA_STRBUF_COMMON_H
+#define EINA_STRBUF_COMMON_H
+#include <Eina.h>
+
+#include "eina_private.h"
+#include "eina_magic.h"
+
+struct _Eina_Strbuf
+{
+   void *buf;
+   size_t len;
+   size_t size;
+   size_t step;
+
+   EINA_MAGIC
+};
+
+#define EINA_MAGIC_CHECK_STRBUF(d, ...)                                \
+   do {                                                                \
+       if (!EINA_MAGIC_CHECK((d), _STRBUF_MAGIC))              \
+         {                                                     \
+            EINA_MAGIC_FAIL((d), _STRBUF_MAGIC);               \
+            return __VA_ARGS__;                                \
+         }                                                     \
+   } while (0)
+
+Eina_Bool
+eina_strbuf_common_init(void);
+
+Eina_Bool
+eina_strbuf_common_shutdown(void);
+Eina_Strbuf *
+eina_strbuf_common_new(size_t csize);
+void
+eina_strbuf_common_free(Eina_Strbuf *buf);
+void
+eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf);
+Eina_Bool
+eina_strbuf_common_append(size_t csize, Eina_Strbuf *buf, const void *str, size_t len);
+Eina_Bool
+eina_strbuf_common_append_escaped(size_t csize, Eina_Strbuf *buf, const void *str);
+Eina_Bool
+eina_strbuf_common_append_n(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t maxlen);
+Eina_Bool
+eina_strbuf_common_append_length(size_t csize, Eina_Strbuf *buf, const void *str, size_t length);
+Eina_Bool
+eina_strbuf_common_insert(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t pos);
+Eina_Bool
+eina_strbuf_common_insert_escaped(size_t csize, Eina_Strbuf *buf, const void *str,
+                           size_t len, size_t pos);
+Eina_Bool
+eina_strbuf_common_insert_n(size_t csize, Eina_Strbuf *buf, const void *str, size_t len, size_t maxlen, size_t pos);
+Eina_Bool
+eina_strbuf_common_insert_length(size_t csize, Eina_Strbuf *buf, const void *str, size_t length, size_t pos);
+Eina_Bool
+eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c);
+Eina_Bool
+eina_strbuf_common_insert_char(size_t csize, Eina_Strbuf *buf, const void *c, size_t pos);
+Eina_Bool
+eina_strbuf_common_remove(size_t csize, Eina_Strbuf *buf, size_t start, size_t end);
+const void *
+eina_strbuf_common_string_get(const Eina_Strbuf *buf);
+void *
+eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf);
+void
+eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf);
+size_t
+eina_strbuf_common_length_get(const Eina_Strbuf *buf);
+
+Eina_Bool
+_eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size);
+/**
+ * @}
+ */
+
+#endif
diff --git a/src/lib/eina_strbuf_template_c.i b/src/lib/eina_strbuf_template_c.i
new file mode 100644 (file)
index 0000000..b5d6e95
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+/* This file should be included from files implementing strbuf. The including file
+ * should define the following macros:
+ * _STRBUF_DATA_TYPE
+ * _STRBUF_CSIZE
+ * _STRBUF_STRUCT_NAME
+ * _STRBUF_STRLEN_FUNC(x)
+ * _STRBUF_STRESCAPE_FUNC(x)
+ * _STRBUF_STRSTR_FUNC(x, y)
+ * _STRBUF_MAGIC
+ * _STRBUF_MAGIC_STR
+ * See how it's done in eina_ustrbuf.c and eina_strbuf.c. This just makes things
+ * a lot easier since those are essentially the same just with different sizes.
+ */
+
+#ifndef EINA_STRBUF_TEMPLATE_C_I
+#define EINA_STRBUF_TEMPLATE_C_I
+
+
+#include <Eina.h>
+#include "eina_strbuf_common.h"
+#include "eina_unicode.h"
+
+/**
+ * @internal
+ * @brief Initialize the strbuf module.
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function sets up the strbuf module of Eina. It is called by
+ * eina_init().
+ *
+ * @see eina_init()
+ */
+Eina_Bool
+_FUNC_EXPAND(init)(void)
+{
+   eina_magic_string_static_set(_STRBUF_MAGIC, _STRBUF_MAGIC_STR);
+   return eina_strbuf_common_init();
+}
+
+/**
+ * @internal
+ * @brief Shut down the strbuf module.
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function shuts down the strbuf module set up by
+ * eina_ustrbuf_init(). It is called by eina_shutdown().
+ *
+ * @see eina_shutdown()
+ */
+Eina_Bool
+_FUNC_EXPAND(shutdown)(void)
+{
+   return eina_strbuf_common_shutdown();
+}
+
+/**
+ * @endcond
+ */
+
+/*============================================================================*
+ *                                   API                                      *
+ *============================================================================*/
+
+EAPI _STRBUF_STRUCT_NAME *
+_FUNC_EXPAND(new)(void)
+{
+   _STRBUF_STRUCT_NAME *buf = eina_strbuf_common_new(_STRBUF_CSIZE);
+   EINA_MAGIC_SET(buf, _STRBUF_MAGIC);
+   return buf;
+}
+
+EAPI void
+_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf);
+   EINA_MAGIC_SET(buf, EINA_MAGIC_NONE);
+   eina_strbuf_common_free(buf);
+}
+
+EAPI void
+_FUNC_EXPAND(reset)(_STRBUF_STRUCT_NAME *buf)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf);
+   eina_strbuf_common_reset(_STRBUF_CSIZE, buf);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(append)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_append(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str));
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(append_escaped)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str)
+{
+   _STRBUF_DATA_TYPE *esc;
+   Eina_Bool ret;
+
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   esc = _STRBUF_STRESCAPE_FUNC(str);
+   if (!esc) {
+      return _FUNC_EXPAND(append)(buf, str);
+   }
+   ret = _FUNC_EXPAND(append)(buf, esc);
+   if (esc)
+      free(esc);
+
+   return ret;
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(append_n)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t maxlen)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_append_n(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), maxlen);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(append_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_append_length(_STRBUF_CSIZE, buf, (const void *) str, length);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(insert)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t pos)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_insert(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), pos);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(insert_escaped)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t pos)
+{
+   _STRBUF_DATA_TYPE *esc;
+   Eina_Bool ret;
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+
+   esc = _STRBUF_STRESCAPE_FUNC(str);
+   if (!esc) {
+      return _FUNC_EXPAND(insert)(buf, str, pos);
+   }
+   ret = _FUNC_EXPAND(insert)(buf, esc, pos);
+   if (esc)
+      free(esc);
+
+   return ret;
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(insert_n)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t maxlen, size_t pos)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_insert_n(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), maxlen, pos);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(insert_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length, size_t pos)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_insert_length(_STRBUF_CSIZE, buf, (const void *) str, length, pos);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(append_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_append_char(_STRBUF_CSIZE, buf, (const void *) &c);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(insert_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c, size_t pos)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_insert_char(_STRBUF_CSIZE, buf, (const void *) &c, pos);
+}
+
+EAPI Eina_Bool
+_FUNC_EXPAND(remove)(_STRBUF_STRUCT_NAME *buf, size_t start, size_t end)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE);
+   return eina_strbuf_common_remove(_STRBUF_CSIZE, buf, start, end);
+}
+
+EAPI const _STRBUF_DATA_TYPE *
+_FUNC_EXPAND(string_get)(const _STRBUF_STRUCT_NAME *buf)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, NULL);
+   return (const _STRBUF_DATA_TYPE *) eina_strbuf_common_string_get(buf);
+}
+
+EAPI _STRBUF_DATA_TYPE *
+_FUNC_EXPAND(string_steal)(_STRBUF_STRUCT_NAME *buf)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, NULL);
+   return (_STRBUF_DATA_TYPE *) eina_strbuf_common_string_steal(_STRBUF_CSIZE, buf);
+}
+
+
+EAPI void
+_FUNC_EXPAND(string_free)(_STRBUF_STRUCT_NAME *buf)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf);
+   eina_strbuf_common_string_free(_STRBUF_CSIZE, buf);
+}
+
+EAPI size_t
+_FUNC_EXPAND(length_get)(const _STRBUF_STRUCT_NAME *buf)
+{
+   EINA_MAGIC_CHECK_STRBUF(buf, 0);
+   return eina_strbuf_common_length_get(buf);
+}
+
+#else
+#error Something went terribly wrong, shouldnt be included twice!
+
+#endif
diff --git a/src/lib/eina_ustrbuf.c b/src/lib/eina_ustrbuf.c
new file mode 100644 (file)
index 0000000..55de552
--- /dev/null
@@ -0,0 +1,15 @@
+#include "eina_strbuf_common.h"
+#include "eina_unicode.h"
+#include "eina_ustrbuf.h"
+
+#define _STRBUF_DATA_TYPE         Eina_Unicode
+#define _STRBUF_CSIZE             sizeof(_STRBUF_DATA_TYPE)
+#define _STRBUF_STRUCT_NAME       Eina_UStrbuf
+#define _STRBUF_STRLEN_FUNC(x)    eina_unicode_strlen(x)
+#define _STRBUF_STRESCAPE_FUNC(x) eina_unicode_escape(x)
+#define _STRBUF_MAGIC             EINA_MAGIC_USTRBUF
+static const char _STRBUF_MAGIC_STR[] = "Eina UStrbuf";
+
+#define _FUNC_EXPAND(y) eina_ustrbuf_##y
+
+#include "eina_strbuf_template_c.i"
\ No newline at end of file