* Sebastian Hammer, Adam Dickmeiss
*
* $Log: isamc.c,v $
- * Revision 1.1 1996-10-29 13:40:48 adam
+ * Revision 1.2 1996-10-29 16:44:56 adam
+ * Work on isc_merge.
+ *
+ * Revision 1.1 1996/10/29 13:40:48 adam
* First work.
*
*/
return 0;
}
-void isc_catpos (ISAMC_P ipos, int *cat, int *pos)
-{
- *pos = ipos >> 3;
- *cat = ipos & 7;
-}
-
int isc_read_block (ISAMC is, int cat, int pos, char *dst)
{
if (is->method->debug > 1)
ISAMC_P isc_merge (ISAMC is, ISAMC_P ipos, ISAMC_I data)
{
- assert (ipos == 0);
- return isc_merge_first (is, data);
+ char i_item[128], *i_item_ptr;
+ int i_more, i_mode, i;
+
+ ISAMC_PP pp;
+ char f_item[128], *f_item_ptr;
+ int f_more;
+ int block_ptr[100]; /* block pointer (0 if none) */
+ int dirty_ptr[100]; /* dirty flag pointer (1 if dirty) */
+
+ int firstpos = 0;
+ int nextpos = 0;
+ int cat = 0;
+ char r_item_buf[128]; /* temporary result output */
+ char *r_buf; /* block with resulting data */
+ int r_offset = 0; /* current offset in r_buf */
+ int r_ptr[100]; /* offset pointer */
+ int r_ptri = 0; /* pointer */
+ void *r_clientData; /* encode client data */
+
+ if (ipos == 0)
+ return isc_merge_first (is, data);
+
+ r_clientData = (*is->method->code_start)(ISAMC_ENCODE);
+ r_buf = is->r_buf + ISAMC_BLOCK_OFFSET;
+
+ pp = isc_pp_open (is, ipos);
+ f_item_ptr = f_item;
+ f_more = isc_read_item (pp, &f_item_ptr);
+ cat = pp->cat;
+
+ /* read first item from i */
+ i_item_ptr = i_item;
+ i_more = (*data->read_item)(data->clientData, &i_item_ptr, &i_mode);
+ block_ptr[r_ptri] = pp->pos;
+ dirty_ptr[r_ptri] = 0;
+ r_ptr[r_ptri++] = 0;
+
+ while (i_more || f_more)
+ {
+ char *r_item = r_item_buf;
+ int cmp;
+
+ if (!f_more)
+ cmp = -1;
+ else if (!i_more)
+ cmp = 1;
+ else
+ cmp = (*is->method->compare_item)(i_item, f_item);
+ if (cmp == 0) /* insert i=f */
+ {
+ if (!i_mode)
+ {
+ r_item = NULL;
+ dirty_ptr[r_ptri-1] = 1;
+ }
+ else
+ memcpy (r_item, f_item, f_item_ptr - f_item);
+
+ /* move i */
+ i_item_ptr = i_item;
+ i_more = (*data->read_item)(data->clientData, &i_item_ptr,
+ &i_mode);
+ /* move f */
+ f_item_ptr = f_item;
+ f_more = isc_read_item (pp, &f_item_ptr);
+ }
+ else if (cmp > 0) /* insert f */
+ {
+ memcpy (r_item, f_item, f_item_ptr - f_item);
+ /* move f */
+ f_item_ptr = f_item;
+ f_more = isc_read_item (pp, &f_item_ptr);
+ }
+ else /* insert i */
+ {
+ if (!i_mode) /* delete item which isn't there? */
+ {
+ logf (LOG_FATAL, "Inconsistent register");
+ abort ();
+ }
+ memcpy (r_item, i_item, i_item_ptr - i_item);
+ dirty_ptr[r_ptri-1] = 1;
+ /* move i */
+ i_item_ptr = i_item;
+ i_more = (*data->read_item)(data->clientData, &i_item_ptr,
+ &i_mode);
+ }
+ if (r_item) /* insert resulting item? */
+ {
+ char *r_out_ptr = r_buf + r_offset;
+ int new_offset;
+ int border;
+
+ /* border set to initial fill or block size depending on
+ whether we are creating a new one or updating and old
+ */
+ if (block_ptr[r_ptri-1])
+ border = r_ptr[r_ptri-1] + is->method->filecat[cat].bsize
+ -ISAMC_BLOCK_OFFSET;
+ else
+ border = r_ptr[r_ptri-1] + is->method->filecat[cat].ifill
+ -ISAMC_BLOCK_OFFSET;
+
+ (*is->method->code_item)(ISAMC_ENCODE, r_clientData,
+ &r_out_ptr, &r_item);
+ new_offset = r_out_ptr - r_buf;
+
+ if (border >= r_offset && border < new_offset)
+ {
+ /* Initial fill of current block category reached...
+ Save offset in r_ptr
+ */
+ r_ptr[r_ptri++] = r_offset;
+ if (cat == is->max_cat)
+ {
+ /* We are dealing with block of max size. Block(s)
+ will be flushed. Note: the block(s) are surely not
+ the last one(s).
+ */
+ if (is->method->debug > 1)
+ logf (LOG_LOG, "isc: flush %d sections", r_ptri-1);
+ isc_flush_blocks (is, r_ptr, r_ptri, r_buf,
+ &nextpos, &firstpos, cat, 0);
+ r_ptri = 0;
+ r_ptr[r_ptri++] = 0;
+ memcpy (r_buf, r_buf + r_offset, new_offset - r_offset);
+ new_offset = (new_offset - r_offset);
+ }
+ }
+ r_offset = new_offset;
+ if (cat < is->max_cat &&
+ r_ptri>is->method->filecat[cat].mblocks)
+ {
+ /* Max number blocks in current category reached ->
+ must switch to next category (with larger block size)
+ */
+ int j = 1;
+ cat++;
+ /* r_ptr[0] = r_ptr[0] = 0 true anyway.. */
+ /* AD: Any old blocks should be deleted */
+ for (i = 2; i < r_ptri; i++)
+ {
+ border = is->method->filecat[cat].ifill -
+ ISAMC_BLOCK_OFFSET + r_ptr[j-1];
+ if (r_ptr[i] > border && r_ptr[i-1] <= border)
+ r_ptr[j++] = r_ptr[i-1];
+ }
+ r_ptri = j;
+ }
+ }
+ }
+ r_ptr[r_ptri++] = r_offset;
+ /* flush rest of block(s) in r_buf */
+ if (is->method->debug > 1)
+ logf (LOG_LOG, "isc: flush rest, %d sections", r_ptri-1);
+ isc_flush_blocks (is, r_ptr, r_ptri, r_buf, &nextpos, &firstpos, cat, 1);
+ (*is->method->code_stop)(ISAMC_ENCODE, r_clientData);
+ return cat + firstpos * 8;
}
{
ISAMC_PP pp = xmalloc (sizeof(*pp));
char *src;
-
- isc_catpos (ipos, &pp->cat, &pp->next);
+
+ pp->cat = isc_type(ipos);
+ pp->next = isc_block(ipos);
src = pp->buf = xmalloc (is->method->filecat[pp->cat].bsize);