2006-04-28 18:22:03 -07:00
|
|
|
/*
|
2005-10-13 07:08:18 -07:00
|
|
|
* mootextbtree.c
|
|
|
|
*
|
2007-06-24 10:56:20 -07:00
|
|
|
* Copyright (C) 2004-2007 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
2005-10-13 07:08:18 -07:00
|
|
|
*
|
2007-06-24 10:56:20 -07:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2005-10-13 07:08:18 -07:00
|
|
|
*
|
|
|
|
* See COPYING file that comes with this distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MOOEDIT_COMPILATION
|
2005-12-10 20:25:13 -08:00
|
|
|
#include "mooedit/mootext-private.h"
|
2005-10-13 07:08:18 -07:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
2005-12-10 20:26:39 -08:00
|
|
|
static BTNode *bt_node_new (BTNode *parent,
|
|
|
|
guint n_children,
|
|
|
|
guint count,
|
|
|
|
guint n_marks);
|
2006-06-21 02:50:36 -07:00
|
|
|
static BTData *bt_data_new (BTNode *parent);
|
2005-12-10 20:26:39 -08:00
|
|
|
static void bt_node_free_rec (BTNode *node,
|
|
|
|
GSList **removed_marks);
|
|
|
|
static void bt_data_free (BTData *data,
|
|
|
|
GSList **removed_marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
#define NODE_IS_ROOT(node__) (!(node__)->parent)
|
|
|
|
|
2006-04-28 17:38:44 -07:00
|
|
|
#if 0 && defined(MOO_DEBUG)
|
2005-10-13 07:08:18 -07:00
|
|
|
#define WANT_CHECK_INTEGRITY
|
|
|
|
static void CHECK_INTEGRITY (BTree *tree, gboolean check_capacity);
|
|
|
|
#else
|
|
|
|
#define CHECK_INTEGRITY(tree,check_capacity)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2006-05-19 22:09:09 -07:00
|
|
|
#if GLIB_CHECK_VERSION(2,10,0)
|
|
|
|
#define data_free__(data) g_slice_free (BTData, data)
|
|
|
|
#define data_new__() g_slice_new0 (BTData)
|
|
|
|
#define node_free__(node) g_slice_free (BTNode, node)
|
|
|
|
#define node_new__() g_slice_new0 (BTNode)
|
|
|
|
#else
|
|
|
|
#define data_free__ g_free
|
|
|
|
#define node_free__ g_free
|
|
|
|
#define data_new__() g_new0 (BTData, 1)
|
|
|
|
#define node_new__() g_new0 (BTNode, 1)
|
|
|
|
#endif
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
|
|
|
|
BTree*
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_new (void)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
BTree *tree = g_new0 (BTree, 1);
|
|
|
|
|
2005-12-10 20:23:32 -08:00
|
|
|
tree->stamp = 1;
|
2005-10-13 07:08:18 -07:00
|
|
|
tree->depth = 0;
|
2005-12-09 05:57:58 -08:00
|
|
|
tree->root = bt_node_new (NULL, 1, 1, 0);
|
2005-10-13 07:08:18 -07:00
|
|
|
tree->root->is_bottom = TRUE;
|
2006-07-08 07:59:35 -07:00
|
|
|
tree->root->u.data[0] = bt_data_new (tree->root);
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
CHECK_INTEGRITY (tree, TRUE);
|
|
|
|
|
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
guint
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_size (BTree *tree)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (tree != 0, 0);
|
|
|
|
return tree->root->count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_free (BTree *tree)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
if (tree)
|
|
|
|
{
|
2005-12-10 20:26:39 -08:00
|
|
|
bt_node_free_rec (tree->root, NULL);
|
2005-10-13 07:08:18 -07:00
|
|
|
g_free (tree);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BTData*
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_get_data (BTree *tree,
|
|
|
|
guint index_)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
BTNode *node;
|
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (index_ < tree->root->count);
|
|
|
|
|
|
|
|
node = tree->root;
|
|
|
|
|
|
|
|
while (!node->is_bottom)
|
|
|
|
{
|
|
|
|
BTNode **child;
|
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
for (child = node->u.children; index_ >= (*child)->count; child++)
|
2005-10-13 07:08:18 -07:00
|
|
|
index_ -= (*child)->count;
|
|
|
|
|
|
|
|
node = *child;
|
|
|
|
}
|
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
return node->u.data[index_];
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static BTNode*
|
|
|
|
bt_node_new (BTNode *parent,
|
|
|
|
guint n_children,
|
2005-12-09 05:57:58 -08:00
|
|
|
guint count,
|
|
|
|
guint n_marks)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
BTNode *node = node_new__ ();
|
|
|
|
|
|
|
|
node->parent = parent;
|
|
|
|
node->count = count;
|
|
|
|
node->n_children = n_children;
|
2005-12-09 05:57:58 -08:00
|
|
|
node->n_marks = n_marks;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2005-12-10 20:26:39 -08:00
|
|
|
bt_node_free_rec (BTNode *node,
|
|
|
|
GSList **removed_marks)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
if (node->is_bottom)
|
|
|
|
{
|
|
|
|
for (i = 0; i < node->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
bt_data_free (node->u.data[i], removed_marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < node->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
bt_node_free_rec (node->u.children[i], removed_marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
node_free__ (node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static BTData*
|
2006-06-21 02:50:36 -07:00
|
|
|
bt_data_new (BTNode *parent)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
BTData *data = data_new__ ();
|
|
|
|
data->parent = parent;
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2005-12-10 20:26:39 -08:00
|
|
|
bt_data_free (BTData *data,
|
|
|
|
GSList **removed_marks)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
if (data)
|
|
|
|
{
|
2005-12-10 20:30:02 -08:00
|
|
|
if (data->n_marks)
|
2005-12-10 20:23:32 -08:00
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
|
2005-12-10 20:30:02 -08:00
|
|
|
for (i = 0; i < data->n_marks; ++i)
|
2005-12-10 20:26:39 -08:00
|
|
|
{
|
2005-12-10 20:30:02 -08:00
|
|
|
if (removed_marks)
|
|
|
|
{
|
2005-12-10 20:26:39 -08:00
|
|
|
*removed_marks = g_slist_prepend (*removed_marks, data->marks[i]);
|
2005-12-10 20:30:02 -08:00
|
|
|
_moo_line_mark_set_line (data->marks[i], NULL, -1, 0);
|
|
|
|
}
|
|
|
|
else
|
2005-12-10 20:26:39 -08:00
|
|
|
{
|
|
|
|
_moo_line_mark_deleted (data->marks[i]);
|
|
|
|
g_object_unref (data->marks[i]);
|
|
|
|
}
|
2005-12-10 20:23:32 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 05:57:58 -08:00
|
|
|
g_free (data->marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
data_free__ (data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
node_get_index (BTNode *node, gpointer child)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
for (i = 0; ; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
if (node->u.children[i] == child)
|
2005-10-13 07:08:18 -07:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_insert__ (BTNode *node, gpointer data, guint index_)
|
|
|
|
{
|
|
|
|
g_assert (node != NULL);
|
|
|
|
g_assert (node->n_children < BTREE_NODE_MAX_CAPACITY);
|
|
|
|
g_assert (index_ <= node->n_children);
|
|
|
|
|
|
|
|
if (index_ < node->n_children)
|
2006-07-08 07:59:35 -07:00
|
|
|
memmove (node->u.children + index_ + 1,
|
|
|
|
node->u.children + index_,
|
2005-10-13 07:08:18 -07:00
|
|
|
(node->n_children - index_) * sizeof (BTData*));
|
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
node->u.children[index_] = data;
|
2005-10-13 07:08:18 -07:00
|
|
|
node->n_children++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_remove__ (BTNode *node, gpointer data)
|
|
|
|
{
|
|
|
|
guint index;
|
|
|
|
|
|
|
|
g_assert (node != NULL);
|
|
|
|
g_assert (node->n_children > 0);
|
|
|
|
|
|
|
|
index = node_get_index (node, data);
|
|
|
|
|
|
|
|
if (index + 1 < node->n_children)
|
2006-07-08 07:59:35 -07:00
|
|
|
memmove (node->u.data + index,
|
|
|
|
node->u.data + index + 1,
|
2005-10-13 07:08:18 -07:00
|
|
|
(node->n_children - index - 1) * sizeof (BTData*));
|
|
|
|
|
|
|
|
node->n_children--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BTData*
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_insert (BTree *tree,
|
2006-06-21 02:50:36 -07:00
|
|
|
guint index_)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
BTNode *node, *tmp;
|
|
|
|
BTData *data;
|
2005-12-09 00:20:23 -08:00
|
|
|
G_GNUC_UNUSED guint index_orig = index_;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (index_ <= tree->root->count);
|
|
|
|
|
|
|
|
tree->stamp++;
|
|
|
|
|
|
|
|
node = tree->root;
|
|
|
|
|
|
|
|
while (!node->is_bottom)
|
|
|
|
{
|
|
|
|
BTNode **child;
|
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
for (child = node->u.children; index_ > (*child)->count; child++)
|
2005-10-13 07:08:18 -07:00
|
|
|
index_ -= (*child)->count;
|
|
|
|
|
|
|
|
node = *child;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert (node->n_children < BTREE_NODE_MAX_CAPACITY);
|
|
|
|
g_assert (index_ <= node->n_children);
|
|
|
|
|
2006-06-21 02:50:36 -07:00
|
|
|
data = bt_data_new (node);
|
2005-10-13 07:08:18 -07:00
|
|
|
node_insert__ (node, data, index_);
|
|
|
|
|
|
|
|
for (tmp = node; tmp != NULL; tmp = tmp->parent)
|
|
|
|
tmp->count++;
|
|
|
|
|
|
|
|
while (node->n_children == BTREE_NODE_MAX_CAPACITY)
|
|
|
|
{
|
|
|
|
BTNode *new_node;
|
|
|
|
guint new_count, i, node_index;
|
|
|
|
|
|
|
|
if (NODE_IS_ROOT (node))
|
|
|
|
{
|
|
|
|
tree->depth++;
|
2005-12-09 05:57:58 -08:00
|
|
|
node->parent = bt_node_new (NULL, 1, node->count, node->n_marks);
|
2006-07-08 07:59:35 -07:00
|
|
|
node->parent->u.children[0] = node;
|
2005-10-13 07:08:18 -07:00
|
|
|
tree->root = node->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node->is_bottom)
|
|
|
|
new_count = BTREE_NODE_MIN_CAPACITY;
|
|
|
|
else
|
|
|
|
for (new_count = 0, i = BTREE_NODE_MIN_CAPACITY; i < BTREE_NODE_MAX_CAPACITY; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
new_count += node->u.children[i]->count;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
node_index = node_get_index (node->parent, node);
|
|
|
|
g_assert (node_index < node->parent->n_children);
|
|
|
|
|
2005-12-09 05:57:58 -08:00
|
|
|
new_node = bt_node_new (node->parent, BTREE_NODE_MIN_CAPACITY, new_count, 0);
|
2005-10-13 07:08:18 -07:00
|
|
|
new_node->is_bottom = node->is_bottom;
|
|
|
|
node->count -= new_count;
|
|
|
|
node_insert__ (node->parent, new_node, node_index + 1);
|
|
|
|
g_assert (node_get_index (node->parent, new_node) == node_index + 1);
|
|
|
|
g_assert (node_get_index (node->parent, node) == node_index);
|
2006-07-08 07:59:35 -07:00
|
|
|
memcpy (new_node->u.children,
|
|
|
|
node->u.children + BTREE_NODE_MIN_CAPACITY,
|
2005-10-13 07:08:18 -07:00
|
|
|
BTREE_NODE_MIN_CAPACITY * sizeof (BTNode*));
|
|
|
|
node->n_children = BTREE_NODE_MIN_CAPACITY;
|
|
|
|
for (i = 0; i < new_node->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
new_node->u.children[i]->parent = new_node;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
2005-12-09 05:57:58 -08:00
|
|
|
if (node->n_marks)
|
|
|
|
{
|
|
|
|
node->n_marks = 0;
|
|
|
|
new_node->n_marks = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < node->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
node->n_marks += node->u.children[i]->n_marks;
|
2005-12-09 05:57:58 -08:00
|
|
|
for (i = 0; i < new_node->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
new_node->n_marks += new_node->u.children[i]->n_marks;
|
2005-12-09 05:57:58 -08:00
|
|
|
}
|
|
|
|
|
2005-10-13 07:08:18 -07:00
|
|
|
node = node->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_INTEGRITY (tree, TRUE);
|
2006-04-28 18:22:03 -07:00
|
|
|
g_assert (data == _moo_text_btree_get_data (tree, index_orig));
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_nodes (BTNode *parent, guint first)
|
|
|
|
{
|
|
|
|
BTNode *node, *next;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
g_assert (first + 1 < parent->n_children);
|
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
node = parent->u.children[first];
|
|
|
|
next = parent->u.children[first+1];
|
2005-10-13 07:08:18 -07:00
|
|
|
g_assert (node->n_children + next->n_children < BTREE_NODE_MAX_CAPACITY);
|
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
memcpy (node->u.children + node->n_children,
|
|
|
|
next->u.children,
|
2005-10-13 07:08:18 -07:00
|
|
|
next->n_children * sizeof (BTNode*));
|
|
|
|
|
|
|
|
for (i = node->n_children; i < node->n_children + next->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
node->u.children[i]->parent = node;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
node->n_children += next->n_children;
|
|
|
|
node->count += next->count;
|
2005-12-10 20:23:32 -08:00
|
|
|
node->n_marks += next->n_marks;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
node_remove__ (parent, next);
|
|
|
|
node_free__ (next);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-31 02:53:45 -08:00
|
|
|
static void
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_delete (BTree *tree,
|
|
|
|
guint index_,
|
|
|
|
GSList **deleted_marks)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
BTNode *node, *tmp;
|
|
|
|
BTData *data;
|
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (tree->root->count > 1);
|
|
|
|
g_assert (index_ < tree->root->count);
|
|
|
|
|
|
|
|
tree->stamp++;
|
|
|
|
|
2006-04-28 18:22:03 -07:00
|
|
|
data = _moo_text_btree_get_data (tree, index_);
|
2005-10-13 07:08:18 -07:00
|
|
|
g_assert (data != NULL);
|
|
|
|
|
|
|
|
node = data->parent;
|
|
|
|
g_assert (node->count == node->n_children);
|
|
|
|
node_remove__ (node, data);
|
|
|
|
|
|
|
|
for (tmp = node; tmp != NULL; tmp = tmp->parent)
|
2005-12-09 05:57:58 -08:00
|
|
|
{
|
2005-10-13 07:08:18 -07:00
|
|
|
tmp->count--;
|
2005-12-10 20:23:32 -08:00
|
|
|
g_assert (tmp->n_marks >= data->n_marks);
|
2005-12-09 05:57:58 -08:00
|
|
|
tmp->n_marks -= data->n_marks;
|
|
|
|
}
|
|
|
|
|
2005-12-10 20:26:39 -08:00
|
|
|
bt_data_free (data, deleted_marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
while (node->n_children < BTREE_NODE_MIN_CAPACITY)
|
|
|
|
{
|
|
|
|
guint node_index;
|
|
|
|
BTNode *parent = node->parent;
|
|
|
|
|
|
|
|
if (!parent)
|
|
|
|
{
|
|
|
|
if (node->n_children > 1 || node->is_bottom)
|
|
|
|
break;
|
|
|
|
|
|
|
|
tree->depth--;
|
2006-07-08 07:59:35 -07:00
|
|
|
tree->root = node->u.children[0];
|
2005-10-13 07:08:18 -07:00
|
|
|
tree->root->parent = NULL;
|
|
|
|
node_free__ (node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (parent->n_children == 1)
|
|
|
|
{
|
|
|
|
g_assert (NODE_IS_ROOT (parent));
|
|
|
|
tree->depth--;
|
|
|
|
tree->root = node;
|
|
|
|
node->parent = NULL;
|
|
|
|
node_free__ (parent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node_index = node_get_index (parent, node);
|
|
|
|
|
|
|
|
if (node_index)
|
|
|
|
{
|
2006-07-08 07:59:35 -07:00
|
|
|
BTNode *sib = parent->u.children[node_index-1];
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
if (sib->n_children > BTREE_NODE_MIN_CAPACITY)
|
|
|
|
{
|
2006-07-08 07:59:35 -07:00
|
|
|
BTNode *child = sib->u.children[sib->n_children-1];
|
2005-10-13 07:08:18 -07:00
|
|
|
node_insert__ (node, child, 0);
|
|
|
|
node_remove__ (sib, child);
|
|
|
|
child->parent = node;
|
|
|
|
|
2005-12-09 05:57:58 -08:00
|
|
|
node->n_marks += child->n_marks;
|
|
|
|
sib->n_marks -= child->n_marks;
|
|
|
|
|
2005-10-13 07:08:18 -07:00
|
|
|
if (!node->is_bottom)
|
|
|
|
{
|
|
|
|
node->count += child->count;
|
|
|
|
sib->count -= child->count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node->count++;
|
|
|
|
sib->count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
merge_nodes (parent, node_index-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-07-08 07:59:35 -07:00
|
|
|
BTNode *sib = parent->u.children[1];
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
if (sib->n_children > BTREE_NODE_MIN_CAPACITY)
|
|
|
|
{
|
2006-07-08 07:59:35 -07:00
|
|
|
BTNode *child = sib->u.children[0];
|
2005-10-13 07:08:18 -07:00
|
|
|
node_insert__ (node, child, node->n_children);
|
|
|
|
node_remove__ (sib, child);
|
|
|
|
g_assert (node->n_children == BTREE_NODE_MIN_CAPACITY);
|
|
|
|
child->parent = node;
|
|
|
|
|
2005-12-09 05:57:58 -08:00
|
|
|
node->n_marks += child->n_marks;
|
|
|
|
sib->n_marks -= child->n_marks;
|
|
|
|
|
2005-10-13 07:08:18 -07:00
|
|
|
if (!node->is_bottom)
|
|
|
|
{
|
|
|
|
node->count += child->count;
|
|
|
|
sib->count -= child->count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node->count++;
|
|
|
|
sib->count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
merge_nodes (parent, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
node = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_INTEGRITY (tree, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX */
|
|
|
|
void
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_insert_range (BTree *tree,
|
|
|
|
int first,
|
2006-06-21 02:50:36 -07:00
|
|
|
int num)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
2005-12-09 05:57:58 -08:00
|
|
|
g_assert (first >= 0 && first <= (int) tree->root->count);
|
2005-10-13 07:08:18 -07:00
|
|
|
g_assert (num > 0);
|
|
|
|
|
|
|
|
for (i = 0; i < num; ++i)
|
2006-06-21 02:50:36 -07:00
|
|
|
_moo_text_btree_insert (tree, first);
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX */
|
|
|
|
void
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_delete_range (BTree *tree,
|
|
|
|
int first,
|
|
|
|
int num,
|
|
|
|
GSList **deleted_marks)
|
2005-10-13 07:08:18 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
2005-12-09 05:57:58 -08:00
|
|
|
g_assert (first >= 0 && first < (int) tree->root->count);
|
|
|
|
g_assert (num > 0 && first + num <= (int) tree->root->count);
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
for (i = 0; i < num; ++i)
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_delete (tree, first, deleted_marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-10 20:23:32 -08:00
|
|
|
void
|
2006-04-28 18:22:03 -07:00
|
|
|
_moo_text_btree_update_n_marks (G_GNUC_UNUSED BTree *tree,
|
|
|
|
BTData *data,
|
|
|
|
int add)
|
2005-12-10 20:23:32 -08:00
|
|
|
{
|
|
|
|
BTNode *node;
|
|
|
|
|
|
|
|
for (node = (BTNode*) data; node != NULL; node = node->parent)
|
|
|
|
{
|
|
|
|
g_assert (add > 0 || (add < 0 && (int) node->n_marks >= -add));
|
|
|
|
node->n_marks += add;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_INTEGRITY (tree, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-10-13 07:08:18 -07:00
|
|
|
#ifdef WANT_CHECK_INTEGRITY
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_check_count (BTNode *node)
|
|
|
|
{
|
2005-12-09 05:57:58 -08:00
|
|
|
guint real_count = 0, mark_count = 0, i;
|
2005-10-13 07:08:18 -07:00
|
|
|
|
|
|
|
if (node->is_bottom)
|
|
|
|
{
|
|
|
|
real_count = node->n_children;
|
2005-12-09 05:57:58 -08:00
|
|
|
mark_count = node->n_marks;
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-12-09 05:57:58 -08:00
|
|
|
for (i = 0; i < node->n_children; ++i)
|
|
|
|
{
|
2006-07-08 07:59:35 -07:00
|
|
|
real_count += node->u.children[i]->count;
|
|
|
|
mark_count += node->u.children[i]->n_marks;
|
2005-12-09 05:57:58 -08:00
|
|
|
}
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
g_assert (real_count == node->count);
|
2005-12-09 05:57:58 -08:00
|
|
|
g_assert (mark_count == node->n_marks);
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_check (BTNode *node, gboolean is_root, gboolean check_capacity)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
if (is_root)
|
|
|
|
{
|
|
|
|
g_assert (node->parent == NULL);
|
|
|
|
g_assert (node->n_children >= 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_assert (node->parent != NULL);
|
|
|
|
if (check_capacity)
|
|
|
|
g_assert (node->n_children >= BTREE_NODE_MIN_CAPACITY);
|
|
|
|
else
|
|
|
|
g_assert (node->n_children >= 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (check_capacity)
|
|
|
|
g_assert (node->n_children < BTREE_NODE_MAX_CAPACITY);
|
|
|
|
|
|
|
|
g_assert (node->count >= node->n_children);
|
|
|
|
|
|
|
|
if (!is_root)
|
|
|
|
{
|
|
|
|
guint index = node_get_index (node->parent, node);
|
|
|
|
g_assert (index < node->parent->n_children);
|
|
|
|
}
|
|
|
|
|
|
|
|
node_check_count (node);
|
|
|
|
|
|
|
|
if (!node->is_bottom)
|
|
|
|
for (i = 0; i < node->n_children; ++i)
|
2006-07-08 07:59:35 -07:00
|
|
|
node_check (node->u.children[i], FALSE, check_capacity);
|
2005-10-13 07:08:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void CHECK_INTEGRITY (BTree *tree, gboolean check_capacity)
|
|
|
|
{
|
|
|
|
guint i, p;
|
|
|
|
BTNode *node;
|
|
|
|
|
|
|
|
g_assert (tree != NULL);
|
|
|
|
g_assert (tree->root != NULL);
|
|
|
|
g_assert (tree->root->count != 0);
|
|
|
|
|
|
|
|
for (i = 0, p = 1; i < BTREE_MAX_DEPTH - 1; ++i, p *= BTREE_NODE_MIN_CAPACITY) ;
|
2005-12-09 05:57:58 -08:00
|
|
|
g_assert (p > 10000000);
|
2005-10-13 07:08:18 -07:00
|
|
|
|
2006-07-08 07:59:35 -07:00
|
|
|
for (i = 0, node = tree->root; i < tree->depth; ++i, node = node->u.children[0])
|
2005-10-13 07:08:18 -07:00
|
|
|
g_assert (!node->is_bottom);
|
|
|
|
g_assert (node->is_bottom);
|
|
|
|
|
|
|
|
node_check (tree->root, TRUE, check_capacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* WANT_CHECK_INTEGRITY */
|