Commit 963f8e5e authored by Per Cederqvist's avatar Per Cederqvist

(add_block_before): New static function.

(find_block): Return a pointer to the last block instead of a NULL
	pointer if a too large local text number is supplied.
(l2g_expensive_set): Now fully implemented.
parent 2e58007c
......@@ -219,6 +219,49 @@ add_block(Local_to_global *l2g)
return binfo;
}
/* Insert a new block in the middle of an l2g structure. This
is only used by l2g_expensive_set, so it doesn't have to be
optimally efficient. */
static void
add_block_before(Local_to_global *l2g,
int position)
{
struct l2g_block_info * binfo;
struct l2g_block_info * new_blocks;
int ix;
/* Allocate a new block pointer array. */
new_blocks = smalloc((l2g->num_blocks+1) * sizeof(struct l2g_block_info));
/* Copy blocks before and after position. */
for (ix = 0; ix < position; ix++)
new_blocks[ix] = l2g->blocks[ix];
for (ix = position; ix < l2g->num_blocks; ix++)
new_blocks[ix+1] = l2g->blocks[ix];
/* Discard the old block pointers. */
sfree(l2g->blocks);
l2g->blocks = new_blocks;
l2g->num_blocks++;
/* Initialize the new block. */
binfo = &new_blocks[position];
binfo->first_free = 0;
binfo->zeroes = L2G_BLOCKSIZE;
#ifndef NDEBUG
binfo->start = 0xdeadbeef;
#endif
binfo->key_block = NULL;
binfo->value_block = smalloc(L2G_BLOCKSIZE * sizeof(Text_no));
#ifndef NDEBUG
for (ix = 0; ix < L2G_BLOCKSIZE; ++ix)
binfo->value_block[ix] = 0xdeadbeef;
#endif
if (++nr_blocks > nr_blocks_peak)
nr_blocks_peak = nr_blocks;
}
/*
* Delete a block from the Local_to_global L2G. The pointer BINFO
......@@ -287,14 +330,15 @@ make_sparse(struct l2g_block_info *binfo)
/*
* Find the block where the local text no LNO is and return a pointer
* to it. Returning a pointer does not mean that the text still exists,
* so a search within the block must also be done later. If LNO is
* smaller than the smallest number in the structure a pointer to the
* first block will be returned.
* Find the block where the local text no LNO should be and return a
* pointer to it. Returning a pointer does not necessarily mean that
* the text exists, so a search within the block must also be done
* later. If LNO is smaller than the smallest number in the structure
* a pointer to the first block will be returned. If LNO is larger
* than the largest number in the structure a pointer to the last
* block will be returned.
*
* Return NULL if LNO is bigger than the highest number in the
* structure, or if the structure is empty.
* Return NULL if (and only if) the structure is empty.
*/
static struct l2g_block_info *
......@@ -309,11 +353,6 @@ find_block(const Local_to_global *l2g, Local_text_no lno)
/* Let binfo point to the last block. */
binfo = &(l2g->blocks[l2g->num_blocks - 1]);
/* If lno is greater than the biggest local number, return NULL. */
assert(binfo->first_free > 0);
if (lno > key_value(binfo, binfo->first_free - 1))
return NULL;
/* Find the block where lno *could* be. */
/* FIXME: Binary search? */
while (binfo > l2g->blocks)
......@@ -708,7 +747,7 @@ l2g_append(Local_to_global *l2g,
binfo->zeroes--;
}
#if 0 /* Not yet completely implemented. */
void
l2g_expensive_set(Local_to_global *l2g,
Local_text_no lno,
......@@ -716,6 +755,7 @@ l2g_expensive_set(Local_to_global *l2g,
{
struct l2g_block_info * binfo;
Local_text_no_iter ix;
int block_no;
if (lno >= l2g->first_unused)
{
......@@ -732,26 +772,43 @@ l2g_expensive_set(Local_to_global *l2g,
binfo = find_block(l2g, lno);
if (binfo == NULL)
{
assert(l2g->num_blocks == 0);
/* Append a new block. */
FIXME;
binfo = add_block(l2g);
assert(binfo->first_free == 0);
assert(binfo->key_block == NULL);
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
}
else if (lno < binfo->start)
{
assert(binfo == l2g->blocks);
/* Prepend a new block. */
FIXME;
add_block_before(l2g, 0);
binfo = l2g->blocks;
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
}
else if (is_dense(binfo))
{
assert(binfo->start <= lno);
if (lno < binfo->start + L2G_BLOCKSIZE)
{
/* The number can be entered into this block. */
while (binfo->start + binfo->first_free <= lno)
{
binfo->value_block[binfo->first_free++] = 0;
assert(binfo->first_free <= L2G_BLOCKSIZE);
}
assert(lno < binfo->start + binfo->first_free);
assert(binfo->first_free < L2G_BLOCKSIZE);
assert(binfo->first_free <= L2G_BLOCKSIZE);
if (binfo->value_block[lno - binfo->start] == 0)
binfo->zeroes--;
......@@ -761,7 +818,13 @@ l2g_expensive_set(Local_to_global *l2g,
{
/* There is no room within this block. Insert a new block
after binfo. */
FIXME;
block_no = 1 + binfo - l2g->blocks;
add_block_before(l2g, block_no);
binfo = l2g->blocks + block_no;
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
}
}
else
......@@ -769,6 +832,7 @@ l2g_expensive_set(Local_to_global *l2g,
ix = sparse_locate_value(binfo, lno);
if (ix < binfo->first_free && binfo->key_block[ix] == lno)
{
/* We found the value in this sparse block. */
assert(binfo->value_block[ix] != 0);
binfo->value_block[ix] = tno;
}
......@@ -776,25 +840,48 @@ l2g_expensive_set(Local_to_global *l2g,
{
if (binfo->zeroes == 0)
{
/* Split the block to make room. */
FIXME; /* IF lno > [the greatest value in the
block] THEN create a new empty
block and let binfo point to it
ELSE move the final lno into the
new block and let binfo point to
the old block, that now contains an
empty slot ENDIF. The ordo for
this is not good when we do many
worst-case insertions, but that is
alright, since this function is
only used for disaster recovery. */
assert(binfo->zeroes == 1 || binfo->first_free == 0);
/* Split the sparse block to make room. */
block_no = 1 + binfo - l2g->blocks;
add_block_before(l2g, block_no);
binfo = l2g->blocks + block_no;
assert(binfo[-1].first_free == L2G_BLOCKSIZE);
if (lno > binfo[-1].key_block[L2G_BLOCKSIZE-1])
{
/* Insert the mapping into the new block. */
binfo->start = lno;
binfo->value_block[0] = tno;
binfo->first_free = 1;
binfo->zeroes--;
return;
}
else
{
/* Move the last mapping from the block into the new block,
and enter the new mapping into the old block. */
/* Set up the new block. */
binfo->start = binfo[-1].key_block[L2G_BLOCKSIZE-1];
binfo->value_block[0] = binfo[-1].value_block[
L2G_BLOCKSIZE-1];
binfo->first_free = 1;
binfo->zeroes--;
/* Fix the old block. */
binfo--;
binfo->zeroes++;
binfo->first_free--;
/* The old block is now compact. Let the code below
enter the new mapping into it. */
}
assert(binfo->zeroes == 1);
}
else
sparse_compact(binfo);
/* There is room for a new mapping in this block. */
assert(binfo->zeroes > 0);
for (ix = binfo->first_free; ix > 0; --ix)
{
assert(binfo->key_block[ix-1] != lno);
......@@ -817,7 +904,6 @@ l2g_expensive_set(Local_to_global *l2g,
}
}
}
#endif
/*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment