home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
DOOG
/
CBASE09.ZIP
/
BTREE.ZIP
/
BTOPS.C
< prev
next >
Wrap
Text File
|
1989-08-31
|
12KB
|
514 lines
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* #ident "btops.c 1.1 - 89/07/03" */
#include <blkio.h>
#include <bool.h>
#include <errno.h>
/* #include <stdlib.h> */
/* #include <string.h> */
#include "btree_.h"
/*man---------------------------------------------------------------------------
NAME
bt_alloc - allocate memory for a btree
SYNOPSIS
#include "btree_.h"
int bt_alloc(btp);
btree_t *btp;
DESCRIPTION
The bt_alloc function allocates the memory needed by btree btp. The
storage is initialized to 0.
bt_alloc will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[ENOMEM] Not enough memory is available for the
calling process to allocate.
[BTENOPEN] btp is not open.
SEE ALSO
bt_free.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
int bt_alloc(btp)
btree_t *btp;
{
errno = 0;
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return -1;
}
#endif
/* free any previously allocated storage */
bt_free(btp);
/* search path */
btp->sp = (btpos_t *)calloc(btp->bthdr.height + 1, sizeof(btpos_t));
if (btp->sp == NULL) {
BTEPRINT;
errno = ENOMEM;
return -1;
}
/* current node */
btp->cbtnp = bt_ndalloc(btp);
if (btp->cbtnp == NULL) {
BTEPRINT;
free((void *)btp->sp);
return -1;
}
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_blksize - btree block size
SYNOPSIS
#include <btree.h>
void *bt_blksize(btp)
btree_t *btp;
DESCRIPTION
bt_blksize returns the size of the blocks in btree btp. If btp is not
a valid open btree, the results are undefined. bt_blksize is a macro.
------------------------------------------------------------------------------*/
/* bt_blksize #defined in btree_.h. */
/*man---------------------------------------------------------------------------
NAME
bt_free - free memory allocated for a btree
SYNOPSIS
#include "btree_.h"
void bt_free(btp)
btree_t *btp;
DESCRIPTION
The bt_free function frees all memory allocated for btree btp. If
btp is not a valid btree, no action is taken.
SEE ALSO
bt_alloc.
------------------------------------------------------------------------------*/
void bt_free(btp)
btree_t *btp;
{
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
return;
}
#endif
/* free memory */
if (btp->sp != NULL) {
free(btp->sp);
btp->sp = NULL;
}
bt_ndfree(btp->cbtnp);
btp->cbtnp = NULL;
return;
}
/*man---------------------------------------------------------------------------
NAME
bt_grow - btree grow
SYNOPSIS
#include "btree_.h"
int bt_grow(btp, bttuple_p)
btree_t *btp;
bttuple_t *bttuple_p;
DESCRIPTION
The bt_grow function creates a new root for btree btp and inserts
the (key, child) tuple pointed to by bttuple_p into it. This
increases the tree height by one. This is the only way that the
height can increase.
bt_grow will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] bttuple_p is the NULL pointer.
[BTENOPEN] btp is not open.
SEE ALSO
bt_shrink.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
int bt_grow(btp, bttuple_p)
btree_t * btp;
bttuple_t * bttuple_p;
{
int rs = 0;
int terrno = 0;
bpos_t oldroot = 0;
bpos_t newroot = 0;
btpos_t * sp = NULL;
btnode_t * btnp = NULL;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if ((!bt_valid(btp)) || (bttuple_p == NULL)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return -1;
}
#endif
/* pop node off of free list stack */
rs = bflpop(btp->bp, &newroot);
if (rs == -1) {
BTEPRINT;
return -1;
}
/* modify header in memory */
oldroot = btp->bthdr.root;
btp->bthdr.root = newroot;
btp->bthdr.height++;
/* add slot to search path */
btp->sp[0].node = newroot;
btp->sp[0].key = 1;
sp = (btpos_t *)calloc(btp->bthdr.height + 1, sizeof(btpos_t));
if (sp == NULL) {
BTEPRINT;
btp->bthdr.root = oldroot;
btp->bthdr.height--;
bflpush(btp->bp, &newroot);
errno = ENOMEM;
return -1;
}
memcpy((void *)(sp + 1), (void *)btp->sp, btp->bthdr.height * sizeof(btpos_t));
free((void *)btp->sp);
btp->sp = sp;
sp = NULL;
/* write new root to file */
btnp = bt_ndalloc(btp);
if (btnp == NULL) {
BTEPRINT;
terrno = errno;
btp->bthdr.root = oldroot;
btp->bthdr.height--;
bflpush(btp->bp, &newroot);
errno = terrno;
return -1;
}
memcpy(bt_kychild_p(btnp, 0), (void *)&oldroot, sizeof(bpos_t));
rs = bt_ndinskey(btp, btnp, (size_t)1, bttuple_p);
if (rs == -1) {
BTEPRINT;
terrno = errno;
bt_ndfree(btnp);
btp->bthdr.root = oldroot;
btp->bthdr.height--;
bflpush(btp->bp, &newroot);
errno = terrno;
return -1;
}
rs = bt_ndput(btp, newroot, btnp);
if (rs == -1) {
BTEPRINT;
terrno = errno;
bt_ndfree(btnp);
btp->bthdr.root = oldroot;
btp->bthdr.height--;
bflpush(btp->bp, &newroot);
errno = terrno;
return -1;
}
bt_ndfree(btnp);
/* update first and last key positions */
if (oldroot == 0) {
btp->bthdr.first = btp->bthdr.last = newroot;
}
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_search - search a btree
SYNOPSIS
#include <btree.h>
int bt_search(btp, buf)
btree_t *btp;
void *buf;
DESCRIPTION
The bt_search function searches the btree btp for the key pointed to
by buf. If it is found, the cursor is set to the location of the key
and 1 is returned. If it is not found, the cursor is set to the
location at which it should be inserted and 0 is returned.
bt_search will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[EINVAL] buf is the NULL pointer.
[BTELOCK] btp is not read locked.
DIAGNOSTICS
Upon successful completion, a value of 1 is returned if the key was
found or a value of 0 if it was not found. On failure, a value of
-1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
int bt_search(btp, buf)
btree_t * btp;
void * buf;
{
int rs = 0;
int spi = 0; /* search path index */
bpos_t node = 0;
int found = 0;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
errno = EINVAL;
return -1;
}
if (buf == NULL) {
errno = EINVAL;
return -1;
}
/* check locks */
if (!(btp->flags & BTRDLCK)) {
errno = BTELOCK;
return -1;
}
#endif
/* initialize btree structure for search */
btp->cbtpos.node = 0; /* initialize cursor */
btp->cbtpos.key = 0;
btp->sp[0].node = 0; /* initialize search path root */
btp->sp[0].key = 0;
/* search loop */
node = btp->bthdr.root;
for (spi = 1; (spi <= btp->bthdr.height); spi++) {
if (node == 0) {
BTEPRINT; /* height value probably incorrect */
bt_ndinit(btp, btp->cbtnp);
errno = BTEPANIC;
return -1;
}
btp->sp[spi].node = node;
rs = bt_ndget(btp, node, btp->cbtnp);
if (rs == -1) {
BTEPRINT;
bt_ndinit(btp, btp->cbtnp);
return -1;
}
found = bt_ndsearch(btp, btp->cbtnp, buf, &btp->sp[spi].key);
if (found == -1) {
BTEPRINT;
bt_ndinit(btp, btp->cbtnp);
return -1;
}
if (found == 0) { /* go down left subtree */
node = *bt_kychild_p(btp->cbtnp, btp->sp[spi].key - 1);
} else { /* go down right subtree */
node = *bt_kychild_p(btp->cbtnp, btp->sp[spi].key);
}
}
if (node != 0) {
BTEPRINT; /* height value probably incorrect */
bt_ndinit(btp, btp->cbtnp);
errno = BTEPANIC;
return -1;
}
/* set cursor */
btp->cbtpos.node = btp->sp[btp->bthdr.height].node;
btp->cbtpos.key = btp->sp[btp->bthdr.height].key;
errno = 0;
return ((found == 1) ? 1: 0);
}
/*man---------------------------------------------------------------------------
NAME
bt_shrink - btree shrink
SYNOPSIS
#include "btree_.h"
int bt_shrink(btp, newroot)
btree_t *btp;
bpos_t newroot;
DESCRIPTION
The bt_shrink function makes newroot the new root for btree btp
and puts the old root back in the free list. This decreases the
tree height by one. This is the only way that the height can
decrease.
bt_shrink will fail if one or more of the following is true:
[EINVAL] btp is not a valid btree pointer.
[BTEPANIC] btp is already empty.
SEE ALSO
bt_grow.
DIAGNOSTICS
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned, and errno set to indicate the error.
------------------------------------------------------------------------------*/
int bt_shrink(btp, newroot)
btree_t * btp;
bpos_t newroot;
{
int rs = 0;
int terrno = 0;
bpos_t oldroot = 0;
btpos_t * sp = NULL;
errno = 0;
#ifdef DEBUG
/* validate arguments */
if (!bt_valid(btp)) {
BTEPRINT;
errno = EINVAL;
return -1;
}
/* check if not open */
if (!(btp->flags & BTOPEN)) {
BTEPRINT;
errno = BTENOPEN;
return -1;
}
#endif
/* check if tree already empty */
if (btp->bthdr.root == 0) {
BTEPRINT;
errno = BTEPANIC;
return -1;
}
/* modify header in memory */
oldroot = btp->bthdr.root;
btp->bthdr.root = newroot;
btp->bthdr.height--;
/* remove slot from search path */
sp = (btpos_t *)calloc(btp->bthdr.height + 1, sizeof(btpos_t));
if (sp == NULL) {
BTEPRINT;
btp->bthdr.root = oldroot;
btp->bthdr.height++;
errno = ENOMEM;
return -1;
}
memcpy((void *)(sp + 1), (void *)(btp->sp + 2), btp->bthdr.height * sizeof(btpos_t));
free((void *)btp->sp);
btp->sp = sp;
sp = NULL;
/* push root back onto free list stack */
rs = bflpush(btp->bp, &oldroot);
if (rs == -1) {
BTEPRINT;
btp->bthdr.root = oldroot;
btp->bthdr.height++;
return -1;
}
/* update first and last key positions */
if (newroot == 0) {
btp->bthdr.first = btp->bthdr.last = 0;
}
errno = 0;
return 0;
}
/*man---------------------------------------------------------------------------
NAME
bt_valid - validate btree
SYNOPSIS
#include "btree_.h"
bool bt_valid(btp)
btree_t *btp;
DESCRIPTION
The bt_valid function determines if btp points to a valid btree
control structure. If it is valid, TRUE is returned. If not,
then FALSE is returned.
------------------------------------------------------------------------------*/
bool bt_valid(btp)
btree_t *btp;
{
if ((btp < btb) || (btp > (btb + BTOPEN_MAX - 1))) {
return FALSE;
}
if (((size_t)((char *)btp - (char *)btb)) % sizeof(btb[0]) != 0) {
return FALSE;
}
return TRUE;
}