--- a/libpurple/trie.c Tue Mar 25 22:52:25 2014 +0100
+++ b/libpurple/trie.c Wed Mar 26 01:02:47 2014 +0100
@@ -22,6 +22,8 @@
@@ -49,6 +51,7 @@
@@ -171,7 +174,7 @@
/* Allocates a state and binds it to the parent. */
-purple_trie_state_new(PurpleTrie *trie, PurpleTrieState *parent, guchar letter)
+purple_trie_state_new(PurpleTrie *trie, PurpleTrieState *parent, guchar character) PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(trie);
@@ -200,7 +203,7 @@
- parent->children[letter] = state;
+ parent->children[character] = state; @@ -241,12 +244,12 @@
for (cur_len = 0; reclist != NULL; cur_len++) {
for (it = reclist; it; it = it->next) {
PurpleTrieRecord *rec = it->rec;
- guchar letter = rec->word[cur_len];
+ guchar character = rec->word[cur_len]; PurpleTrieState *prefix = it->extra_data;
PurpleTrieState *lon_suf_parent;
/* the whole word is already added to the trie */
+ if (character == '\0') { if (prefix->found_word == NULL)
prefix->found_word = rec;
@@ -263,15 +266,15 @@
/* word's prefix is already in the trie, added by the
- if (prefix->children && prefix->children[letter]) {
- it->extra_data = prefix->children[letter];
+ if (prefix->children && prefix->children[character]) { + it->extra_data = prefix->children[character]; /* We need to create a new branch of trie.
- * prefix is now of length increased by one letter.
+ * prefix is now of length increased by one character. - prefix = purple_trie_state_new(trie, prefix, letter);
+ prefix = purple_trie_state_new(trie, prefix, character); g_object_unref(reclist_mpool);
@@ -287,12 +290,13 @@
lon_suf_parent = prefix->parent->longest_suffix;
if (lon_suf_parent->children &&
- lon_suf_parent->children[letter])
+ lon_suf_parent->children[character]) - prefix->longest_suffix =
- lon_suf_parent->children[letter];
+ prefix->longest_suffix = lon_suf_parent-> + lon_suf_parent = lon_suf_parent->longest_suffix; if (prefix->longest_suffix == NULL)
prefix->longest_suffix = root;
@@ -305,6 +309,66 @@
/*******************************************************************************
+ ******************************************************************************/ +purple_trie_replace(PurpleTrie *trie, const gchar *src, + PurpleTrieReplaceCb replace_cb, gpointer user_data) + PurpleTriePrivate *priv = PURPLE_TRIE_GET_PRIVATE(trie); + PurpleTrieState *state; + g_return_val_if_fail(replace_cb != NULL, g_strdup(src)); + g_return_val_if_fail(priv != NULL, NULL); + out = g_string_new(NULL); + state = priv->root_state; + while (src[i] != '\0') { + guchar character = src[i]; + /* change state after processing a character */ + /* Perfect fit - next character is the same, as the + * child of the prefix we reached so far. */ + if (state->children && state->children[character]) { + state = state->children[character]; + /* We reached root, that's a pity. */ + if (state == priv->root_state) + state = state->longest_suffix; + /* if we reached a "found" state, let's process it */ + if (state->found_word) { + was_replaced = replace_cb(out, state->found_word->word, + state->found_word->data, user_data); + if (was_replaced || priv->reset_on_match) { + i += state->found_word->word_len; + state = priv->root_state; + return g_string_free(out, FALSE); +/******************************************************************************* ******************************************************************************/
@@ -325,6 +389,7 @@
rec = purple_memory_pool_alloc(priv->records_obj_mempool,
sizeof(PurpleTrieRecord), sizeof(gpointer));
rec->word = purple_memory_pool_strdup(priv->records_str_mempool, word);
+ rec->word_len = strlen(word); priv->records = purple_record_list_prepend(priv->records_obj_mempool,
--- a/libpurple/trie.h Tue Mar 25 22:52:25 2014 +0100
+++ b/libpurple/trie.h Wed Mar 26 01:02:47 2014 +0100
@@ -57,6 +57,22 @@
void (*purple_reserved4)(void);
+ * @out: Currently built output string, append replacement to it. + * @word_data: A user data bound with this word, when added with + * @user_data: A user supplied data passed when calling purple_trie_replace(). + * A funtion called after every found matching substring to be replaced. + * Returns: %TRUE, if the word was replaced, %FALSE otherwise. In the second + * case you might possibly want to leave @out untouched. +typedef gboolean (*PurpleTrieReplaceCb)(GString *out, const gchar *word, + gpointer word_data, gpointer user_data); @@ -105,6 +121,22 @@
purple_trie_add(PurpleTrie *trie, const gchar *word, gpointer data);
+ * @src: The source string. + * @replace_cb: The replacement function. + * @user_data: Custom data to be passed to @replace_cb. + * Looks for all occuriences of words added to @trie, in @src string. + * It's O(strlen(src)), if replace_cb runs in O(strlen(word)). + * Returns: resulting string. Must be g_free'd when you are done using it. +purple_trie_replace(PurpleTrie *trie, const gchar *src, + PurpleTrieReplaceCb replace_cb, gpointer user_data); #endif /* PURPLE_MEMORY_POOL_H */