131 lines
2.5 KiB
Plaintext
131 lines
2.5 KiB
Plaintext
|
|
fun _count(elm)
|
|
{
|
|
if type(elm) == type({}):
|
|
|
|
if type(elm._count) == type(_count):
|
|
|
|
return elm._count(elm);
|
|
|
|
else if type(elm._count) == type(1):
|
|
|
|
return elm._count;
|
|
|
|
return count(elm);
|
|
}
|
|
|
|
fun newTree()
|
|
{
|
|
return {root: none, _count: 0};
|
|
}
|
|
|
|
fun locate(tree, index, path)
|
|
{
|
|
# This function walks the tree to find the
|
|
# leaf that is referred to by the specified
|
|
# index.
|
|
# The traversed nodes are stored in the path
|
|
# argument. The last one is the leaf.
|
|
# The return value is the index relative to
|
|
# the start of the leaf.
|
|
assert(type(index) == type(1));
|
|
|
|
path = []; # List of traversed nodes (without the leaf).
|
|
rindex = index; # index relative to the found leaf.
|
|
cursor = tree; # Tree cursor. At the end it will refer to the leaf.
|
|
|
|
path[count(path)] = cursor;
|
|
|
|
while cursor.is_leaf == false:
|
|
{
|
|
if rindex < _count(cursor.left):
|
|
cursor = cursor.left;
|
|
else
|
|
{
|
|
rindex = rindex - _count(cursor.left);
|
|
cursor = cursor.right;
|
|
}
|
|
|
|
path[count(path)] = cursor;
|
|
}
|
|
return rindex;
|
|
}
|
|
|
|
fun insert(tree, data, index)
|
|
{
|
|
if index == none:
|
|
# Insert at the end.
|
|
index = _count(tree);
|
|
|
|
path = [];
|
|
rindex = locate(tree, index, path);
|
|
assert(count(path) > 1);
|
|
|
|
leaf = path[count(path)-1];
|
|
assert(type(leaf) == type(newBuffer(0)));
|
|
|
|
if rindex == 0:
|
|
# Want to store the data before
|
|
# the leaf buffer.
|
|
{}
|
|
else if rindex < leaf.used:
|
|
# Want to store the data in the
|
|
# middle of the leaf.
|
|
{
|
|
fun min(a, b)
|
|
{
|
|
if a < b:
|
|
return a;
|
|
return b;
|
|
}
|
|
|
|
fun copy(dst, src, num)
|
|
{
|
|
i = 0;
|
|
while i < num:
|
|
{
|
|
dst[i] = src[i];
|
|
i = i + 1;
|
|
}
|
|
}
|
|
|
|
# Insert in the current leaf what's
|
|
# possible.
|
|
|
|
unused = count(leaf.buffer) - leaf.used;
|
|
copied = min(unused, count(data));
|
|
copy(leaf.buffer, data, copied);
|
|
leaf.used = leaf.used + copied;
|
|
|
|
if copied == count(data):
|
|
{
|
|
# We're done. The unused portion of
|
|
# the leaf was enough to store the
|
|
# data.
|
|
|
|
# Update the path.
|
|
i = count(path)-2;
|
|
while i > 0:
|
|
{
|
|
if path[i] == path[i-1].left:
|
|
path[i-1]._count = path[i-1]._count + copied;
|
|
i = i - 1;
|
|
}
|
|
return none;
|
|
}
|
|
|
|
# There's more data that needs to be
|
|
# stored, but now we don't need to
|
|
# insert in the middle of the leaf.
|
|
|
|
data = sliceBuffer(data, copying, count(data));
|
|
}
|
|
|
|
if rindex == leaf.used:
|
|
# Want to append data to the
|
|
# end of the contents.
|
|
{}
|
|
}
|
|
|
|
print( count(newTree()), '\n');
|
|
print(_count(newTree()), '\n'); |