diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index 3c72ae974..a5cdf5e84 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -537,6 +537,55 @@ num_files = 2 str = weechat.ngettext("file", "files", num_files) ---- +==== asprintf + +_WeeChat ≥ 4.3.0._ + +Format a message in a string allocated by the function. + +[NOTE] +This function is defined for systems where the GNU function `asprintf()` +is not available. + +The behavior is almost the same except that `*result` is set to NULL on error. + +Prototype: + +[source,c] +---- +int weechat_asprintf (char **result, const char *fmt, ...); +---- + +Arguments: + +* _result_: pointer to a string pointer +* _fmt_: format string + +Return value: + +* number of bytes written in `*result` (excluding the final null byte), + a negative value in case of error. + +C example: + +[source,c] +---- +char *str; + +if (weechat_asprintf (&str, "%s, %d", "test", 42) >= 0) +{ + /* *str == "test, 42" */ + /* ... */ + free (str); +} +else +{ + /* error: *str == NULL */ +} +---- + +[NOTE] +This function is not available in scripting API. + ==== strndup Return duplicated string, with a max number of bytes. diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index 36937541e..ea4acd4e5 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -547,6 +547,56 @@ num_files = 2 str = weechat.ngettext("file", "files", num_files) ---- +==== asprintf + +_WeeChat ≥ 4.3.0._ + +Formater un message dans une chaîne allouée par la fonction. + +[NOTE] +Cette fonction est définie pour les systèmes où la fonction GNU `asprintf()` +n'est pas disponible. + +Le comportement est quasiment le même à l'exception de `*result` qui est mis à +NULL en cas d'erreur. + +Prototype : + +[source,c] +---- +int weechat_asprintf (char **result, const char *fmt, ...); +---- + +Paramètres : + +* _result_ : pointeur vers un pointeur de chaîne +* _fmt_ : chaîne de formatage + +Valeur de retour : + +* nombre d'octets écrits dans `*result` (en excluant le caractère nul de fin), + une valeur négative en cas d'erreur. + +Exemple en C : + +[source,c] +---- +char *str; + +if (weechat_asprintf (&str, "%s, %d", "test", 42) >= 0) +{ + /* *str == "test, 42" */ + /* ... */ + free (str); +} +else +{ + /* erreur : *str == NULL */ +} +---- + +[NOTE] +Cette fonction n'est pas disponible dans l'API script. + ==== strndup Retourner la chaîne dupliquée, avec un nombre maximum d'octets. diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index 7ee9cc055..a3fcab585 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -568,6 +568,60 @@ num_files = 2 str = weechat.ngettext("file", "files", num_files) ---- +==== asprintf + +_WeeChat ≥ 4.3.0._ + +// TRANSLATION MISSING +Format a message in a string allocated by the function. + +// TRANSLATION MISSING +[NOTE] +This function is defined for systems where the GNU function `asprintf()` +is not available. + +The behavior is almost the same except that `*result` is set to NULL on error. + +Prototipo: + +[source,c] +---- +int weechat_asprintf (char **result, const char *fmt, ...); +---- + +Argomenti: + +// TRANSLATION MISSING +* _result_: pointer to a string pointer +// TRANSLATION MISSING +* _fmt_: format string + +Valore restituito: + +// TRANSLATION MISSING +* number of bytes written in `*result` (excluding the final null byte), + a negative value in case of error. + +Esempio in C: + +[source,c] +---- +char *str; + +if (weechat_asprintf (&str, "%s, %d", "test", 42) >= 0) +{ + /* *str == "test, 42" */ + /* ... */ + free (str); +} +else +{ + /* error: *str == NULL */ +} +---- + +[NOTE] +Questa funzione non è disponibile nelle API per lo scripting. + ==== strndup // TRANSLATION MISSING diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index 9bc90793f..a38b6fd95 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -547,6 +547,60 @@ num_files = 2 str = weechat.ngettext("file", "files", num_files) ---- +==== asprintf + +_WeeChat ≥ 4.3.0._ + +// TRANSLATION MISSING +Format a message in a string allocated by the function. + +// TRANSLATION MISSING +[NOTE] +This function is defined for systems where the GNU function `asprintf()` +is not available. + +The behavior is almost the same except that `*result` is set to NULL on error. + +プロトタイプ: + +[source,c] +---- +int weechat_asprintf (char **result, const char *fmt, ...); +---- + +引数: + +// TRANSLATION MISSING +* _result_: pointer to a string pointer +// TRANSLATION MISSING +* _fmt_: format string + +戻り値: + +// TRANSLATION MISSING +* number of bytes written in `*result` (excluding the final null byte), + a negative value in case of error. + +C 言語での使用例: + +[source,c] +---- +char *str; + +if (weechat_asprintf (&str, "%s, %d", "test", 42) >= 0) +{ + /* *str == "test, 42" */ + /* ... */ + free (str); +} +else +{ + /* error: *str == NULL */ +} +---- + +[NOTE] +スクリプト API ではこの関数を利用できません。 + ==== strndup // TRANSLATION MISSING diff --git a/doc/sr/weechat_plugin_api.sr.adoc b/doc/sr/weechat_plugin_api.sr.adoc index bcde00a9e..456f478a7 100644 --- a/doc/sr/weechat_plugin_api.sr.adoc +++ b/doc/sr/weechat_plugin_api.sr.adoc @@ -512,6 +512,60 @@ num_files = 2 str = weechat.ngettext("file", "files", num_files) ---- +==== asprintf + +_WeeChat ≥ 4.3.0._ + +// TRANSLATION MISSING +Format a message in a string allocated by the function. + +// TRANSLATION MISSING +[NOTE] +This function is defined for systems where the GNU function `asprintf()` +is not available. + +The behavior is almost the same except that `*result` is set to NULL on error. + +Прототип: + +[source,c] +---- +int weechat_asprintf (char **result, const char *fmt, ...); +---- + +Аргументи: + +// TRANSLATION MISSING +* _result_: pointer to a string pointer +// TRANSLATION MISSING +* _fmt_: format string + +Повратна вредност: + +// TRANSLATION MISSING +* number of bytes written in `*result` (excluding the final null byte), + a negative value in case of error. + +C пример: + +[source,c] +---- +char *str; + +if (weechat_asprintf (&str, "%s, %d", "test", 42) >= 0) +{ + /* *str == "test, 42" */ + /* ... */ + free (str); +} +else +{ + /* error: *str == NULL */ +} +---- + +[NOTE] +Ова функција није доступна у API скриптовања. + ==== strndup Враћа дуплирани стринг, са максималним бројем бајтова. diff --git a/src/core/core-string.c b/src/core/core-string.c index 572e6d1cd..4b8f3c957 100644 --- a/src/core/core-string.c +++ b/src/core/core-string.c @@ -70,6 +70,61 @@ int string_concat_index = 0; char **string_concat_buffer[STRING_NUM_CONCAT_BUFFERS]; +/* + * Formats a message in a string allocated by the function. + * + * This function is defined for systems where the GNU function `asprintf()` + * is not available. + * The behavior is almost the same except that `*result` is set to NULL on error. + * + * Returns the number of bytes in the resulting string, negative value in case + * of error. + * + * Value of `*result` is allocated with the result string (NULL if error), + * it must be freed after use. + */ + +int +string_asprintf (char **result, const char *fmt, ...) +{ + va_list argptr; + int num_bytes; + size_t size; + + if (!result) + return -1; + + *result = NULL; + + if (!fmt) + return -1; + + /* determine required size */ + va_start (argptr, fmt); + num_bytes = vsnprintf (NULL, 0, fmt, argptr); + va_end (argptr); + + if (num_bytes < 0) + return num_bytes; + + size = (size_t)num_bytes + 1; + *result = malloc (size); + if (!*result) + return -1; + + va_start (argptr, fmt); + num_bytes = vsnprintf (*result, size, fmt, argptr); + va_end (argptr); + + if (num_bytes < 0) + { + free (*result); + *result = NULL; + } + + return num_bytes; +} + /* * Defines a "strndup" function for systems where this function does not exist * (FreeBSD and maybe others). diff --git a/src/core/core-string.h b/src/core/core-string.h index e79ce6279..6408114f2 100644 --- a/src/core/core-string.h +++ b/src/core/core-string.h @@ -39,6 +39,7 @@ struct t_string_dyn struct t_hashtable; +extern int string_asprintf (char **result, const char *fmt, ...); extern char *string_strndup (const char *string, int bytes); extern char *string_cut (const char *string, int length, int count_suffix, int screen, const char *cut_suffix); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 90227fd25..d885774b8 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -608,6 +608,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->iconv_from_internal = &string_iconv_from_internal; new_plugin->gettext = &plugin_api_gettext; new_plugin->ngettext = &plugin_api_ngettext; + new_plugin->asprintf = &string_asprintf; new_plugin->strndup = &string_strndup; new_plugin->string_cut = &string_cut; new_plugin->string_tolower = &string_tolower; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index c71313545..052ccb90c 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -73,7 +73,7 @@ struct t_weelist_item; * 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 "20240307-01" +#define WEECHAT_PLUGIN_API_VERSION "20240402-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -316,6 +316,7 @@ struct t_weechat_plugin char *(*iconv_from_internal) (const char *charset, const char *string); const char *(*gettext) (const char *string); const char *(*ngettext) (const char *single, const char *plural, int count); + int (*asprintf) (char **result, const char *fmt, ...); char *(*strndup) (const char *string, int bytes); char *(*string_cut) (const char *string, int length, int count_suffix, int screen, const char *cut_suffix); @@ -1290,7 +1291,9 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); #define weechat_gettext(string) (weechat_plugin->gettext)(string) #define weechat_ngettext(single,plural,number) \ (weechat_plugin->ngettext)(single, plural, number) -#define weechat_strndup(__string, __bytes) \ +#define weechat_asprintf(__result, __fmt, __argz...) \ + (weechat_plugin->asprintf)(__result, __fmt, ##__argz) +#define weechat_strndup(__string, __bytes) \ (weechat_plugin->strndup)(__string, __bytes) #define weechat_string_cut(__string, __length, __count_suffix, \ __screen, __cut_suffix) \ diff --git a/tests/unit/core/test-core-string.cpp b/tests/unit/core/test-core-string.cpp index 8881d2df5..2d6552a31 100644 --- a/tests/unit/core/test-core-string.cpp +++ b/tests/unit/core/test-core-string.cpp @@ -123,6 +123,43 @@ TEST_GROUP(CoreString) { }; +/* + * Tests functions: + * string_asprintf + */ + +TEST(CoreString, Asprintf) +{ + char *test; + + test = (char *)0x1; + LONGS_EQUAL(-1, string_asprintf (NULL, NULL)); + POINTERS_EQUAL(0x1, test); + + test = (char *)0x1; + LONGS_EQUAL(-1, string_asprintf (NULL, "")); + POINTERS_EQUAL(0x1, test); + + test = (char *)0x1; + LONGS_EQUAL(-1, string_asprintf (&test, NULL)); + POINTERS_EQUAL(NULL, test); + + test = (char *)0x1; + LONGS_EQUAL(0, string_asprintf (&test, "")); + STRCMP_EQUAL("", test); + free (test); + + test = (char *)0x1; + LONGS_EQUAL(4, string_asprintf (&test, "test")); + STRCMP_EQUAL("test", test); + free (test); + + test = (char *)0x1; + LONGS_EQUAL(16, string_asprintf (&test, "test, %s, %d", "string", 42)); + STRCMP_EQUAL("test, string, 42", test); + free (test); +} + /* * Tests functions: * string_strndup