📄 btdemo.cpp
字号:
/* Copyright (c) 1989 Citadel */
/* All Rights Reserved */
/* #ident "@(#)btdemo.c 1.4 - 90/06/20" */
#include <blkio.h>
#include <errno.h>
#include <btree.h>
#include <ctype.h>
#include <stdio.h>
#ifdef AC_HDRS
#include <stdlib.h>
#include <string.h>
#else
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS (0)
#define EXIT_FAILURE (1)
void *memmove(t, s, n)
void *t;
void *s;
size_t n;
{
void *buf = NULL;
if ((buf = calloc((size_t)1, n)) == NULL) return NULL;
memcpy(buf, s, n);
memcpy(t, buf, n);
free(buf);
return t;
}
#endif
#endif
#ifdef AC_PROTO
int bdlock(btree_t *btp, int ltype);
int putmenu(void);
#else
int bdlock();
int putmenu();
#endif
/* comparison function */
int cmp(p1, p2, n)
const void *p1;
const void *p2;
size_t n;
{
return strncmp((char *)p1, (char *)p2, n);
}
/* constants */
#define LMAXTRIES 100 /* maximum lock tries */
#define USAGE ("Usage: btdemo filename keysize")
/* btdemo user requests */
#define REQ_NEXT ('N') /* next */
#define REQ_PREV ('P') /* previous */
#define REQ_FIRST ('F') /* first */
#define REQ_LAST ('L') /* last */
#define REQ_INS ('I') /* insert */
#define REQ_DEL ('D') /* delete */
#define REQ_SRCH ('S') /* search */
#define REQ_CUR ('C') /* current */
#define REQ_ALL ('A') /* all */
#define REQ_MENU ('M') /* help */
#define REQ_QUIT ('Q') /* quit */
/*man---------------------------------------------------------------------------
NAME
btdemo - btree demonstration program
SYNOPSIS
btdemo filename keysize
DESCRIPTION
btdemo is a demonstration program for the btree library. It
allows interactive direct access to a btree with keys having a
single field of string data sorted by strncmp in ascending order.
SEE ALSO
btdump, btlist, btree.
WARNING
btdemo should be used only on btrees with keys having a single
field of string data sorted by strncmp in ascending order. Use
on other btrees will produce unpredictable results and corrupt
the file if modifications are attempted.
------------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
btree_t * btp = NULL; /* btree pointer */
char buf[256]; /* input buffer */
char * endp = NULL; /* pointer for strtol fct */
char filename[FILENAME_MAX + 1]; /* btree file name */
int fldc = 1; /* field count */
btfield_t fldv[1]; /* field definition list */
int found = 0; /* key found flag */
void * key = NULL; /* key */
long keylen = 0; /* strtol return */
size_t keysize = 0; /* key size */
const int m = 4; /* btree order */
int rq = 0; /* user request */
/* process command line options and arguments */
--argc; /* filename argument */
++argv;
if (argc < 1) {
puts(USAGE);
bexit(EXIT_FAILURE);
}
strncpy(filename, *argv, sizeof(filename));
filename[sizeof(filename) - 1] = NUL;
--argc; /* key size argument */
++argv;
if (argc < 1) {
puts(USAGE);
bexit(EXIT_FAILURE);
}
errno = 0;
keylen = strtol(*argv, &endp, 10);
if (errno == ERANGE) {
puts("btdemo: keysize argument out of range.");
puts(USAGE);
bexit(EXIT_FAILURE);
}
if (endp != NULL) {
if (endp[0] != NUL) {
puts(USAGE);
bexit(EXIT_FAILURE);
}
}
if (keylen < 1) {
puts(USAGE);
bexit(EXIT_FAILURE);
}
keysize = keylen;
if (argc != 1) {
puts(USAGE);
bexit(EXIT_FAILURE);
}
/* open btree */
fldc = 1;
fldv[0].offset = 0;
fldv[0].len = keysize;
fldv[0].cmp = cmp;
fldv[0].flags = BT_FASC;
btp = btopen(filename, "r+", fldc, fldv);
if (btp == NULL) {
if (errno != ENOENT) {
fprintf(stderr, "*** Error %d opening btree.\n", errno);
bexit(EXIT_FAILURE);
}
printf("btree %s does not exist. Creating.\n\n", filename);
if (btcreate(filename, m, keysize, fldc, fldv) == -1) {
fprintf(stderr, "*** Error %d creating btree.\n", errno);
bexit(EXIT_FAILURE);
}
btp = btopen(filename, "r+", fldc, fldv);
if (btp == NULL) {
fprintf(stderr, "*** Error %d opening btree.\n", errno);
bexit(EXIT_FAILURE);
}
}
if (keysize != btkeysize(btp)) {
printf("Incorrect keysize. Keysize for this btree is %lu.\n", (unsigned long)btkeysize(btp));
bexit(EXIT_FAILURE);
}
/* allocate key storage */
key = calloc(btkeysize(btp), (size_t)1);
if (key == NULL) {
fprintf(stderr, "Insufficient memory for key.\n");
bexit(EXIT_FAILURE);
}
puts("\n--------------------------------------------------");
puts("| btree Library Demo Program |");
puts("--------------------------------------------------\n");
putmenu();
/* main loop */
for (;;) {
fputs("Enter selection: ", stdout);
fgets(buf, (int)sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n') {
buf[strlen(buf) - 1] = NUL;
}
/* add string library function to extract leading spaces */
rq = toupper(*buf);
if (rq == REQ_QUIT) { /* quit btdemo */
break;
}
if (rq == NUL) { /* default to next key */
rq = REQ_NEXT;
}
if (rq == 'X') {
if (bt_dgbtree(btp, btp->bthdr.root, stdout) == -1) {
perror("bt_dgbtree");
exit(1);
}
continue;
}
switch (rq) {
case REQ_NEXT: /* next key */
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
if (btkeycnt(btp) == 0) {
printf("The btree is empty.\n\n");
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break;
}
found = btsearch(btp, key);
if (found == -1) {
fprintf(stderr, "*** Error %d searching for key.\n", errno);
bexit(EXIT_FAILURE);
}
if (found == 1) {
if (btnext(btp) == -1) {
fprintf(stderr, "*** Error %d finding next key.\n", errno);
bexit(EXIT_FAILURE);
}
}
if (btcursor(btp) == NULL) {
puts("On last key.\n");
} else {
if (btgetk(btp, key) == -1) {
fprintf(stderr, "*** Error %d reading key.\n", errno);
bexit(EXIT_FAILURE);
}
printf("The next key is %s.\n\n", (char *)key);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_NEXT: */
case REQ_PREV: /* previous key */
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
if (btkeycnt(btp) == 0) {
puts("The btree is empty.\n");
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break;
}
found = btsearch(btp, key);
if (found == -1) {
fprintf(stderr, "*** Error %d searching for key.\n", errno);
bexit(EXIT_FAILURE);
}
if (found == 1) {
if (btprev(btp) == -1) {
fprintf(stderr, "*** Error %d finding previous key.\n", errno);
bexit(EXIT_FAILURE);
}
}
if (btcursor(btp) == NULL) {
puts("On first key.\n");
} else {
if (btgetk(btp, key) == -1) {
fprintf(stderr, "*** Error %d reading key.\n", errno);
bexit(EXIT_FAILURE);
}
printf("The previous key is %s.\n\n", (char *)key);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_PREV: */
case REQ_FIRST: /* first key */
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
if (btkeycnt(btp) == 0) {
puts("The btree is empty.\n");
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break;
}
if (btfirst(btp) == -1) {
fprintf(stderr, "*** Error %d finding first key.\n", errno);
bexit(EXIT_FAILURE);
}
if (btgetk(btp, key) == -1) {
fprintf(stderr, "*** Error %d reading key.\n", errno);
bexit(EXIT_FAILURE);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
printf("The first key is %s.\n\n", (char *)key);
break; /* case REQ_FIRST: */
case REQ_LAST: /* last key */
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
if (btkeycnt(btp) == 0) {
puts("The btree is empty.\n");
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break;
}
if (btlast(btp) == -1) {
fprintf(stderr, "*** Error %d finding last key.\n", errno);
bexit(EXIT_FAILURE);
}
if (btgetk(btp, key) == -1) {
fprintf(stderr, "*** Error %d reading key.\n", errno);
bexit(EXIT_FAILURE);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
printf("The last key is %s.\n", (char *)key);
break; /* case REQ_LAST: */
case REQ_INS: /* insert key */
printf("Enter key to insert: ");
memset(key, 0, btkeysize(btp));
fgets(buf, (int)sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n') {
buf[strlen(buf) - 1] = NUL;
}
strncpy((char *)key, buf, btkeysize(btp));
((char *)key)[btkeysize(btp) - 1] = NUL;
if (bdlock(btp, BT_WRLCK) == -1) {
fprintf(stderr, "*** Error %d write locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
if (btinsert(btp, key) == -1) {
if (errno == BTEDUP) {
printf("%s is already in the btree.\n\n", (char *)key);
} else {
fprintf(stderr, "*** Error %d inserting key into btree.\n", errno);
bexit(EXIT_FAILURE);
}
} else {
printf("%s inserted in btree.\n\n", (char *)key);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_INS: */
case REQ_DEL: /* delete key */
fputs("Enter key to delete: ", stdout);
memset(key, 0, btkeysize(btp));
fgets(buf, (int)sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n') {
buf[strlen(buf) - 1] = NUL;
}
strncpy((char *)key, buf, btkeysize(btp));
((char *)key)[btkeysize(btp) - 1] = NUL;
if (bdlock(btp, BT_WRLCK) == -1) {
fprintf(stderr, "*** Error %d write locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
if (btdelete(btp, key) == -1) {
if (errno == BTENKEY) {
printf("%s not found.\n\n", (char *)key);
} else {
fprintf(stderr, "*** Error %d deleting key.\n", errno);
bexit(EXIT_FAILURE);
}
} else {
printf("%s deleted from btree.\n\n", (char *)key);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_DEL: */
case REQ_SRCH: /* search for key */
fputs("Enter search key: ", stdout);
memset(key, 0, btkeysize(btp));
fgets(buf, (int)sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n') {
buf[strlen(buf) - 1] = NUL;
}
strncpy((char *)key, buf, btkeysize(btp));
((char *)key)[btkeysize(btp) - 1] = NUL;
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
found = btsearch(btp, key);
if (found == -1) {
fprintf(stderr, "*** Error %d searching for key.\n", errno);
bexit(EXIT_FAILURE);
}
if (found == 1) {
printf("%s found.\n", (char *)key);
} else {
printf("%s not found.\n", (char *)key);
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_SRCH: */
case REQ_CUR: /* current key */
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
found = btsearch(btp, key);
if (found == -1) {
fprintf(stderr, "*** Error %d searching for key.\n", errno);
bexit(EXIT_FAILURE);
}
if (found == 1) {
printf("Current key: %s.\n", (char *)key);
} else {
printf("No current key.\n");
}
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_CUR: */
case REQ_ALL: /* list all keys */
if (bdlock(btp, BT_RDLCK) == -1) {
fprintf(stderr, "*** Error %d read locking btree.\n", errno);
bexit(EXIT_FAILURE);
}
printf("There are %lu keys in the btree.\n\n", btkeycnt(btp));
if (btsetcur(btp, NULL) == -1) {
fprintf(stderr, "*** Error %d setting cursor.\n", errno);
bexit(EXIT_FAILURE);
}
for (;;) {
if (btnext(btp) == -1) {
fprintf(stderr, "*** Error %d finding next key.\n", errno);
bexit(EXIT_FAILURE);
}
if (btcursor(btp) == NULL) {
break;
}
if (btgetk(btp, key) == -1) {
fprintf(stderr, "*** Error %d reading key.\n", errno);
bexit(EXIT_FAILURE);
}
puts((char *)key);
}
putchar((int)'\n');
if (bdlock(btp, BT_UNLCK) == -1) {
fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
bexit(EXIT_FAILURE);
}
break; /* case REQ_ALL: */
case REQ_MENU: /* menu */
putmenu();
break; /* case REQ_MENU: */
default:
printf("Invalid selection.\a\n");
break; /* default: */
}
}
/* close btree */
if (btclose(btp) == -1) {
fprintf(stderr, "*** Error %d closing btree.\n", errno);
bexit(EXIT_FAILURE);
}
bexit(EXIT_SUCCESS);
}
/* bdlock: btdemo lock */
int bdlock(btp, ltype)
btree_t *btp;
int ltype;
{
int i = 0;
for (i = 0; i < LMAXTRIES; ++i) {
if (btlock(btp, ltype) == -1) {
if (errno == EAGAIN) {
continue;
}
return -1;
} else {
errno = 0;
return 0;
}
}
errno = EAGAIN;
return -1;
}
/* putmenu: display menu */
int putmenu()
{
puts("-----------------------MENU-----------------------");
puts("| N - Next key P - Previous key |");
puts("| F - First key L - Last key |");
puts("| I - Insert key D - Delete key |");
puts("| S - Search for key C - Current key |");
puts("| A - display All keys |");
puts("| M - Menu Q - Quit |");
puts("--------------------------------------------------");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -