[Xfce4-commits] <squeeze:master> Start supporting delete from the btree
Peter de Ridder
noreply at xfce.org
Thu Dec 22 23:00:04 CET 2011
Updating branch refs/heads/master
to 1f04b35581219671f11601e0b057f0b26a636769 (commit)
from f3472d91253a3016d68e2941b128a0d96f52ae00 (commit)
commit 1f04b35581219671f11601e0b057f0b26a636769
Author: Peter de Ridder <peter at xfce.org>
Date: Sun Oct 9 16:47:12 2011 +0200
Start supporting delete from the btree
libsqueeze/archive-iter.c | 57 +++-----------
libsqueeze/btree.c | 184 +++++++++++++++++++++++++++++++++++++++++++++
libsqueeze/btree.h | 7 ++
3 files changed, 202 insertions(+), 46 deletions(-)
diff --git a/libsqueeze/archive-iter.c b/libsqueeze/archive-iter.c
index e713cb3..0c3b5f4 100644
--- a/libsqueeze/archive-iter.c
+++ b/libsqueeze/archive-iter.c
@@ -1246,7 +1246,7 @@ lsq_archive_entry_get_child(const LSQArchiveEntry *entry, const gchar *filename)
}
static gint
-lsq_archive_entry_filename_compare(LSQArchiveEntry *a, LSQArchiveEntry *b)
+lsq_archive_entry_compare(LSQArchiveEntry *a, LSQArchiveEntry *b)
{
return strcmp(a->filename, b->filename);
}
@@ -1267,7 +1267,7 @@ lsq_archive_entry_add_child(LSQArchiveEntry *parent, const gchar *filename)
}
//g_debug("i: %s", filename);
- parent->buffer = lsq_btree_insert_sorted_single(parent->buffer, child, (GCompareFunc)lsq_archive_entry_filename_compare);
+ parent->buffer = lsq_btree_insert_sorted_single(parent->buffer, child, (GCompareFunc)lsq_archive_entry_compare);
/* Cache the length so we doen't have to check every time */
parent->buffer_length++;
@@ -1280,11 +1280,15 @@ lsq_archive_entry_add_child(LSQArchiveEntry *parent, const gchar *filename)
return child;
}
+static gint
+lsq_archive_entry_filename_compare(const gchar *a_filename, LSQArchiveEntry *b)
+{
+ return strcmp(a_filename, b->filename);
+}
+
static gboolean
lsq_archive_entry_remove_child(LSQArchiveEntry *entry, const gchar *filename)
{
- LSQBTree *buffer_iter = NULL, **prev_iter = NULL;
-
/* the first element of the array (*entry->children) contains the size of the array */
guint total_size, size = total_size = entry->children?GPOINTER_TO_UINT(*entry->children):0;
guint pos = 0;
@@ -1292,6 +1296,7 @@ lsq_archive_entry_remove_child(LSQArchiveEntry *entry, const gchar *filename)
gint cmp = 0;
const gchar *_pos = strchr(filename, '/');
gchar *_filename;
+ LSQArchiveEntry *found = NULL;
if ( 0 != _pos )
{
@@ -1333,50 +1338,10 @@ lsq_archive_entry_remove_child(LSQArchiveEntry *entry, const gchar *filename)
}
/* search the buffer */
- prev_iter = &entry->buffer;
- if ( NULL == entry->buffer || NULL != entry->buffer->next )
- {
- for(buffer_iter = entry->buffer; buffer_iter; buffer_iter = buffer_iter->next)
- {
- cmp = strcmp(_filename, buffer_iter->entry->filename);
-
- if ( 0 == cmp )
- {
- g_free(_filename);
- *prev_iter = buffer_iter->next;
- g_free(buffer_iter);
- return TRUE;
- }
- if(cmp < 0)
- break;
- prev_iter = &buffer_iter->next;
- }
- }
- else
- {
- for ( buffer_iter = entry->buffer; NULL != buffer_iter; buffer_iter = *prev_iter )
- {
- /* archive can be NULL */
- cmp = strcmp(filename, buffer_iter->entry->filename);
-
- if ( cmp < 0 )
- {
- prev_iter = &buffer_iter->left;
- }
- else if ( cmp > 0 )
- {
- prev_iter = &buffer_iter->right;
- }
- else
- {
- g_critical("todo");
- return TRUE;
- }
- }
- }
+ entry->buffer = lsq_btree_remove_sorted_single(entry->buffer, _filename, (GCompareFunc)lsq_archive_entry_filename_compare, &found);
g_free(_filename);
- return FALSE;
+ return NULL != found;
}
inline static const gchar*
diff --git a/libsqueeze/btree.c b/libsqueeze/btree.c
index ca3c49f..69ab4aa 100644
--- a/libsqueeze/btree.c
+++ b/libsqueeze/btree.c
@@ -234,6 +234,190 @@ lsq_btree_insert_sorted_single (
return list;
}
+LSQBTree *
+lsq_btree_remove_sorted_single (
+ LSQBTree *list,
+ gchar *filename,
+ GCompareFunc cmp_func,
+ LSQArchiveEntry **found )
+{
+ gint cmp;
+ LSQBTree *iter;
+ LSQBTree **next = &list;
+ LSQBTree *del_entry;
+ LSQBTree *stack[LSQ_BTREE_MAX_DEPTH];
+ guint stack_i = 0;
+ LSQBTree *swap_iter;
+ gboolean short_side;
+
+ if ( NULL != found )
+ {
+ *found = NULL;
+ }
+
+ /* The tree is flattened */
+ if ( NULL == list || NULL != list->next )
+ {
+ for ( iter = list; NULL != iter; iter = iter->next)
+ {
+ cmp = cmp_func( filename, iter->entry );
+
+ if ( 0 == cmp )
+ {
+ if ( NULL != found )
+ {
+ *found = iter->entry;
+ }
+
+ /* remove it */
+ *next = iter->next;
+ g_free ( iter );
+ return list;
+ }
+ else if ( 0 > cmp )
+ {
+ return list;
+ }
+
+ next = &iter->next;
+ }
+ }
+ else
+ {
+ /* Walk the btree */
+ for ( iter = list; NULL != iter; iter = *next )
+ {
+ /* archive can be NULL */
+ cmp = cmp_func( filename, iter->entry );
+
+ if ( 0 > cmp )
+ {
+ /* Go the the left */
+ next = &iter->left;
+ }
+ else if ( 0 < cmp )
+ {
+ /* Go to the right */
+ next = &iter->right;
+ }
+ else
+ {
+ if ( NULL != found )
+ {
+ *found = iter->entry;
+ }
+ break;
+ }
+
+ /* Keep a stack of the path we followed */
+ g_return_val_if_fail(stack_i < LSQ_BTREE_MAX_DEPTH, NULL);
+ stack[stack_i++] = iter;
+ }
+
+ /* Not found */
+ if ( NULL == iter )
+ {
+ return list;
+ }
+
+ if ( NULL == iter->left )
+ {
+ *next = iter->right;
+ g_free ( iter );
+ }
+ else if ( NULL == iter->right )
+ {
+ *next = iter->left;
+ g_free ( iter );
+ }
+ else
+ {
+ /* Find either the most right or most left element in the tree and replace iter with it.
+ * We do this by replaceing the content of the iter, not the iter itself.
+ *
+ * We that the longest of the two paths, i the hope to be better balanced. */
+
+ /* Keep a stack of the path we followed */
+ g_return_val_if_fail(stack_i < LSQ_BTREE_MAX_DEPTH, NULL);
+ stack[stack_i++] = iter;
+
+ /* Right it the longest */
+ if ( 0 < iter->balance )
+ {
+ /* Go right */
+ for ( swap_iter = iter->right; NULL != swap_iter->left; swap_iter = *next )
+ {
+ next = &swap_iter->left;
+
+ /* Keep a stack of the path we followed */
+ g_return_val_if_fail(stack_i < LSQ_BTREE_MAX_DEPTH, NULL);
+ stack[stack_i++] = iter;
+ }
+
+ /* remove the iter from the list */
+ *next = swap_iter->right;
+
+ /* copy the iter to our current location */
+ iter->entry = swap_iter->entry;
+
+ g_free ( swap_iter );
+ }
+ else
+ {
+ /* Go left */
+ for ( swap_iter = iter->right; NULL != iter->left; iter = iter->left )
+ {
+ next = &swap_iter->right;
+
+ /* Keep a stack of the path we followed */
+ g_return_val_if_fail(stack_i < LSQ_BTREE_MAX_DEPTH, NULL);
+ stack[stack_i++] = iter;
+ }
+
+ /* remove the iter from the list */
+ *next = swap_iter->left;
+
+ /* copy the iter to our current location */
+ iter->entry = swap_iter->entry;
+
+ g_free ( swap_iter );
+ }
+ }
+
+ /* Get the new pointer for balancing */
+ del_entry = *next;
+
+ /* Balance the tree */
+ while ( 0 < stack_i )
+ {
+ iter = stack[--stack_i];
+
+ /* Calculate new the balance for the parent */
+ if ( iter->left == del_entry )
+ {
+ short_side = 0 <= iter->balance;
+ ++iter->balance;
+ }
+ else
+ {
+ short_side = 0 >= iter->balance;
+ --iter->balance;
+ }
+
+ /* The balance in the higher parents doesn't change when the short side changed */
+ if ( FALSE != short_side )
+ {
+ break;
+ }
+
+ /* Store ourself in new_entry for the check in the next parent */
+ del_entry = iter;
+ }
+ }
+
+ return list;
+}
+
guint
lsq_btree_length ( LSQBTree *list )
{
diff --git a/libsqueeze/btree.h b/libsqueeze/btree.h
index a7bc8d7..574a87b 100644
--- a/libsqueeze/btree.h
+++ b/libsqueeze/btree.h
@@ -33,6 +33,13 @@ lsq_btree_insert_sorted_single (
LSQArchiveEntry *entry,
GCompareFunc ) G_GNUC_INTERNAL;
+LSQBTree *
+lsq_btree_remove_sorted_single (
+ LSQBTree *list,
+ gchar *filename,
+ GCompareFunc cmp_func,
+ LSQArchiveEntry **found ) G_GNUC_INTERNAL;
+
guint
lsq_btree_length ( LSQBTree *list ) G_GNUC_INTERNAL;
More information about the Xfce4-commits
mailing list