Commit 4baf41fc authored by inge's avatar inge

Added code for an iterator.

parent 81e9082c
Thu Sep 12 19:14:39 1996 Inge Wallin <inge@lysator.liu.se>
* local-to-global.h: Added code for an iterator.
* local-to-global.c: Added code for an iterator.
* kom-types.h: Include some files which are used here.
Sun Sep 1 21:32:22 1996 Inge Wallin <inge@lysator.liu.se>
* (l2g_delete): Delete the block if empty.
......
......@@ -158,6 +158,81 @@ find_block(Local_to_global *l2g, Local_text_no lno)
}
static Local_text_no
find_block_index_key(Local_to_global *l2g, Local_text_no lno,
L2g_block_info **binfo_out,
int *index_out)
{
L2g_block_info * binfo;
int i;
/* If the number is not to be found, return 0. */
binfo = find_block(l2g, lno);
if (binfo == NULL)
return 0;
/* If lno is lower than the first text, treat this as a special case. */
if (lno >= binfo->start) {
/* Check the found block */
if (binfo->key_block == NULL) {
/* dense block */
for (i = lno - binfo->start + 1; i < binfo->first_free; ++i) {
if (binfo->value_block[i] != 0) {
*binfo_out = binfo;
*index_out = i;
return binfo->start + i;
}
}
} else {
/* sparse block */
/* FIXME: binary search */
for (i = 0; i < binfo->first_free; ++i) {
if (binfo->key_block[i] > lno) {
*binfo_out = binfo;
*index_out = i;
return binfo->key_block[i];
}
}
}
binfo++;
}
/*
* If the block didn't contain anything more, try next block
* until there are no more blocks. Blocks can be completely
* empty due to removals of entries.
*/
for (; binfo < l2g->blocks + l2g->num_blocks; ++binfo) {
/* If the block contains anything at all, get the item. */
if (binfo->zeroes < L2G_BLOCKSIZE){
if (binfo->key_block == NULL) {
/* dense block */
for (i = 0; i < binfo->first_free; ++i) {
if (binfo->value_block[i] != 0) {
*binfo_out = binfo;
*index_out = i;
return binfo->start + i;
}
}
} else {
/* sparse block */
*binfo_out = binfo;
*index_out = 0;
return binfo->key_block[0];
}
}
}
return 0;
}
/* ================================================================ */
/* ==== Outside accessible functions ==== */
/* ================================================================ */
......@@ -282,12 +357,26 @@ l2g_append(Local_to_global *l2g,
} else if (binfo->key_block == NULL
&& lno - binfo->start >= L2G_BLOCKSIZE){
/*
* First of all, a little optimization:
* If the block contains no entries, the entries in it have
* been deleted. We can then reuse the block and pretend
* it is a newly allocated block.
*/
if (binfo->zeroes == L2G_BLOCKSIZE) {
binfo->first_free = 0;
binfo->start = 0;
if (binfo->value_block != NULL) {
free(binfo->value_block);
binfo->value_block = NULL;
}
/*
* If the last block is dense, and LNO is outside the block,
* check if we should convert it to a sparse block or if we
* should allocate a new one.
*/
if ((L2G_BLOCKSIZE - binfo->first_free)
} else if ((L2G_BLOCKSIZE - binfo->first_free)
+ binfo->zeroes > L2G_BLOCKSIZE / 2) {
make_sparse(binfo);
} else {
......@@ -348,10 +437,14 @@ l2g_delete(Local_to_global *l2g, Local_text_no lno)
/* FIXME: Compacting? */
binfo->value_block[i] = 0;
binfo->zeroes++;
break;
}
}
}
#if 0
/* NOTE: This is disabled since it wreaks havoc with iterators. */
/* Delete the block if it is empty. */
/* NOTE, FIXME: Check what this does to iterators, and maybe */
/* find some other way. Perhaps we could set */
......@@ -359,6 +452,7 @@ l2g_delete(Local_to_global *l2g, Local_text_no lno)
/* the blocks only when compact() is called. */
if (binfo->zeroes == L2G_BLOCKSIZE)
delete_block(l2g, binfo);
#endif
}
......@@ -403,54 +497,7 @@ l2g_next_key(Local_to_global *l2g, Local_text_no lno)
L2g_block_info * binfo;
int i;
binfo = find_block(l2g, lno);
if (binfo == NULL)
return 0;
/* If lno is lower than the first text, treat this as a special case. */
if (lno >= binfo->start) {
/* Check the found block */
if (binfo->key_block == NULL) {
/* dense block */
for (i = lno - binfo->start + 1; i < binfo->first_free; ++i) {
if (binfo->value_block[i] != 0)
return binfo->start + i;
}
} else {
/* sparse block */
/* FIXME: binary search */
for (i = 0; i < binfo->first_free; ++i) {
if (binfo->key_block[i] > lno)
return binfo->key_block[i];
}
}
binfo++;
}
/*
* If the block didn't contain anything more, try next block
* until there are no more blocks. Blocks can be completely
* empty due to removals of entries.
*/
for (; binfo < l2g->blocks + l2g->num_blocks; ++binfo) {
/* If the block contains anything at all, get the item. */
if (binfo->zeroes < L2G_BLOCKSIZE){
if (binfo->key_block == NULL) {
/* dense block */
for (i = 0; i < binfo->first_free; ++i) {
if (binfo->value_block[i] != 0)
return binfo->start + i;
}
} else {
/* sparse block */
return binfo->key_block[0];
}
}
}
return 0;
return find_block_index_key(l2g, lno, &binfo, &i);
}
......@@ -586,3 +633,128 @@ l2g_write(Local_to_global *l2g, FILE *fp)
fputs(" ]", fp);
}
/* ================================================================ */
/* === Iterator code === */
/* ================================================================ */
void
l2gi_searchall (L2g_iterator *l2gi, Local_to_global *l2g)
{
L2g_block_info * binfo;
int index;
l2gi->l2g = l2g;
find_block_index_key(l2g, 0, &binfo, &index);
l2gi->binfo = binfo;
l2gi->arrindex = index;
l2gi->endval = MAX_LOCAL_TEXT_NO;
if (binfo == NULL) {
l2gi->search_ended = 1;
return;
}
if (binfo->key_block == NULL) {
l2gi->lno = binfo->start + index;
l2gi->tno = binfo->value_block[index];
} else {
l2gi->lno = binfo->key_block[index];
l2gi->tno = binfo->value_block[index];
}
}
void
l2gi_searchsome(L2g_iterator *l2gi, Local_to_global *l2g,
Local_text_no start,
Local_text_no end)
{
L2g_block_info * binfo;
int index;
l2gi->l2g = l2g;
find_block_index_key(l2g, start, &binfo, &index);
l2gi->binfo = binfo;
l2gi->arrindex = index;
l2gi->endval = end;
if (binfo == NULL) {
l2gi->search_ended = 1;
return;
}
if (binfo->key_block == NULL) {
l2gi->lno = binfo->start + index;
l2gi->tno = binfo->value_block[index];
} else {
l2gi->lno = binfo->key_block[index];
l2gi->tno = binfo->value_block[index];
}
}
void l2gi_next(L2g_iterator *l2gi)
{
Local_to_global * l2g;
L2g_block_info * binfo;
int i;
int arrindex;
l2g = l2gi->l2g;
arrindex = l2gi->arrindex + 1;
for (binfo = l2gi->binfo;
binfo < l2g->blocks + l2g->num_blocks;
++binfo, arrindex = 0)
{
/* If the block contains nothing at all, skip to next block item. */
/* This works even the first time around. */
if (binfo->zeroes == L2G_BLOCKSIZE)
continue;
if (binfo->key_block == NULL) {
/* dense block */
for (i = arrindex; i < binfo->first_free; ++i) {
if (binfo->start + i >= l2gi->endval) {
l2gi->search_ended = 1;
return;
}
if (binfo->value_block[i] != 0) {
l2gi->binfo = binfo;
l2gi->arrindex = i;
l2gi->lno = binfo->start + i;
l2gi->tno = binfo->value_block[i];
return;
}
}
} else {
/* sparse block */
for (i = arrindex; i < binfo->first_free; ++i) {
if (binfo->key_block[i] >=l2gi->endval) {
l2gi->search_ended = 1;
return;
}
if (binfo->value_block[i] != 0) {
l2gi->binfo = binfo;
l2gi->arrindex = i;
l2gi->lno = binfo->key_block[i];
l2gi->tno = binfo->value_block[i];
return;
}
}
}
}
l2gi->search_ended = 1;
return;
}
......@@ -47,6 +47,51 @@ void l2g_compact (Local_to_global *l2g);
/* Text file representation, e.g. for the database. */
void l2g_dump (Local_to_global *l2g, FILE *file);
void l2g_read (Local_to_global *l2g, FILE *file);
void l2g_print (Local_to_global *l2g, FILE *file);
void l2g_write (Local_to_global *l2g, FILE *file);
/* ================================================================ */
/*
* Iterator for a Local_to_global.
*
* Usage:
*
* Local_to_global l2g;
* L2g_iterator l2gi;
*
* for (l2gi_searchall(&l2gi, &l2g); !l2gi.search_ended; l2gi_next(l2gi)) {
* use(l2gi.lno, l2gi.tno);
* }
*
* or:
*
* for (l2gi_searchsome(&l2gi, &l2g, startval, endval);
* !l2gi.search_ended;
* l2gi_next(l2gi))
* {
* use(l2gi.lno, l2gi.tno);
* }
*/
typedef struct {
Local_to_global * l2g;
L2g_block_info * binfo;
int arrindex;
Local_text_no endval; /* Last index in the search + 1 */
int search_ended; /* 1 if finished, 0 otherwise */
Local_text_no lno; /* The Local_text_no to use */
Text_no tno; /* The Text_no to use */
} L2g_iterator;
void l2gi_searchall (L2g_iterator *l2gi, Local_to_global *l2g);
void l2gi_searchsome(L2g_iterator *l2gi, Local_to_global *l2g,
Local_text_no start, Local_text_no end);
void l2gi_next(L2g_iterator *l2gi);
#endif /* LOCAL2GLOBAL__H */
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