[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