int gui_history_hdata_history_update_cb (void *data, struct t_hdata *hdata, void *pointer, struct t_hashtable *hashtable) { struct t_gui_history *ptr_history; struct t_gui_buffer *ptr_buffer; const char *text, *buffer; long unsigned int value; int rc; /* make C compiler happy */ (void) data; (void) hdata; rc = 0; text = hashtable_get (hashtable, "text"); if (!text) return rc; if (pointer) { /* update history */ ptr_history = (struct t_gui_history *)pointer; if (ptr_history->text) free (ptr_history->text); ptr_history->text = strdup (text); } else { /* create new entry in history */ ptr_buffer = NULL; if (hashtable_has_key (hashtable, "buffer")) { buffer = hashtable_get (hashtable, "buffer"); if (buffer) { rc = sscanf (buffer, "%lx", &value); if ((rc != EOF) && (rc != 0)) ptr_buffer = (struct t_gui_buffer *)value; } } if (ptr_buffer) gui_history_add (ptr_buffer, text); else gui_history_global_add (text); } return rc; }
int hdata_update (struct t_hdata *hdata, void *pointer, struct t_hashtable *hashtable) { const char *value; struct t_hdata_var *var; int rc; if (!hdata || !hashtable || !hdata->callback_update) return 0; /* check if create of structure is allowed */ if (hashtable_has_key (hashtable, "__create_allowed")) return (int)hdata->create_allowed; /* check if delete of structure is allowed */ if (hashtable_has_key (hashtable, "__delete_allowed")) return (int)hdata->delete_allowed; /* check if update of variable is allowed */ value = hashtable_get (hashtable, "__update_allowed"); if (value) { if (!hdata->callback_update) return 0; var = hashtable_get (hdata->hash_var, value); if (!var) return 0; return (var->update_allowed) ? 1 : 0; } /* update data */ hdata->update_pending = 1; rc = (hdata->callback_update) (hdata->callback_update_data, hdata, pointer, hashtable); hdata->update_pending = 0; return rc; }
TEST(Hashtable, SetGetRemove) { struct t_hashtable *hashtable, *hashtable2; struct t_hashtable_item *item, *ptr_item, *ptr_item2; const char *str_key = HASHTABLE_TEST_KEY; const char *str_value = HASHTABLE_TEST_VALUE; const char *ptr_value; unsigned long long hash; int i; hashtable = hashtable_new (32, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, &test_hashtable_hash_key_cb, &test_hashtable_keycmp_cb); LONGS_EQUAL(32, hashtable->size); LONGS_EQUAL(0, hashtable->items_count); /* invalid set of items */ POINTERS_EQUAL(NULL, hashtable_set_with_size (NULL, NULL, -1, NULL, -1)); POINTERS_EQUAL(NULL, hashtable_set_with_size (NULL, NULL, -1, NULL, -1)); /* add an item in hashtable with NULL value */ item = hashtable_set (hashtable, str_key, NULL); CHECK(item); LONGS_EQUAL(1, hashtable->items_count); STRCMP_EQUAL(str_key, (const char *)item->key); LONGS_EQUAL(strlen (str_key) + 1, item->key_size); POINTERS_EQUAL(NULL, item->value); LONGS_EQUAL(0, item->value_size); POINTERS_EQUAL(NULL, item->prev_item); POINTERS_EQUAL(NULL, item->next_item); /* set a string value for the same key */ item = hashtable_set (hashtable, str_key, str_value); CHECK(item); LONGS_EQUAL(1, hashtable->items_count); STRCMP_EQUAL(str_key, (const char *)item->key); LONGS_EQUAL(strlen (str_key) + 1, item->key_size); STRCMP_EQUAL(str_value, (const char *)item->value); LONGS_EQUAL(strlen (str_value) + 1, item->value_size); POINTERS_EQUAL(NULL, item->prev_item); POINTERS_EQUAL(NULL, item->next_item); /* get item */ item = hashtable_get_item (hashtable, str_key, &hash); CHECK(item); STRCMP_EQUAL(str_key, (const char *)item->key); STRCMP_EQUAL(str_value, (const char *)item->value); LONGS_EQUAL(2, hash); /* get value */ ptr_value = (const char *)hashtable_get (hashtable, str_key); CHECK(ptr_value); STRCMP_EQUAL(ptr_value, str_value); /* check if key is in hashtable */ LONGS_EQUAL(0, hashtable_has_key (hashtable, NULL)); LONGS_EQUAL(0, hashtable_has_key (hashtable, "")); LONGS_EQUAL(0, hashtable_has_key (hashtable, "xxx")); LONGS_EQUAL(1, hashtable_has_key (hashtable, str_key)); /* delete an item */ hashtable_remove (hashtable, str_key); LONGS_EQUAL(0, hashtable->items_count); /* add an item with size in hashtable */ item = hashtable_set_with_size (hashtable, str_key, strlen (str_key) + 1, str_value, strlen (str_value) + 1); CHECK(item); LONGS_EQUAL(1, hashtable->items_count); STRCMP_EQUAL(str_key, (const char *)item->key); LONGS_EQUAL(strlen (str_key) + 1, item->key_size); STRCMP_EQUAL(str_value, (const char *)item->value); LONGS_EQUAL(strlen (str_value) + 1, item->value_size); /* add another item */ hashtable_set (hashtable, "xxx", "zzz"); LONGS_EQUAL(2, hashtable->items_count); /* * test duplication of hashtable and check that duplicated content is * exactly the same as initial hashtable */ hashtable2 = hashtable_dup (hashtable); CHECK(hashtable2); LONGS_EQUAL(hashtable->size, hashtable2->size); LONGS_EQUAL(hashtable->items_count, hashtable2->items_count); for (i = 0; i < hashtable->size; i++) { if (hashtable->htable[i]) { ptr_item = hashtable->htable[i]; ptr_item2 = hashtable2->htable[i]; while (ptr_item && ptr_item2) { LONGS_EQUAL(ptr_item->key_size, ptr_item2->key_size); LONGS_EQUAL(ptr_item->value_size, ptr_item2->value_size); if (ptr_item->key) { STRCMP_EQUAL((const char *)ptr_item->key, (const char *)ptr_item2->key); } else { POINTERS_EQUAL(ptr_item->key, ptr_item2->key); } if (ptr_item->value) { STRCMP_EQUAL((const char *)ptr_item->value, (const char *)ptr_item2->value); } else { POINTERS_EQUAL(ptr_item->value, ptr_item2->value); } ptr_item = ptr_item->next_item; ptr_item2 = ptr_item2->next_item; CHECK((ptr_item && ptr_item2) || (!ptr_item && !ptr_item2)); } } else { POINTERS_EQUAL(hashtable->htable[i], hashtable2->htable[i]); } } /* remove all items */ hashtable_remove_all (hashtable); LONGS_EQUAL(0, hashtable->items_count); /* free hashtables */ hashtable_free (hashtable); hashtable_free (hashtable2); /* * create a hashtable with size 8, and add 6 items, * to check if many items with same hashed key work fine, * the expected htable inside hashtable is: * +-----+ * | 0 | * +-----+ * | 1 | * +-----+ * | 2 | --> "extensible" * +-----+ * | 3 | --> "fast" --> "light" * +-----+ * | 4 | * +-----+ * | 5 | --> "chat" * +-----+ * | 6 | --> "client" * +-----+ * | 7 | --> "weechat" * +-----+ */ hashtable = hashtable_new (8, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, NULL, NULL); LONGS_EQUAL(8, hashtable->size); LONGS_EQUAL(0, hashtable->items_count); item = hashtable_set (hashtable, "weechat", NULL); CHECK(item); POINTERS_EQUAL(item, hashtable->htable[7]); item = hashtable_set (hashtable, "fast", NULL); CHECK(item); POINTERS_EQUAL(item, hashtable->htable[3]); item = hashtable_set (hashtable, "light", NULL); CHECK(item); POINTERS_EQUAL(item, hashtable->htable[3]->next_item); item = hashtable_set (hashtable, "extensible", NULL); CHECK(item); POINTERS_EQUAL(item, hashtable->htable[2]); item = hashtable_set (hashtable, "chat", NULL); CHECK(item); POINTERS_EQUAL(item, hashtable->htable[5]); item = hashtable_set (hashtable, "client", NULL); CHECK(item); POINTERS_EQUAL(item, hashtable->htable[6]); /* free hashtable */ hashtable_free (hashtable); }
char * eval_expression (const char *expr, struct t_hashtable *pointers, struct t_hashtable *extra_vars, struct t_hashtable *options) { int condition, extra_vars_eval, rc, pointers_allocated, regex_allocated; char *value; const char *prefix, *suffix; const char *default_prefix = EVAL_DEFAULT_PREFIX; const char *default_suffix = EVAL_DEFAULT_SUFFIX; const char *ptr_value, *regex_replace; struct t_gui_window *window; regex_t *regex; if (!expr) return NULL; condition = 0; extra_vars_eval = 0; pointers_allocated = 0; regex_allocated = 0; prefix = default_prefix; suffix = default_suffix; regex = NULL; regex_replace = NULL; if (pointers) { regex = (regex_t *)hashtable_get (pointers, "regex"); } else { /* create hashtable pointers if it's NULL */ pointers = hashtable_new (32, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, NULL, NULL); if (!pointers) return NULL; pointers_allocated = 1; } /* * set window/buffer with pointer to current window/buffer * (if not already defined in the hashtable) */ if (gui_current_window) { if (!hashtable_has_key (pointers, "window")) hashtable_set (pointers, "window", gui_current_window); if (!hashtable_has_key (pointers, "buffer")) { window = (struct t_gui_window *)hashtable_get (pointers, "window"); if (window) hashtable_set (pointers, "buffer", window->buffer); } } /* read options */ if (options) { /* check the type of evaluation */ ptr_value = hashtable_get (options, "type"); if (ptr_value && (strcmp (ptr_value, "condition") == 0)) condition = 1; /* check if extra vars must be evaluated */ ptr_value = hashtable_get (options, "extra"); if (ptr_value && (strcmp (ptr_value, "eval") == 0)) extra_vars_eval = 1; /* check for custom prefix */ ptr_value = hashtable_get (options, "prefix"); if (ptr_value && ptr_value[0]) prefix = ptr_value; /* check for custom suffix */ ptr_value = hashtable_get (options, "suffix"); if (ptr_value && ptr_value[0]) suffix = ptr_value; /* check for regex */ ptr_value = hashtable_get (options, "regex"); if (ptr_value) { regex = malloc (sizeof (*regex)); if (string_regcomp (regex, ptr_value, REG_EXTENDED | REG_ICASE) == 0) { regex_allocated = 1; } else { free (regex); regex = NULL; } } /* check for regex replacement (evaluated later) */ ptr_value = hashtable_get (options, "regex_replace"); if (ptr_value) { regex_replace = ptr_value; } } /* evaluate expression */ if (condition) { /* evaluate as condition (return a boolean: "0" or "1") */ value = eval_expression_condition (expr, pointers, extra_vars, extra_vars_eval, prefix, suffix); rc = eval_is_true (value); if (value) free (value); value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE); } else { if (regex && regex_replace) { /* replace with regex */ value = eval_replace_regex (expr, regex, regex_replace, pointers, extra_vars, extra_vars_eval, prefix, suffix); } else { /* only replace variables in expression */ value = eval_replace_vars (expr, pointers, extra_vars, extra_vars_eval, prefix, suffix, NULL); } } if (pointers_allocated) hashtable_free (pointers); if (regex && regex_allocated) { regfree (regex); free (regex); } return value; }
int gui_line_hdata_line_data_update_cb (void *data, struct t_hdata *hdata, void *pointer, struct t_hashtable *hashtable) { const char *value; struct t_gui_line_data *line_data; struct t_gui_window *ptr_win; int rc, update_coords; /* make C compiler happy */ (void) data; line_data = (struct t_gui_line_data *)pointer; rc = 0; update_coords = 0; if (hashtable_has_key (hashtable, "date")) { value = hashtable_get (hashtable, "date"); if (value) { hdata_set (hdata, pointer, "date", value); if (line_data->str_time) free (line_data->str_time); line_data->str_time = gui_chat_get_time_string (line_data->date); rc++; update_coords = 1; } } if (hashtable_has_key (hashtable, "date_printed")) { value = hashtable_get (hashtable, "date_printed"); if (value) { hdata_set (hdata, pointer, "date_printed", value); rc++; } } if (hashtable_has_key (hashtable, "tags_array")) { value = hashtable_get (hashtable, "tags_array"); gui_line_tags_free (line_data); gui_line_tags_alloc (line_data, value); rc++; } if (hashtable_has_key (hashtable, "prefix")) { value = hashtable_get (hashtable, "prefix"); hdata_set (hdata, pointer, "prefix", value); line_data->prefix_length = (line_data->prefix) ? gui_chat_strlen_screen (line_data->prefix) : 0; line_data->buffer->lines->prefix_max_length_refresh = 1; rc++; update_coords = 1; } if (hashtable_has_key (hashtable, "message")) { value = hashtable_get (hashtable, "message"); hdata_set (hdata, pointer, "message", value); rc++; update_coords = 1; } if (rc > 0) { if (update_coords) { for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window) { gui_window_coords_remove_line_data (ptr_win, line_data); } } gui_filter_buffer (line_data->buffer, line_data); gui_buffer_ask_chat_refresh (line_data->buffer, 1); } return rc; }
char * eval_expression (const char *expr, struct t_hashtable *pointers, struct t_hashtable *extra_vars, struct t_hashtable *options) { int condition, rc, pointers_allocated; char *value; const char *prefix, *suffix; const char *default_prefix = EVAL_DEFAULT_PREFIX; const char *default_suffix = EVAL_DEFAULT_SUFFIX; const char *ptr_value; struct t_gui_window *window; if (!expr) return NULL; condition = 0; pointers_allocated = 0; prefix = default_prefix; suffix = default_suffix; /* create hashtable pointers if it's NULL */ if (!pointers) { pointers = hashtable_new (32, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, NULL, NULL); if (!pointers) return NULL; pointers_allocated = 1; } /* * set window/buffer with pointer to current window/buffer * (if not already defined in the hashtable) */ if (gui_current_window) { if (!hashtable_has_key (pointers, "window")) hashtable_set (pointers, "window", gui_current_window); if (!hashtable_has_key (pointers, "buffer")) { window = (struct t_gui_window *)hashtable_get (pointers, "window"); if (window) hashtable_set (pointers, "buffer", window->buffer); } } /* read options */ if (options) { /* check the type of evaluation */ ptr_value = hashtable_get (options, "type"); if (ptr_value && (strcmp (ptr_value, "condition") == 0)) condition = 1; /* check for custom prefix */ ptr_value = hashtable_get (options, "prefix"); if (ptr_value && ptr_value[0]) prefix = ptr_value; /* check for custom suffix */ ptr_value = hashtable_get (options, "suffix"); if (ptr_value && ptr_value[0]) suffix = ptr_value; } /* evaluate expression */ if (condition) { /* evaluate as condition (return a boolean: "0" or "1") */ value = eval_expression_condition (expr, pointers, extra_vars, prefix, suffix); rc = eval_is_true (value); if (value) free (value); value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE); } else { /* only replace variables in expression */ value = eval_replace_vars (expr, pointers, extra_vars, prefix, suffix); } if (pointers_allocated) hashtable_free (pointers); return value; }