]> jfr.im git - irc/weechat/weechat.git/commitdiff
api: add function string_concat (issue #2005)
authorSébastien Helleu <redacted>
Sat, 2 Sep 2023 09:53:56 +0000 (11:53 +0200)
committerSébastien Helleu <redacted>
Tue, 17 Oct 2023 16:14:53 +0000 (18:14 +0200)
12 files changed:
ChangeLog.adoc
doc/en/weechat_plugin_api.en.adoc
doc/fr/weechat_plugin_api.fr.adoc
doc/it/weechat_plugin_api.it.adoc
doc/ja/weechat_plugin_api.ja.adoc
doc/sr/weechat_plugin_api.sr.adoc
src/core/wee-string.c
src/core/wee-string.h
src/core/weechat.c
src/plugins/plugin.c
src/plugins/weechat-plugin.h
tests/unit/core/test-core-string.cpp

index 646872337bc22413ddf70e7f24ec162b5ca03aac..7f32686976e48f2bcbc21ce004a046dcb41e4e4b 100644 (file)
@@ -37,7 +37,7 @@ New features::
   * core: add options weechat.buffer.* to save buffer properties set by user, add option `setauto` in command `/buffer` (issue #352)
   * core: add parameters and key bindings to move to edges of current area with commands `/cursor go` and `/cursor move` (issue #1282)
   * core: add variables "_chat_focused_line_bol" and "_chat_focused_line_eol" in focus data (issue #1955)
-  * api: add function hook_url, add option `url` in command `/debug` (issue #1723)
+  * api: add function string_concat (issue #2005)
   * api: add support of path to variable and hashtable comparison in function hdata_compare (issue #1066)
   * api: add infos "nick_color_ignore_case" and "nick_color_name_ignore_case" (issue #194)
   * api: add info "buffer" (issue #1962)
index 2be3f7237ec42b10c1b4fbbf7314f291f069a47e..bbd2ec40a10e724148482f85707f11bb7b5e12e8 100644 (file)
@@ -3476,6 +3476,46 @@ weechat_string_dyn_free (string, 1);
 [NOTE]
 This function is not available in scripting API.
 
+==== string_concat
+
+_WeeChat ≥ 4.2.0._
+
+Concatenate multiple strings using a separator.
+
+Prototype:
+
+[source,c]
+----
+const char *weechat_string_concat (const char *separator, ...);
+----
+
+Arguments:
+
+* _separator_: the separator string which is inserted between concatenated
+  strings (can be NULL or empty string)
+
+[NOTE]
+Last argument *MUST* always be NULL. +
+A macro called `WEECHAT_STR_CONCAT` can be used, where the final NULL value is
+not needed (usage of this macro is recommended).
+
+Return value:
+
+* concatenated string
+
+C example:
+
+[source,c]
+----
+const char *result = weechat_string_concat (" / ", "abc", "def", "ghi", NULL);  /* result == "abc / def / ghi" */
+
+/* with macro */
+const char *result = WEECHAT_STR_CONCAT(" / ", "abc", "def", "ghi");  /* result == "abc / def / ghi" */
+----
+
+[NOTE]
+This function is not available in scripting API.
+
 [[utf-8]]
 === UTF-8
 
index 42b1ff747efcf0464ce9f8d1d83fcd52679b6c11..c9432f18a141bf0a3b082ce8ccbefba6147cade9 100644 (file)
@@ -3533,6 +3533,46 @@ weechat_string_dyn_free (string, 1);
 [NOTE]
 Cette fonction n'est pas disponible dans l'API script.
 
+==== string_concat
+
+_WeeChat ≥ 4.2.0._
+
+Concaténer plusieurs chaînes de caractères en utilisant un séparateur.
+
+Prototype :
+
+[source,c]
+----
+const char *weechat_string_concat (const char *separator, ...);
+----
+
+Paramètres :
+
+* _separator_ : la chaîne de séparation qui est insérée entre les chaînes
+  concaténées (peut être NULL ou une chaîne vide)
+
+[NOTE]
+Le dernier paramètre *DOIT* toujours être NULL. +
+Une macro nommée `WEECHAT_STR_CONCAT` peut être utilisée, où la valeur finale
+NULL n'est pas nécessaire (l'utilisation de cette macro est recommandée).
+
+Valeur de retour :
+
+* chaîne concaténée
+
+Exemple en C :
+
+[source,c]
+----
+const char *result = weechat_string_concat (" / ", "abc", "def", "ghi", NULL);  /* result == "abc / def / ghi" */
+
+/* with macro */
+const char *result = WEECHAT_STR_CONCAT(" / ", "abc", "def", "ghi");  /* result == "abc / def / ghi" */
+----
+
+[NOTE]
+Cette fonction n'est pas disponible dans l'API script.
+
 [[utf-8]]
 === UTF-8
 
index 6efd0c6e9d31bd5f13d9335ba388cf25047bb654..c8330e7fc634d6f52b34b1f6c98a2b62760a9be4 100644 (file)
@@ -3641,6 +3641,51 @@ weechat_string_dyn_free (string, 1);
 [NOTE]
 Questa funzione non è disponibile nelle API per lo scripting.
 
+==== string_concat
+
+_WeeChat ≥ 4.2.0._
+
+// TRANSLATION MISSING
+Concatenate multiple strings using a separator.
+
+Prototipo:
+
+[source,c]
+----
+const char *weechat_string_concat (const char *separator, ...);
+----
+
+Argomenti:
+
+// TRANSLATION MISSING
+* _separator_: the separator string which is inserted between concatenated
+  strings (can be NULL or empty string)
+
+// TRANSLATION MISSING
+[NOTE]
+Last argument *MUST* always be NULL. +
+A macro called `WEECHAT_STR_CONCAT` can be used, where the final NULL value is
+not needed (usage of this macro is recommended).
+
+Valore restituito:
+
+// TRANSLATION MISSING
+* concatenated string
+
+Esempio in C:
+
+// TRANSLATION MISSING
+[source,c]
+----
+const char *result = weechat_string_concat (" / ", "abc", "def", "ghi", NULL);  /* result == "abc / def / ghi" */
+
+/* with macro */
+const char *result = WEECHAT_STR_CONCAT(" / ", "abc", "def", "ghi");  /* result == "abc / def / ghi" */
+----
+
+[NOTE]
+Questa funzione non è disponibile nelle API per lo scripting.
+
 [[utf-8]]
 === UTF-8
 
index f651d640da22298527bd357efcacaaf7835e645f..406a5560a574d51ac1ca9d838257a08440431cfe 100644 (file)
@@ -3579,6 +3579,51 @@ weechat_string_dyn_free (string, 1);
 [NOTE]
 スクリプト API ではこの関数を利用できません。
 
+==== string_concat
+
+_WeeChat ≥ 4.2.0._
+
+// TRANSLATION MISSING
+Concatenate multiple strings using a separator.
+
+プロトタイプ:
+
+[source,c]
+----
+const char *weechat_string_concat (const char *separator, ...);
+----
+
+引数:
+
+// TRANSLATION MISSING
+* _separator_: the separator string which is inserted between concatenated
+  strings (can be NULL or empty string)
+
+// TRANSLATION MISSING
+[NOTE]
+Last argument *MUST* always be NULL. +
+A macro called `WEECHAT_STR_CONCAT` can be used, where the final NULL value is
+not needed (usage of this macro is recommended).
+
+戻り値:
+
+// TRANSLATION MISSING
+* concatenated string
+
+C 言語での使用例:
+
+// TRANSLATION MISSING
+[source,c]
+----
+const char *result = weechat_string_concat (" / ", "abc", "def", "ghi", NULL);  /* result == "abc / def / ghi" */
+
+/* with macro */
+const char *result = WEECHAT_STR_CONCAT(" / ", "abc", "def", "ghi");  /* result == "abc / def / ghi" */
+----
+
+[NOTE]
+スクリプト API ではこの関数を利用できません。
+
 [[utf-8]]
 === UTF-8
 
index dc9e538b87be08fea22bc33fc17e1c3085ed7670..393ffe57026030130aafe35300a919bb81080382 100644 (file)
@@ -3357,6 +3357,51 @@ weechat_string_dyn_free (string, 1);
 [NOTE]
 Ова функција није доступна у API скриптовања.
 
+==== string_concat
+
+_WeeChat ≥ 4.2.0._
+
+// TRANSLATION MISSING
+Concatenate multiple strings using a separator.
+
+Прототип:
+
+[source,c]
+----
+const char *weechat_string_concat (const char *separator, ...);
+----
+
+Аргументи:
+
+// TRANSLATION MISSING
+* _separator_: the separator string which is inserted between concatenated
+  strings (can be NULL or empty string)
+
+// TRANSLATION MISSING
+[NOTE]
+Last argument *MUST* always be NULL. +
+A macro called `WEECHAT_STR_CONCAT` can be used, where the final NULL value is
+not needed (usage of this macro is recommended).
+
+Повратна вредност:
+
+// TRANSLATION MISSING
+* concatenated string
+
+C пример:
+
+// TRANSLATION MISSING
+[source,c]
+----
+const char *result = weechat_string_concat (" / ", "abc", "def", "ghi", NULL);  /* result == "abc / def / ghi" */
+
+/* with macro */
+const char *result = WEECHAT_STR_CONCAT(" / ", "abc", "def", "ghi");  /* result == "abc / def / ghi" */
+----
+
+[NOTE]
+Ова функција није доступна у API скриптовања.
+
 [[utf-8]]
 === UTF-8
 
index ab0bee82ec13338fd41a3444a4991fe98fee8176..7374f9fe9f46bb807044cfbd540b08022446e69f 100644 (file)
@@ -66,6 +66,8 @@
 #define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))
 
 struct t_hashtable *string_hashtable_shared = NULL;
+int string_concat_index = 0;
+char **string_concat_buffer[STRING_NUM_CONCAT_BUFFERS];
 
 
 /*
@@ -4693,6 +4695,68 @@ string_dyn_free (char **string, int free_string)
     return ptr_string;
 }
 
+/*
+ * Concatenates strings, using a separator (which can be NULL or empty string
+ * to not use any separator).
+ *
+ * Last argument must be NULL to terminate the variable list of arguments.
+ */
+
+const char *
+string_concat (const char *separator, ...)
+{
+    va_list args;
+    const char *str;
+    int index;
+
+    string_concat_index = (string_concat_index + 1) % 8;
+
+    if (string_concat_buffer[string_concat_index])
+    {
+        string_dyn_copy (string_concat_buffer[string_concat_index], NULL);
+    }
+    else
+    {
+        string_concat_buffer[string_concat_index] = string_dyn_alloc (128);
+        if (!string_concat_buffer[string_concat_index])
+            return NULL;
+    }
+
+    index = 0;
+    va_start (args, separator);
+    while (1)
+    {
+        str = va_arg (args, const char *);
+        if (!str)
+            break;
+        if ((index > 0) && separator && separator[0])
+        {
+            string_dyn_concat (string_concat_buffer[string_concat_index],
+                               separator, -1);
+        }
+        string_dyn_concat (string_concat_buffer[string_concat_index], str, -1);
+        index++;
+    }
+    va_end (args);
+
+    return (const char *)(*string_concat_buffer[string_concat_index]);
+}
+
+/*
+ * Initializes string.
+ */
+
+void
+string_init ()
+{
+    int i;
+
+    for (i = 0; i < STRING_NUM_CONCAT_BUFFERS; i++)
+    {
+        string_concat_buffer[i] = NULL;
+    }
+}
+
 /*
  * Frees all allocated data.
  */
@@ -4700,9 +4764,19 @@ string_dyn_free (char **string, int free_string)
 void
 string_end ()
 {
+    int i;
+
     if (string_hashtable_shared)
     {
         hashtable_free (string_hashtable_shared);
         string_hashtable_shared = NULL;
     }
+    for (i = 0; i < STRING_NUM_CONCAT_BUFFERS; i++)
+    {
+        if (string_concat_buffer[i])
+        {
+            string_dyn_free (string_concat_buffer[i], 1);
+            string_concat_buffer[i] = NULL;
+        }
+    }
 }
index 522d3e440f93f3f9acb698d7edcdcae2961158bb..716335e9a62ed2d6fe43d85b3b4df9d743fb3e25 100644 (file)
@@ -24,6 +24,9 @@
 #include <stdint.h>
 #include <regex.h>
 
+#define STRING_NUM_CONCAT_BUFFERS 8
+#define STR_CONCAT(separator, argz...) string_concat (separator, ##argz, NULL)
+
 typedef uint32_t string_shared_count_t;
 
 typedef uint32_t string_dyn_size_t;
@@ -157,6 +160,8 @@ 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, int bytes);
 extern char *string_dyn_free (char **string, int free_string);
+extern const char *string_concat (const char *separator, ...);
+extern void string_init ();
 extern void string_end ();
 
 #endif /* WEECHAT_STRING_H */
index 9c11dd16b614eaffd770a607799be28e661de368..4eb80c8b24a6d9844e16028fcbba9545fa2b2fc5 100644 (file)
@@ -642,6 +642,7 @@ weechat_init (int argc, char *argv[], void (*gui_init_cb)())
            ^ getpid ());
 
     weeurl_init ();                     /* initialize URL                   */
+    string_init ();                     /* initialize string                */
     signal_init ();                     /* initialize signals               */
     hdata_init ();                      /* initialize hdata                 */
     hook_init ();                       /* initialize hooks                 */
index 91836e3e28f82413006eec9864553cea0ac320d7..e496d547aa363aead4112e250f61de577c9a37ae 100644 (file)
@@ -658,6 +658,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
         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->string_concat = &string_concat;
 
         new_plugin->utf8_has_8bits = &utf8_has_8bits;
         new_plugin->utf8_is_valid = &utf8_is_valid;
index ae27b9bddd7e16abd9e9ea18812d329c31c77a98..e976760bf274eca35f407197c383e8f9d31ddf17 100644 (file)
@@ -68,7 +68,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 "20230908-01"
+#define WEECHAT_PLUGIN_API_VERSION "20231017-01"
 
 /* macros for defining plugin infos */
 #define WEECHAT_PLUGIN_NAME(__name)                                     \
@@ -216,6 +216,10 @@ struct timeval;
         }                                                               \
     }
 
+/* macro to concatenate strings */
+#define WEECHAT_STR_CONCAT(separator, argz...)                          \
+    weechat_string_concat (separator, ##argz, NULL)
+
 /*
  * macro to return error in case of missing arguments in callback of
  * hook_command
@@ -367,6 +371,7 @@ struct t_weechat_plugin
     int (*string_dyn_copy) (char **string, const char *new_string);
     int (*string_dyn_concat) (char **string, const char *add, int bytes);
     char *(*string_dyn_free) (char **string, int free_string);
+    const char *(*string_concat) (const char *separator, ...);
 
     /* UTF-8 strings */
     int (*utf8_has_8bits) (const char *string);
@@ -1379,6 +1384,8 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
     (weechat_plugin->string_dyn_concat)(__string, __add, __bytes)
 #define weechat_string_dyn_free(__string, __free_string)                \
     (weechat_plugin->string_dyn_free)(__string, __free_string)
+#define weechat_string_concat(__separator, __argz...)                   \
+    (weechat_plugin->string_concat)(__separator, ##__argz)
 
 /* UTF-8 strings */
 #define weechat_utf8_has_8bits(__string)                                \
index 11a7421615ef90bb162d102d609e60c8cc0f02b4..ea4722e38e1f1289e1e1175809a1a485a73f14c8 100644 (file)
@@ -2969,3 +2969,32 @@ TEST(CoreString, Dyn)
     string_dyn_free (NULL, 0);
     string_dyn_free (str, 0);
 }
+
+/*
+ * Tests functions:
+ *   string_concat
+ */
+
+TEST(CoreString, Concat)
+{
+    STRCMP_EQUAL("", string_concat (NULL, NULL));
+    STRCMP_EQUAL("", string_concat (NULL, "", NULL));
+    STRCMP_EQUAL("", string_concat ("", "", NULL));
+    STRCMP_EQUAL("", string_concat (",", "", NULL));
+
+    STRCMP_EQUAL("abc", string_concat (NULL, "abc", NULL));
+    STRCMP_EQUAL("abcdef", string_concat (NULL, "abc", "def", NULL));
+    STRCMP_EQUAL("abcdefghi", string_concat (NULL, "abc", "def", "ghi", NULL));
+
+    STRCMP_EQUAL("abc", string_concat ("", "abc", NULL));
+    STRCMP_EQUAL("abcdef", string_concat ("", "abc", "def", NULL));
+    STRCMP_EQUAL("abcdefghi", string_concat ("", "abc", "def", "ghi", NULL));
+
+    STRCMP_EQUAL("abc", string_concat (",", "abc", NULL));
+    STRCMP_EQUAL("abc,def", string_concat (",", "abc", "def", NULL));
+    STRCMP_EQUAL("abc,def,ghi", string_concat (",", "abc", "def", "ghi", NULL));
+
+    STRCMP_EQUAL("abc", string_concat (" / ", "abc", NULL));
+    STRCMP_EQUAL("abc / def", string_concat (" / ", "abc", "def", NULL));
+    STRCMP_EQUAL("abc / def / ghi", string_concat (" / ", "abc", "def", "ghi", NULL));
+}