mirror of
https://github.com/weechat/weechat.git
synced 2026-07-07 18:23:13 +02:00
core: add unique "id" in buffer (issue #2081)
The id is a "long long" variable with the current time (microseconds precision). It is guaranteed to be unique for all buffers, and the same number is never used again, during the lifetime of the process. It persists and is unchanged after `/upgrade`.
This commit is contained in:
@@ -15,6 +15,7 @@ For a list of important changes that require manual actions, please look at rele
|
||||
|
||||
New features::
|
||||
|
||||
* core: add unique identifier "id" in buffer (issue #2081)
|
||||
* core: add option `malloc_trim` in command `/sys`
|
||||
* core: add support of SGR mouse events (issue #2082)
|
||||
* core: reintroduce help on the variables and operators in `/help eval` (issue #2005)
|
||||
|
||||
@@ -14639,6 +14639,7 @@ Arguments:
|
||||
|
||||
* _buffer_: buffer pointer
|
||||
* _property_: property name:
|
||||
** _id_: unique identifier _(WeeChat ≥ 4.3.0)_
|
||||
** _plugin_: name of plugin which created this buffer ("core" for WeeChat main buffer)
|
||||
** _name_: name of buffer
|
||||
** _full_name_: full name of buffer ("plugin.name") _(WeeChat ≥ 0.3.7)_
|
||||
|
||||
@@ -14955,6 +14955,7 @@ Paramètres :
|
||||
|
||||
* _buffer_ : pointeur vers le tampon
|
||||
* _property_ : nom de la propriété :
|
||||
** _id_ : identifiant unique _(WeeChat ≥ 4.3.0)_
|
||||
** _plugin_ : nom de l'extension qui a créé ce tampon ("core" pour le tampon principal WeeChat)
|
||||
** _name_ : nom du tampon
|
||||
** _full_name_ : nom complet du tampon ("extension.nom") _(WeeChat ≥ 0.3.7)_
|
||||
|
||||
@@ -15327,6 +15327,8 @@ Argomenti:
|
||||
|
||||
* _buffer_: puntatore al buffer
|
||||
* _property_: nome proprietà:
|
||||
// TRANSLATION MISSING
|
||||
** _id_: unique identifier _(WeeChat ≥ 4.3.0)_
|
||||
** _plugin_: nome del plugin che ha creato questo buffer ("core" per il buffer principale di WeeChat)
|
||||
** _name_: nome del buffer
|
||||
** _full_name_: nome completo del buffer ("plugin.nome") _(WeeChat ≥ 0.3.7)_
|
||||
|
||||
@@ -14861,6 +14861,8 @@ const char *weechat_buffer_get_string (struct t_gui_buffer *buffer,
|
||||
|
||||
* _buffer_: バッファへのポインタ
|
||||
* _property_: プロパティ名:
|
||||
// TRANSLATION MISSING
|
||||
** _id_: unique identifier _(WeeChat ≥ 4.3.0)_
|
||||
** _plugin_: バッファを作成したプラグインの名前 ("core" は WeeChat メインバッファ)
|
||||
** _name_: バッファの名前
|
||||
** _full_name_: バッファの完全な名前 ("plugin.name") _(WeeChat バージョン 0.3.7 以上で利用可)_
|
||||
|
||||
@@ -14222,6 +14222,8 @@ const char *weechat_buffer_get_string (struct t_gui_buffer *buffer,
|
||||
|
||||
* _buffer_: показивач на бафер
|
||||
* _property_: име особине:
|
||||
// TRANSLATION MISSING
|
||||
** _id_: unique identifier _(WeeChat ≥ 4.3.0)_
|
||||
** _plugin_: име додатка који је креирао овај бафер („core” за главни бафер програма WeeChat)
|
||||
** _name_: име бафера
|
||||
** _full_name_: пуно име бафера („додатак.име”) _(WeeChat ≥ 0.3.7)_
|
||||
|
||||
+32
-7
@@ -405,10 +405,27 @@ void
|
||||
upgrade_weechat_read_buffer (struct t_infolist *infolist)
|
||||
{
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
const char *key, *var_name, *name, *plugin_name;
|
||||
const char *key, *var_name, *name, *plugin_name, *ptr_id;
|
||||
const char *str;
|
||||
char option_name[64], *option_key, *option_var;
|
||||
char option_name[64], *option_key, *option_var, *error;
|
||||
int index, length, main_buffer;
|
||||
long long id;
|
||||
|
||||
/* "id" is new in WeeChat 4.3.0 */
|
||||
id = -1;
|
||||
if (infolist_search_var (infolist, "id"))
|
||||
{
|
||||
ptr_id = infolist_string (infolist, "id");
|
||||
if (ptr_id)
|
||||
{
|
||||
error = NULL;
|
||||
id = strtoll (ptr_id, &error, 10);
|
||||
if (!error || error[0])
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
if (id < 0)
|
||||
id = gui_buffer_generate_id ();
|
||||
|
||||
plugin_name = infolist_string (infolist, "plugin_name");
|
||||
name = infolist_string (infolist, "name");
|
||||
@@ -420,19 +437,25 @@ upgrade_weechat_read_buffer (struct t_infolist *infolist)
|
||||
{
|
||||
/* use WeeChat main buffer */
|
||||
upgrade_current_buffer = gui_buffers;
|
||||
upgrade_current_buffer->id = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create buffer it it's not main buffer */
|
||||
upgrade_current_buffer = gui_buffer_new (NULL,
|
||||
infolist_string (infolist,
|
||||
"name"),
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
upgrade_current_buffer = gui_buffer_new_props_with_id (
|
||||
id,
|
||||
NULL, /* plugin */
|
||||
infolist_string (infolist, "name"),
|
||||
NULL, /* properties */
|
||||
NULL, NULL, NULL, /* input callback */
|
||||
NULL, NULL, NULL); /* close callback */
|
||||
}
|
||||
if (!upgrade_current_buffer)
|
||||
return;
|
||||
|
||||
if (upgrade_current_buffer->id > gui_buffer_last_id_assigned)
|
||||
gui_buffer_last_id_assigned = upgrade_current_buffer->id;
|
||||
|
||||
ptr_buffer = upgrade_current_buffer;
|
||||
|
||||
if (infolist_integer (infolist, "current_buffer"))
|
||||
@@ -799,6 +822,8 @@ upgrade_weechat_read_cb (const void *pointer, void *data,
|
||||
(void) data;
|
||||
(void) upgrade_file;
|
||||
|
||||
gui_buffer_last_id_assigned = -1;
|
||||
|
||||
infolist_reset_item_cursor (infolist);
|
||||
while (infolist_next (infolist))
|
||||
{
|
||||
|
||||
+100
-18
@@ -32,6 +32,7 @@
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../core/weechat.h"
|
||||
@@ -75,6 +76,8 @@ int gui_buffers_visited_count = 0; /* number of visited buffers*/
|
||||
int gui_buffers_visited_frozen = 0; /* 1 to forbid list updates */
|
||||
struct t_gui_buffer *gui_buffer_last_displayed = NULL; /* last b. displayed */
|
||||
|
||||
long long gui_buffer_last_id_assigned = -1; /* last id assigned */
|
||||
|
||||
char *gui_buffer_reserved_names[] =
|
||||
{ GUI_BUFFER_MAIN, SECURE_BUFFER_NAME, GUI_COLOR_BUFFER_NAME,
|
||||
NULL
|
||||
@@ -106,7 +109,7 @@ char *gui_buffer_properties_get_integer[] =
|
||||
NULL
|
||||
};
|
||||
char *gui_buffer_properties_get_string[] =
|
||||
{ "plugin", "name", "full_name", "old_full_name", "short_name", "title",
|
||||
{ "id", "plugin", "name", "full_name", "old_full_name", "short_name", "title",
|
||||
"input", "text_search_input", "highlight_words", "highlight_disable_regex",
|
||||
"highlight_regex", "highlight_tags_restrict", "highlight_tags",
|
||||
"hotlist_max_level_nicks",
|
||||
@@ -605,6 +608,34 @@ gui_buffer_insert (struct t_gui_buffer *buffer)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new unique id for a buffer.
|
||||
*
|
||||
* The id is the current time with microseconds precision.
|
||||
* The same time (including microseconds) can be used only one time, so that
|
||||
* all buffer ids are guaranteed to be unique.
|
||||
*/
|
||||
|
||||
long long
|
||||
gui_buffer_generate_id ()
|
||||
{
|
||||
struct timeval tv;
|
||||
long long id;
|
||||
|
||||
gettimeofday (&tv, NULL);
|
||||
|
||||
id = ((long long)tv.tv_sec * 1000000LL) + (long long)(tv.tv_usec);
|
||||
|
||||
/*
|
||||
* ensure we never use the same id for two buffers and that the returned
|
||||
* id is strictly greater than the last assigned one
|
||||
*/
|
||||
if (id <= gui_buffer_last_id_assigned)
|
||||
id = gui_buffer_last_id_assigned + 1;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes input_buffer_* variables in a buffer.
|
||||
*/
|
||||
@@ -746,26 +777,28 @@ gui_buffer_apply_config_properties (struct t_gui_buffer *buffer)
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new buffer in current window with some optional properties.
|
||||
* Creates a new buffer in current window with some optional properties,
|
||||
* using id (this function is for internal use only).
|
||||
*
|
||||
* Returns pointer to new buffer, NULL if error.
|
||||
*/
|
||||
|
||||
struct t_gui_buffer *
|
||||
gui_buffer_new_props (struct t_weechat_plugin *plugin,
|
||||
const char *name,
|
||||
struct t_hashtable *properties,
|
||||
int (*input_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *input_data),
|
||||
const void *input_callback_pointer,
|
||||
void *input_callback_data,
|
||||
int (*close_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer),
|
||||
const void *close_callback_pointer,
|
||||
void *close_callback_data)
|
||||
gui_buffer_new_props_with_id (long long id,
|
||||
struct t_weechat_plugin *plugin,
|
||||
const char *name,
|
||||
struct t_hashtable *properties,
|
||||
int (*input_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *input_data),
|
||||
const void *input_callback_pointer,
|
||||
void *input_callback_data,
|
||||
int (*close_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer),
|
||||
const void *close_callback_pointer,
|
||||
void *close_callback_data)
|
||||
{
|
||||
struct t_gui_buffer *new_buffer;
|
||||
int first_buffer_creation;
|
||||
@@ -797,6 +830,9 @@ gui_buffer_new_props (struct t_weechat_plugin *plugin,
|
||||
return NULL;
|
||||
|
||||
/* init buffer */
|
||||
new_buffer->id = id;
|
||||
if (new_buffer->id > gui_buffer_last_id_assigned)
|
||||
gui_buffer_last_id_assigned = new_buffer->id;
|
||||
new_buffer->opening = 1;
|
||||
new_buffer->plugin = plugin;
|
||||
new_buffer->plugin_name_for_upgrade = NULL;
|
||||
@@ -971,6 +1007,41 @@ gui_buffer_new_props (struct t_weechat_plugin *plugin,
|
||||
return new_buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new buffer in current window with some optional properties.
|
||||
*
|
||||
* Returns pointer to new buffer, NULL if error.
|
||||
*/
|
||||
|
||||
struct t_gui_buffer *
|
||||
gui_buffer_new_props (struct t_weechat_plugin *plugin,
|
||||
const char *name,
|
||||
struct t_hashtable *properties,
|
||||
int (*input_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *input_data),
|
||||
const void *input_callback_pointer,
|
||||
void *input_callback_data,
|
||||
int (*close_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer),
|
||||
const void *close_callback_pointer,
|
||||
void *close_callback_data)
|
||||
{
|
||||
return gui_buffer_new_props_with_id (
|
||||
gui_buffer_generate_id (),
|
||||
plugin,
|
||||
name,
|
||||
properties,
|
||||
input_callback,
|
||||
input_callback_pointer,
|
||||
input_callback_data,
|
||||
close_callback,
|
||||
close_callback_pointer,
|
||||
close_callback_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new buffer in current window.
|
||||
*
|
||||
@@ -1441,11 +1512,17 @@ const char *
|
||||
gui_buffer_get_string (struct t_gui_buffer *buffer, const char *property)
|
||||
{
|
||||
const char *ptr_value;
|
||||
static char str_value[64];
|
||||
|
||||
if (!buffer || !property)
|
||||
return NULL;
|
||||
|
||||
if (strcmp (property, "plugin") == 0)
|
||||
if (strcmp (property, "id") == 0)
|
||||
{
|
||||
snprintf (str_value, sizeof (str_value), "%lld", buffer->id);
|
||||
return str_value;
|
||||
}
|
||||
else if (strcmp (property, "plugin") == 0)
|
||||
return gui_buffer_get_plugin_name (buffer);
|
||||
else if (strcmp (property, "name") == 0)
|
||||
return buffer->name;
|
||||
@@ -5012,6 +5089,7 @@ gui_buffer_hdata_buffer_cb (const void *pointer, void *data,
|
||||
0, 0, NULL, NULL);
|
||||
if (hdata)
|
||||
{
|
||||
HDATA_VAR(struct t_gui_buffer, id, LONGLONG, 0, NULL, NULL);
|
||||
HDATA_VAR(struct t_gui_buffer, opening, INTEGER, 0, NULL, NULL);
|
||||
HDATA_VAR(struct t_gui_buffer, plugin, POINTER, 0, NULL, "plugin");
|
||||
HDATA_VAR(struct t_gui_buffer, plugin_name_for_upgrade, STRING, 0, NULL, NULL);
|
||||
@@ -5183,7 +5261,7 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist,
|
||||
{
|
||||
struct t_infolist_item *ptr_item;
|
||||
struct t_gui_key *ptr_key;
|
||||
char option_name[64];
|
||||
char option_name[64], str_value[64];
|
||||
int i;
|
||||
|
||||
if (!infolist || !buffer)
|
||||
@@ -5198,6 +5276,9 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist,
|
||||
if (!infolist_new_var_integer (ptr_item, "current_buffer",
|
||||
(gui_current_window->buffer == buffer) ? 1 : 0))
|
||||
return 0;
|
||||
snprintf (str_value, sizeof (str_value), "%lld", buffer->id);
|
||||
if (!infolist_new_var_string (ptr_item, "id", str_value))
|
||||
return 0;
|
||||
if (!infolist_new_var_integer (ptr_item, "opening", buffer->opening))
|
||||
return 0;
|
||||
if (!infolist_new_var_pointer (ptr_item, "plugin", buffer->plugin))
|
||||
@@ -5457,6 +5538,7 @@ gui_buffer_print_log ()
|
||||
{
|
||||
log_printf ("");
|
||||
log_printf ("[buffer (addr:0x%lx)]", ptr_buffer);
|
||||
log_printf (" id. . . . . . . . . . . : %lld", ptr_buffer->id);
|
||||
log_printf (" opening . . . . . . . . : %d", ptr_buffer->opening);
|
||||
log_printf (" plugin. . . . . . . . . : 0x%lx ('%s')",
|
||||
ptr_buffer->plugin, gui_buffer_get_plugin_name (ptr_buffer));
|
||||
|
||||
@@ -98,6 +98,8 @@ struct t_gui_input_undo
|
||||
|
||||
struct t_gui_buffer
|
||||
{
|
||||
long long id; /* unique id for buffer */
|
||||
/* (timestamp with microseconds) */
|
||||
int opening; /* 1 if buffer is being opened */
|
||||
struct t_weechat_plugin *plugin; /* plugin which created this buffer */
|
||||
/* (NULL for a WeeChat buffer) */
|
||||
@@ -276,6 +278,7 @@ extern int gui_buffers_visited_index;
|
||||
extern int gui_buffers_visited_count;
|
||||
extern int gui_buffers_visited_frozen;
|
||||
extern struct t_gui_buffer *gui_buffer_last_displayed;
|
||||
extern long long gui_buffer_last_id_assigned;
|
||||
extern char *gui_buffer_reserved_names[];
|
||||
extern char *gui_buffer_type_string[];
|
||||
extern char *gui_buffer_notify_string[];
|
||||
@@ -300,9 +303,25 @@ extern void gui_buffer_local_var_add (struct t_gui_buffer *buffer,
|
||||
extern void gui_buffer_local_var_remove (struct t_gui_buffer *buffer,
|
||||
const char *name);
|
||||
extern void gui_buffer_notify_set_all ();
|
||||
extern long long gui_buffer_generate_id ();
|
||||
extern int gui_buffer_is_reserved_name (const char *name);
|
||||
extern void gui_buffer_apply_config_option_property (struct t_gui_buffer *buffer,
|
||||
struct t_config_option *option);
|
||||
extern struct t_gui_buffer *gui_buffer_new_props_with_id (long long id,
|
||||
struct t_weechat_plugin *plugin,
|
||||
const char *name,
|
||||
struct t_hashtable *properties,
|
||||
int (*input_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer,
|
||||
const char *input_data),
|
||||
const void *input_callback_pointer,
|
||||
void *input_callback_data,
|
||||
int (*close_callback)(const void *pointer,
|
||||
void *data,
|
||||
struct t_gui_buffer *buffer),
|
||||
const void *close_callback_pointer,
|
||||
void *close_callback_data);
|
||||
extern struct t_gui_buffer *gui_buffer_new_props (struct t_weechat_plugin *plugin,
|
||||
const char *name,
|
||||
struct t_hashtable *properties,
|
||||
|
||||
@@ -705,7 +705,7 @@ def test_hdata():
|
||||
line2 = weechat.hdata_pointer(hdata_line, line1, 'next_line')
|
||||
line3 = weechat.hdata_pointer(hdata_line, line2, 'next_line')
|
||||
# hdata_get_var_offset
|
||||
check(weechat.hdata_get_var_offset(hdata_buffer, 'opening') == 0)
|
||||
check(weechat.hdata_get_var_offset(hdata_buffer, 'id') == 0)
|
||||
check(weechat.hdata_get_var_offset(hdata_buffer, 'plugin') > 0)
|
||||
# hdata_get_var_type_string
|
||||
check(weechat.hdata_get_var_type_string(hdata_buffer, 'plugin') == 'pointer')
|
||||
@@ -751,6 +751,8 @@ def test_hdata():
|
||||
weechat.buffer_set(buffer, 'hotlist', weechat.WEECHAT_HOTLIST_MESSAGE)
|
||||
gui_hotlist = weechat.hdata_get_list(hdata_hotlist, 'gui_hotlist')
|
||||
check(weechat.hdata_long(hdata_hotlist, gui_hotlist, 'creation_time.tv_usec') >= 0)
|
||||
# hdata_longlong
|
||||
check(weechat.hdata_longlong(hdata_buffer, buffer2, 'id') > 1708874542000000)
|
||||
# hdata_string
|
||||
check(weechat.hdata_string(hdata_buffer, buffer2, 'name') == 'test')
|
||||
# hdata_pointer
|
||||
|
||||
@@ -383,6 +383,23 @@ TEST(GuiBuffer, Insert)
|
||||
/* TODO: write tests */
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* gui_buffer_generate_id
|
||||
*/
|
||||
|
||||
TEST(GuiBuffer, GenerateId)
|
||||
{
|
||||
long long id;
|
||||
|
||||
id = gui_buffer_generate_id ();
|
||||
CHECK(id > gui_buffer_last_id_assigned);
|
||||
id = gui_buffer_generate_id ();
|
||||
CHECK(id > gui_buffer_last_id_assigned);
|
||||
id = gui_buffer_generate_id ();
|
||||
CHECK(id > gui_buffer_last_id_assigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* gui_buffer_input_buffer_init
|
||||
@@ -492,6 +509,7 @@ test_buffer_close_cb (const void *pointer, void *data,
|
||||
|
||||
/*
|
||||
* Tests functions:
|
||||
* gui_buffer_new_props_with_id
|
||||
* gui_buffer_new_props
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user