diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index 53b2eaa9f..1435ec9d3 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -2169,6 +2169,166 @@ options = { str5 = weechat.string_eval_expression("password=abc password=def", {}, {}, options) # "password=*** password=***" ---- +==== string_dyn_alloc + +_WeeChat ≥ 1.8._ + +Allocate a dynamic string, with a variable length. + +Internally, a structure is allocated with the string pointer, the allocated size +and current length of string. + +Only the pointer to string pointer (_**string_) is used in all the +_pass:[string_dyn_*]_ functions. + +Prototype: + +[source,C] +---- +char **weechat_dyn_alloc (int size_alloc); +---- + +Arguments: + +* _size_alloc_: the initial allocated size (must be greater than zero) + +Return value: + +* pointer to the dynamic string + +C example: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +---- + +[NOTE] +This function is not available in scripting API. + +==== string_dyn_copy + +_WeeChat ≥ 1.8._ + +Copy a string in a dynamic string. + +The pointer _*string_ can change if the string is reallocated (if there is +not enough space to copy the string). + +Prototype: + +[source,C] +---- +int weechat_dyn_copy (char **string, const char *new_string); +---- + +Arguments: + +* _string_: pointer to dynamic string +* _new_string_: the string to copy + +Return value: + +* 1 if OK, 0 if error + +C example: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + /* OK */ +} +else +{ + /* error */ +} +---- + +[NOTE] +This function is not available in scripting API. + +==== string_dyn_concat + +_WeeChat ≥ 1.8._ + +Concatenate a string to a dynamic string. + +The pointer _*string_ can change if the string is reallocated (if there is +not enough space to concatenate the string). + +Prototype: + +[source,C] +---- +int weechat_dyn_concat (char **string, const char *add); +---- + +Arguments: + +* _string_: pointer to dynamic string +* _add_: the string to add + +Return value: + +* 1 if OK, 0 if error + +C example: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + if (weechat_dyn_concat (string, "abc")) + { + /* ... */ + } +} +---- + +[NOTE] +This function is not available in scripting API. + +==== string_dyn_free + +_WeeChat ≥ 1.8._ + +Free a dynamic string. + +Prototype: + +[source,C] +---- +void weechat_dyn_free (char **string, int free_string); +---- + +Arguments: + +* _string_: pointer to dynamic string +* _free_string_: free the string itself; if 0, the content of _*string_ remains + valid after the call to this function + +C example: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_concat (string, "test")) +{ + /* OK */ +} +else +{ + /* error */ +} +/* ... */ +weechat_dyn_free (string, 1); +---- + +[NOTE] +This function is not available in scripting API. + [[utf-8]] === UTF-8 diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index 01debc442..b6f3163aa 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -2211,6 +2211,166 @@ options = { str5 = weechat.string_eval_expression("password=abc password=def", {}, {}, options) # "password=*** password=***" ---- +==== string_dyn_alloc + +_WeeChat ≥ 1.8._ + +Allouer une chaîne dynamique, avec une longueur variable. + +De manière interne, une structure est allouée avec le pointeur vers la chaîne, +la taille allouée et la longueur courante de la chaîne. + +Seul le pointeur de pointeur de chaîne (_**string_) est utilisé dans toutes les fonctions +_pass:[string_dyn_*]_. + +Prototype : + +[source,C] +---- +char **weechat_dyn_alloc (int size_alloc); +---- + +Paramètres : + +* _size_alloc_ : la taille initialement allouée (doit être supérieure à zéro) + +Valeur de retour : + +* pointeur vers la chaîne dynamique + +Exemple en C : + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + +==== string_dyn_copy + +_WeeChat ≥ 1.8._ + +Copier une chaîne dans une chaîne dynamique. + +Le pointeur _*string_ peut changer si la chaîne est réallouée (s'il n'y a pas +assez de place pour copier la chaîne). + +Prototype : + +[source,C] +---- +int weechat_dyn_copy (char **string, const char *new_string); +---- + +Paramètres : + +* _string_ : pointeur vers la chaîne dynamique +* _new_string_ : la chaîne à copier + +Valeur de retour : + +* 1 si OK, 0 si erreur + +Exemple en C : + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + /* OK */ +} +else +{ + /* erreur */ +} +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + +==== string_dyn_concat + +_WeeChat ≥ 1.8._ + +Concaténer une chaîne dans une chaîne dynamique. + +Le pointeur _*string_ peut changer si la chaîne est réallouée (s'il n'y a pas +assez de place pour concaténer la chaîne). + +Prototype : + +[source,C] +---- +int weechat_dyn_concat (char **string, const char *add); +---- + +Paramètres : + +* _string_ : pointeur vers la chaîne dynamique +* _add_ : la chaîne à ajouter + +Valeur de retour : + +* 1 si OK, 0 si erreur + +Exemple en C : + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + if (weechat_dyn_concat (string, "abc")) + { + /* ... */ + } +} +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + +==== string_dyn_free + +_WeeChat ≥ 1.8._ + +Libérer une chaîne dynamique. + +Prototype : + +[source,C] +---- +void weechat_dyn_free (char **string, int free_string); +---- + +Paramètres : + +* _string_ : pointeur vers la chaîne dynamique +* _free_string_ : libérer la chaîne elle-même ; si 0, le contenu de _*string_ + reste valide après l'appel à cette fonction + +Exemple en C : + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_concat (string, "test")) +{ + /* OK */ +} +else +{ + /* erreur */ +} +/* ... */ +weechat_dyn_free (string, 1); +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + [[utf-8]] === UTF-8 diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index 899166da1..1727ba6f5 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -2248,6 +2248,180 @@ options = { str5 = weechat.string_eval_expression("password=abc password=def", {}, {}, options) # "password=*** password=***" ---- +==== string_dyn_alloc + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Allocate a dynamic string, with a variable length. + +Internally, a structure is allocated with the string pointer, the allocated size +and current length of string. + +// TRANSLATION MISSING +Only the pointer to string pointer (_**string_) is used in all the +_pass:[string_dyn_*]_ functions. + +Prototipo: + +[source,C] +---- +char **weechat_dyn_alloc (int size_alloc); +---- + +Argomenti: + +// TRANSLATION MISSING +* _size_alloc_: the initial allocated size (must be greater than zero) + +Valore restituito: + +// TRANSLATION MISSING +* pointer to the dynamic string + +Esempio in C: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + +==== string_dyn_copy + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Copy a string in a dynamic string. + +// TRANSLATION MISSING +The pointer _*string_ can change if the string is reallocated (if there is +not enough space to copy the string). + +Prototipo: + +[source,C] +---- +int weechat_dyn_copy (char **string, const char *new_string); +---- + +Argomenti: + +// TRANSLATION MISSING +* _string_: pointer to dynamic string +* _new_string_: the string to copy + +Valore restituito: + +// TRANSLATION MISSING +* 1 if OK, 0 if error + +Esempio in C: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + /* OK */ +} +else +{ + /* error */ +} +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + +==== string_dyn_concat + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Concatenate a string to a dynamic string. + +// TRANSLATION MISSING +The pointer _*string_ can change if the string is reallocated (if there is +not enough space to concatenate the string). + +Prototipo: + +[source,C] +---- +int weechat_dyn_concat (char **string, const char *add); +---- + +Argomenti: + +// TRANSLATION MISSING +* _string_: pointer to dynamic string +* _add_: the string to add + +Valore restituito: + +// TRANSLATION MISSING +* 1 if OK, 0 if error + +Esempio in C: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + if (weechat_dyn_concat (string, "abc")) + { + /* ... */ + } +} +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + +==== string_dyn_free + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Free a dynamic string. + +Prototipo: + +[source,C] +---- +void weechat_dyn_free (char **string, int free_string); +---- + +Argomenti: + +// TRANSLATION MISSING +* _string_: pointer to dynamic string +* _free_string_: free the string itself; if 0, the content of _*string_ remains + valid after the call to this function + +Esempio in C: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_concat (string, "test")) +{ + /* OK */ +} +else +{ + /* error */ +} +/* ... */ +weechat_dyn_free (string, 1); +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + [[utf-8]] === UTF-8 diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index 44aa330ff..452352b58 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -2175,6 +2175,180 @@ options = { str5 = weechat.string_eval_expression("password=abc password=def", {}, {}, options) # "password=*** password=***" ---- +==== string_dyn_alloc + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Allocate a dynamic string, with a variable length. + +Internally, a structure is allocated with the string pointer, the allocated size +and current length of string. + +// TRANSLATION MISSING +Only the pointer to string pointer (_**string_) is used in all the +_pass:[string_dyn_*]_ functions. + +プロトタイプ: + +[source,C] +---- +char **weechat_dyn_alloc (int size_alloc); +---- + +引数: + +// TRANSLATION MISSING +* _size_alloc_: the initial allocated size (must be greater than zero) + +戻り値: + +// TRANSLATION MISSING +* pointer to the dynamic string + +C 言語での使用例: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + +==== string_dyn_copy + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Copy a string in a dynamic string. + +// TRANSLATION MISSING +The pointer _*string_ can change if the string is reallocated (if there is +not enough space to copy the string). + +プロトタイプ: + +[source,C] +---- +int weechat_dyn_copy (char **string, const char *new_string); +---- + +引数: + +// TRANSLATION MISSING +* _string_: pointer to dynamic string +* _new_string_: the string to copy + +戻り値: + +// TRANSLATION MISSING +* 1 if OK, 0 if error + +C 言語での使用例: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + /* OK */ +} +else +{ + /* error */ +} +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + +==== string_dyn_concat + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Concatenate a string to a dynamic string. + +// TRANSLATION MISSING +The pointer _*string_ can change if the string is reallocated (if there is +not enough space to concatenate the string). + +プロトタイプ: + +[source,C] +---- +int weechat_dyn_concat (char **string, const char *add); +---- + +引数: + +// TRANSLATION MISSING +* _string_: pointer to dynamic string +* _add_: the string to add + +戻り値: + +// TRANSLATION MISSING +* 1 if OK, 0 if error + +C 言語での使用例: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_copy (string, "test")) +{ + if (weechat_dyn_concat (string, "abc")) + { + /* ... */ + } +} +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + +==== string_dyn_free + +_WeeChat ≥ 1.8._ + +// TRANSLATION MISSING +Free a dynamic string. + +プロトタイプ: + +[source,C] +---- +void weechat_dyn_free (char **string, int free_string); +---- + +引数: + +// TRANSLATION MISSING +* _string_: pointer to dynamic string +* _free_string_: free the string itself; if 0, the content of _*string_ remains + valid after the call to this function + +C 言語での使用例: + +[source,C] +---- +char **string = weechat_dyn_alloc (256); +if (weechat_dyn_concat (string, "test")) +{ + /* OK */ +} +else +{ + /* error */ +} +/* ... */ +weechat_dyn_free (string, 1); +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + [[utf-8]] === UTF-8 diff --git a/src/core/wee-string.c b/src/core/wee-string.c index 3003bcf8b..2c4711b09 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -60,8 +60,6 @@ ((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : \ c - '0') -typedef uint32_t string_shared_count_t; - struct t_hashtable *string_hashtable_shared = NULL; @@ -3195,6 +3193,190 @@ string_shared_free (const char *string) hashtable_remove (string_hashtable_shared, ptr_count); } +/* + * Allocates a dynamic string (with a variable length). + * + * The parameter size_alloc is the initial allocated size, which must be + * greater than zero. + * + * Returns the pointer to the allocated string, which is initialized as empty + * string. + * + * The string returned can be used with following restrictions: + * - changes are allowed in the string, between the first char and the final + * '\0', which must not be removed nor moved, + * - no other '\0' must be added in the string, + * - content can be added in the string with function string_dyn_concat(), + * - string can be freed with function string_dyn_free() (do NEVER call + * directly free() on the string). + * + * Note: result must be freed after use with function string_dyn_free(). + */ + +char ** +string_dyn_alloc (int size_alloc) +{ + struct t_string_dyn *string_dyn; + + if (size_alloc <= 0) + return NULL; + + string_dyn = malloc (sizeof (*string_dyn)); + if (!string_dyn) + return NULL; + + string_dyn->string = malloc (size_alloc); + if (!string_dyn->string) + { + free (string_dyn); + return NULL; + } + + string_dyn->string[0] = '\0'; + string_dyn->size_alloc = size_alloc; + string_dyn->size = 1; + + return &(string_dyn->string); +} + +/* + * Copies "new_string" into a dynamic string and replaces its current content + * (adjusts its size accordingly). + * + * The string pointer (*string) is updated with the new allocated string + * if the string had to be extended, or the same pointer if there was enough + * size to copy the new string. + * + * Returns: + * 1: OK + * 0: error + */ + +int +string_dyn_copy (char **string, const char *new_string) +{ + struct t_string_dyn *ptr_string_dyn; + char *string_realloc; + string_dyn_size_t length_new, new_size_alloc; + + if (!string || !*string) + return 0; + + ptr_string_dyn = (struct t_string_dyn *)string; + + length_new = (new_string) ? strlen (new_string) : 0; + + if (length_new + 1 > ptr_string_dyn->size_alloc) + { + /* compute new size_alloc for the string + add */ + new_size_alloc = (ptr_string_dyn->size_alloc < 2) ? + 2 : ptr_string_dyn->size_alloc + (ptr_string_dyn->size_alloc / 2); + if (new_size_alloc < length_new + 1) + new_size_alloc = length_new + 1; + string_realloc = realloc (ptr_string_dyn->string, new_size_alloc); + if (!string_realloc) + return 0; + ptr_string_dyn->string = string_realloc; + *string = string_realloc; + ptr_string_dyn->size_alloc = new_size_alloc; + } + + /* copy "new_string" in "string" */ + if (new_string) + memmove (ptr_string_dyn->string, new_string, length_new + 1); + else + ptr_string_dyn->string[0] = '\0'; + ptr_string_dyn->size = length_new + 1; + + return 1; +} + +/* + * Concatenates a string to a dynamic string and adjusts its size accordingly. + * + * The string pointer (*string) is updated with the new allocated string + * if the string had to be extended, or the same pointer if there was enough + * size to concatenate the new string. + * + * Returns: + * 1: OK + * 0: error + */ + +int +string_dyn_concat (char **string, const char *add) +{ + struct t_string_dyn *ptr_string_dyn; + char *string_realloc; + string_dyn_size_t length_add, new_size_alloc, new_size; + + if (!string || !*string) + return 0; + + if (!add || !add[0]) + return 1; + + ptr_string_dyn = (struct t_string_dyn *)string; + + length_add = strlen (add); + new_size = ptr_string_dyn->size + length_add; + + if (new_size > ptr_string_dyn->size_alloc) + { + /* compute new size_alloc for the string + add */ + new_size_alloc = (ptr_string_dyn->size_alloc < 2) ? + 2 : ptr_string_dyn->size_alloc + (ptr_string_dyn->size_alloc / 2); + if (new_size_alloc < new_size) + new_size_alloc = new_size; + string_realloc = realloc (ptr_string_dyn->string, new_size_alloc); + if (!string_realloc) + { + free (ptr_string_dyn->string); + free (ptr_string_dyn); + *string = NULL; + return 0; + } + ptr_string_dyn->string = string_realloc; + *string = string_realloc; + ptr_string_dyn->size_alloc = new_size_alloc; + } + + /* concatenate "add" after "string" */ + memmove (ptr_string_dyn->string + ptr_string_dyn->size - 1, + add, + length_add + 1); + ptr_string_dyn->size = new_size; + + return 1; +} + +/* + * Frees a dynamic string. + * + * The argument "string" is a pointer on a string returned by function + * string_dyn_alloc or a string pointer modified by string_dyn_concat. + * + * If free_string == 1, the string itself is freed in the structure. + * Otherwise the pointer (*string) remains valid after this call, and + * the caller must manually free the string with a call to free(). + */ + +void +string_dyn_free (char **string, int free_string) +{ + struct t_string_dyn *ptr_string_dyn; + + if (!string || !*string) + return; + + ptr_string_dyn = (struct t_string_dyn *)string; + + if (free_string) + free (ptr_string_dyn->string); + + free (ptr_string_dyn); +} + /* * Frees all allocated data. */ diff --git a/src/core/wee-string.h b/src/core/wee-string.h index fc7ba8dd2..bfed81411 100644 --- a/src/core/wee-string.h +++ b/src/core/wee-string.h @@ -20,8 +20,19 @@ #ifndef WEECHAT_STRING_H #define WEECHAT_STRING_H 1 +#include #include +typedef uint32_t string_shared_count_t; + +typedef uint32_t string_dyn_size_t; +struct t_string_dyn +{ + char *string; /* the string */ + string_dyn_size_t size_alloc; /* allocated size */ + string_dyn_size_t size; /* size of string (including '\0') */ +}; + struct t_hashtable; extern char *string_strndup (const char *string, int length); @@ -104,6 +115,10 @@ extern char *string_replace_with_callback (const char *string, int *errors); extern const char *string_shared_get (const char *string); extern void string_shared_free (const char *string); +extern char **string_dyn_alloc (int size_alloc); +extern int string_dyn_copy (char **string, const char *new_string); +extern int string_dyn_concat (char **string, const char *add); +extern void string_dyn_free (char **string, int free_string); extern void string_end (); #endif /* WEECHAT_STRING_H */ diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 8d99534ba..c89ca6614 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -638,6 +638,10 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->string_is_command_char = &string_is_command_char; new_plugin->string_input_for_buffer = &string_input_for_buffer; new_plugin->string_eval_expression = &eval_expression; + new_plugin->string_dyn_alloc = &string_dyn_alloc; + new_plugin->string_dyn_copy = &string_dyn_copy; + new_plugin->string_dyn_concat = &string_dyn_concat; + new_plugin->string_dyn_free = &string_dyn_free; new_plugin->utf8_has_8bits = &utf8_has_8bits; new_plugin->utf8_is_valid = &utf8_is_valid; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 70f1c9b58..3d7fc2e1b 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -58,7 +58,7 @@ struct timeval; * please change the date with current one; for a second change at same * date, increment the 01, otherwise please keep 01. */ -#define WEECHAT_PLUGIN_API_VERSION "20160618-01" +#define WEECHAT_PLUGIN_API_VERSION "20170303-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -324,6 +324,10 @@ struct t_weechat_plugin struct t_hashtable *pointers, struct t_hashtable *extra_vars, struct t_hashtable *options); + char **(*string_dyn_alloc) (int size_alloc); + int (*string_dyn_copy) (char **string, const char *new_string); + int (*string_dyn_concat) (char **string, const char *add); + void (*string_dyn_free) (char **string, int free_string); /* UTF-8 strings */ int (*utf8_has_8bits) (const char *string); @@ -1185,6 +1189,14 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); __extra_vars, __options) \ (weechat_plugin->string_eval_expression)(__expr, __pointers, \ __extra_vars, __options) +#define weechat_string_dyn_alloc(__size_alloc) \ + (weechat_plugin->string_dyn_alloc)(__size_alloc) +#define weechat_string_dyn_copy(__string, __new_string) \ + (weechat_plugin->string_dyn_copy)(__string, __new_string) +#define weechat_string_dyn_concat(__string, __add) \ + (weechat_plugin->string_dyn_concat)(__string, __add) +#define weechat_string_dyn_free(__string, __free_string) \ + (weechat_plugin->string_dyn_free)(__string, __free_string) /* UTF-8 strings */ #define weechat_utf8_has_8bits(__string) \ diff --git a/tests/unit/core/test-string.cpp b/tests/unit/core/test-string.cpp index 748aff2fe..4a9cab548 100644 --- a/tests/unit/core/test-string.cpp +++ b/tests/unit/core/test-string.cpp @@ -1345,3 +1345,118 @@ TEST(String, Shared) string_shared_free (str3); LONGS_EQUAL(count + 0, string_hashtable_shared->items_count); } + +/* + * Tests functions: + * string_dyn_alloc + * string_dyn_copy + * string_dyn_concat + * string_dyn_free + */ + +TEST(String, Dyn) +{ + char **str, *str_ptr; + struct t_string_dyn *ptr_string_dyn; + + POINTERS_EQUAL(NULL, string_dyn_alloc (-1)); + POINTERS_EQUAL(NULL, string_dyn_alloc (0)); + + str = string_dyn_alloc (1); + CHECK(str); + CHECK(*str); + STRCMP_EQUAL("", *str); + + /* check internal structure content */ + ptr_string_dyn = (struct t_string_dyn *)str; + LONGS_EQUAL(1, ptr_string_dyn->size_alloc); + LONGS_EQUAL(1, ptr_string_dyn->size); + STRCMP_EQUAL("", ptr_string_dyn->string); + + /* check copy with NULL */ + LONGS_EQUAL(1, string_dyn_copy (str, NULL)); + LONGS_EQUAL(1, ptr_string_dyn->size_alloc); + LONGS_EQUAL(1, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("", ptr_string_dyn->string); + STRCMP_EQUAL("", *str); + + /* check copy with an empty string */ + LONGS_EQUAL(1, string_dyn_copy (str, "")); + LONGS_EQUAL(1, ptr_string_dyn->size_alloc); + LONGS_EQUAL(1, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("", ptr_string_dyn->string); + STRCMP_EQUAL("", *str); + + /* check copy with some strings */ + LONGS_EQUAL(1, string_dyn_copy (str, "a")); + LONGS_EQUAL(2, ptr_string_dyn->size_alloc); + LONGS_EQUAL(2, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("a", ptr_string_dyn->string); + STRCMP_EQUAL("a", *str); + + LONGS_EQUAL(1, string_dyn_copy (str, "abcd")); + LONGS_EQUAL(5, ptr_string_dyn->size_alloc); + LONGS_EQUAL(5, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("abcd", ptr_string_dyn->string); + STRCMP_EQUAL("abcd", *str); + + string_dyn_free (str, 1); + + str = string_dyn_alloc (1); + + /* check concat with NULL */ + LONGS_EQUAL(1, string_dyn_concat (str, NULL)); + LONGS_EQUAL(1, ptr_string_dyn->size_alloc); + LONGS_EQUAL(1, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("", ptr_string_dyn->string); + STRCMP_EQUAL("", *str); + + /* check concat with an empty string */ + LONGS_EQUAL(1, string_dyn_concat (str, "")); + LONGS_EQUAL(1, ptr_string_dyn->size_alloc); + LONGS_EQUAL(1, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("", ptr_string_dyn->string); + STRCMP_EQUAL("", *str); + + /* check concat with some strings */ + LONGS_EQUAL(1, string_dyn_concat (str, "a")); + LONGS_EQUAL(2, ptr_string_dyn->size_alloc); + LONGS_EQUAL(2, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("a", ptr_string_dyn->string); + STRCMP_EQUAL("a", *str); + + LONGS_EQUAL(1, string_dyn_concat (str, "bcd")); + LONGS_EQUAL(5, ptr_string_dyn->size_alloc); + LONGS_EQUAL(5, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("abcd", ptr_string_dyn->string); + STRCMP_EQUAL("abcd", *str); + + LONGS_EQUAL(1, string_dyn_concat (str, "e")); + LONGS_EQUAL(7, ptr_string_dyn->size_alloc); + LONGS_EQUAL(6, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("abcde", ptr_string_dyn->string); + STRCMP_EQUAL("abcde", *str); + + LONGS_EQUAL(1, string_dyn_concat (str, "fg")); + LONGS_EQUAL(10, ptr_string_dyn->size_alloc); + LONGS_EQUAL(8, ptr_string_dyn->size); + POINTERS_EQUAL(ptr_string_dyn->string, *str); + STRCMP_EQUAL("abcdefg", ptr_string_dyn->string); + STRCMP_EQUAL("abcdefg", *str); + + str_ptr = *str; + string_dyn_free (str, 0); + + STRCMP_EQUAL("abcdefg", str_ptr); + + free (str_ptr); +}