+ if (sub_p2)
+ {
+ char dst_buf[2048];
+ char *dst = dst_buf;
+
+ assert (sub_size < 20);
+
+ memcpy (dst, startp, src - startp);
+
+ dst += src - startp;
+
+ encode_ptr (&dst, sub_size); /* sub length and item */
+ memcpy (dst, sub_item, sub_size);
+ dst += sub_size;
+
+ encode_ptr (&dst, sub_p2->pos); /* pos */
+
+ if (endp - src) /* remaining data */
+ {
+ memcpy (dst, src, endp - src);
+ dst += endp - src;
+ }
+ p->size = dst - dst_buf + ISAMB_DATA_OFFSET;
+ if (p->size <= b->head.block_size)
+ {
+ memcpy (startp, dst_buf, dst - dst_buf);
+ }
+ else
+ {
+ int p_new_size;
+ char *half;
+ src = dst_buf;
+ endp = dst;
+
+ half = src + b->head.block_size/2;
+ decode_ptr (&src, &pos);
+ while (src <= half)
+ {
+ decode_ptr (&src, split_size);
+ src += *split_size;
+ decode_ptr (&src, &pos);
+ }
+ p_new_size = src - dst_buf;
+ memcpy (p->bytes + ISAMB_DATA_OFFSET, dst_buf, p_new_size);
+ p_new_size += ISAMB_DATA_OFFSET;
+
+ decode_ptr (&src, split_size);
+ memcpy (split_item, src, *split_size);
+ src += *split_size;
+
+ *sp = new_block (b, 0);
+ (*sp)->size = endp - src;
+ memcpy ((*sp)->bytes+ISAMB_DATA_OFFSET, src, (*sp)->size);
+ (*sp)->size += ISAMB_DATA_OFFSET;
+
+ yaz_log (LOG_LOG, "i split %d -> %d %d",
+ p->size, p_new_size, (*sp)->size);
+ p->size = p_new_size;
+ }
+ p->dirty = 1;
+ close_block (b, sub_p2);
+ }
+ close_block (b, sub_p1);
+}
+
+void insert_sub (ISAMB b, struct ISAMB_block *p, const void *new_item,
+ struct ISAMB_block **sp,
+ void *sub_item, int *sub_size)
+{
+ if (p->leaf)
+ insert_leaf (b, p, new_item, sp, sub_item, sub_size);
+ else
+ insert_int (b, p, new_item, sp, sub_item, sub_size);
+}
+
+int isamb_insert_one (ISAMB b, const void *item, ISAMC_P pos)
+{
+ struct ISAMB_block *p, *sp = 0;
+ char sub_item[256];
+ int sub_size;
+
+ if (!pos)
+ p = new_block (b, 1);
+ else
+ p = open_block (b, pos);
+ if (!p)
+ return -1;
+
+ insert_sub (b, p, item, &sp, sub_item, &sub_size);
+ if (sp)
+ { /* increase level of tree by one */
+ struct ISAMB_block *p2 = new_block (b, 0);
+ char *dst = p2->bytes + p2->size;
+
+ encode_ptr (&dst, p->pos);
+ assert (sub_size < 20);
+ encode_ptr (&dst, sub_size);
+ memcpy (dst, sub_item, sub_size);
+ dst += sub_size;
+ encode_ptr (&dst, sp->pos);
+
+ p2->size = dst - (char*) p2->bytes;
+ pos = p2->pos; /* return new super page */
+ close_block (b, sp);
+ close_block (b, p2);
+ }
+ else
+ pos = p->pos; /* return current one (again) */
+ close_block (b, p);
+ return pos;
+}
+
+ISAMB_P isamb_merge (ISAMB b, ISAMB_P pos, ISAMC_I data)
+{
+ int i_mode;
+ char item_buf[256];
+ char *item_ptr = item_buf;
+ while ((*data->read_item)(data->clientData, &item_ptr, &i_mode))
+ {
+ item_ptr = item_buf;
+ pos = isamb_insert_one (b, item_buf, pos);
+ }
+ return pos;
+}
+
+ISAMB_PP isamb_pp_open (ISAMB isamb, ISAMB_P pos)
+{
+ ISAMB_PP pp = xmalloc (sizeof(*pp));
+
+ pp->isamb = isamb;
+ pp->block = xmalloc (10 * sizeof(*pp->block));
+
+ pp->level = 0;
+ while (1)
+ {
+ struct ISAMB_block *p = open_block (isamb, pos);
+ char *src = p->bytes + p->offset;
+ pp->block[pp->level] = p;
+
+ if (p->bytes[0]) /* leaf */
+ break;
+
+ decode_ptr (&src, &pos);
+ p->offset = src - (char*) p->bytes;
+ pp->level++;
+ }
+ pp->block[pp->level+1] = 0;
+ return pp;
+}
+
+void isamb_pp_close (ISAMB_PP pp)
+{
+ int i;
+ if (!pp)
+ return;
+ for (i = 0; i <= pp->level; i++)
+ close_block (pp->isamb, pp->block[i]);
+ xfree (pp->block);
+ xfree (pp);
+}
+
+int isamb_pp_read (ISAMB_PP pp, void *buf)
+{
+ char *dst = buf;
+ char *src;
+ struct ISAMB_block *p = pp->block[pp->level];
+ if (!p)
+ return 0;
+
+ while (p->offset == p->size)
+ {
+ int pos, item_len;
+ while (p->offset == p->size)
+ {
+ if (pp->level == 0)
+ return 0;
+ close_block (pp->isamb, pp->block[pp->level]);
+ pp->block[pp->level] = 0;
+ (pp->level)--;
+ p = pp->block[pp->level];
+ assert (p->bytes[0] == 0); /* must be int */
+ }
+ src = p->bytes + p->offset;
+
+ decode_ptr (&src, &item_len);
+ src += item_len;
+ decode_ptr (&src, &pos);
+
+ p->offset = src - (char*) p->bytes;
+
+ ++(pp->level);
+
+ while (1)
+ {
+ pp->block[pp->level] = p = open_block (pp->isamb, pos);
+
+ if (p->bytes[0]) /* leaf */
+ {
+ break;
+ }
+ src = p->bytes + p->offset;
+ decode_ptr (&src, &pos);
+ p->offset = src - (char*) p->bytes;
+ pp->level++;
+ }
+ }
+ assert (p->offset < p->size);
+ assert (p->bytes[0]);
+ src = p->bytes + p->offset;
+ (*pp->isamb->method->code_item)(ISAMC_DECODE, p->decodeClientData,
+ &dst, &src);
+ p->offset = src - (char*) p->bytes;
+ return 1;
+}
+
+int isamb_pp_num (ISAMB_PP pp)
+{
+ return 1;