|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*----------------------------------------------------------------------------*
|
|
Toshihiro Shimizu |
890ddd |
| |
|
|
Toshihiro Shimizu |
890ddd |
| avl.c |
|
|
Toshihiro Shimizu |
890ddd |
| |
|
|
Toshihiro Shimizu |
890ddd |
| by W.T. 11-MAR-91, last revision 11-OCT-96 |
|
|
Toshihiro Shimizu |
890ddd |
| |
|
|
Toshihiro Shimizu |
890ddd |
*----------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
9f5a1b |
#ifdef _WIN32
|
|
Toshihiro Shimizu |
890ddd |
#pragma warning(push)
|
|
Toshihiro Shimizu |
890ddd |
#pragma warning(disable : 4113)
|
|
Toshihiro Shimizu |
890ddd |
#pragma warning(disable : 4996)
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <stdio.h></stdio.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <stdlib.h></stdlib.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <string.h></string.h>
|
|
Toshihiro Shimizu |
890ddd |
#define AVL_C
|
|
Toshihiro Shimizu |
890ddd |
#include "avl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcm.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef TRUE
|
|
Toshihiro Shimizu |
890ddd |
#define TRUE 1
|
|
Toshihiro Shimizu |
890ddd |
#define FALSE 0
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//#define NIL ((void *)0)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef unsigned long ulong;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifndef MACOSX
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef unsigned int uint;
|
|
Toshihiro Shimizu |
890ddd |
typedef unsigned short ushort;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef struct avl_node NODE;
|
|
Toshihiro Shimizu |
890ddd |
typedef struct avl_path PATH;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define MBR_KEY (AVL_NODUP_MBR >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define PTR_KEY (AVL_NODUP_PTR >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define STR_KEY (AVL_NODUP_STR >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define LNG_KEY (AVL_NODUP_LNG >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define INT_KEY (AVL_NODUP_INT >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define SHT_KEY (AVL_NODUP_SHT >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define ULN_KEY (AVL_NODUP_ULN >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define UIN_KEY (AVL_NODUP_UIN >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define USH_KEY (AVL_NODUP_USH >> 1)
|
|
Toshihiro Shimizu |
890ddd |
#define CHR_KEY (AVL_NODUP_CHR >> 1)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define USR_CMP 0
|
|
Toshihiro Shimizu |
890ddd |
#define STR_CMP 1
|
|
Toshihiro Shimizu |
890ddd |
#define VAL_CMP 2
|
|
Toshihiro Shimizu |
890ddd |
#define COR_CMP 3
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NODUP 0
|
|
Toshihiro Shimizu |
890ddd |
#define DUP 1
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define USR_NODUP (USR_CMP | NODUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define STR_NODUP (STR_CMP | NODUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define VAL_NODUP (VAL_CMP | NODUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define COR_NODUP (COR_CMP | NODUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define USR_DUP (USR_CMP | DUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define STR_DUP (STR_CMP | DUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define VAL_DUP (VAL_CMP | DUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
#define COR_DUP (COR_CMP | DUP << 2)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* keyinfo: bits 6-3: KEYTYPE, bit 2: DUP, bits 1-0: CMPTYPE */
|
|
Toshihiro Shimizu |
890ddd |
/* bits 6-2: TREETYPE, bits 2-0: LOCTYPE */
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define KEYTYPE(keyinfo) ((keyinfo) >> 3)
|
|
Toshihiro Shimizu |
890ddd |
#define TREETYPE(keyinfo) ((keyinfo) >> 2)
|
|
Toshihiro Shimizu |
890ddd |
#define CMPTYPE(keyinfo) ((keyinfo)&0x3)
|
|
Toshihiro Shimizu |
890ddd |
#define LOCTYPE(keyinfo) ((keyinfo)&0x7)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define MAXUSHORT (((unsigned short)(~0)) >> 1)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define MINLONG ((long)~(((unsigned long)(~0L)) >> 1))
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define CORRECT(u) ((long)(u) + MINLONG)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef VAX
|
|
Shinya Kitaoka |
120a6e |
#define SET_STRCMP(cmp, str1, str2) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
char *p1, *p2; \
|
|
Shinya Kitaoka |
120a6e |
for (p1 = (str1), p2 = (str2); *p1 && *p1 == *p2; p1++, p2++) \
|
|
Shinya Kitaoka |
120a6e |
; \
|
|
Shinya Kitaoka |
120a6e |
(cmp) = *(unsigned char *)p1 - *(unsigned char *)p2; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Shinya Kitaoka |
120a6e |
#define SET_STRCMP(cmp, str1, str2) \
|
|
Shinya Kitaoka |
120a6e |
{ (cmp) = strcmp((str1), (str2)); }
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#define SET_PTRCMP(cmp, usrcmp, ptr1, ptr2) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (usrcmp) \
|
|
Shinya Kitaoka |
120a6e |
(cmp) = (*(usrcmp))((ptr1), (ptr2)); \
|
|
Shinya Kitaoka |
120a6e |
else \
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP((cmp), (char *)(ptr1), (char *)(ptr2)) \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define ERROR (-1)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define BAL 0
|
|
Toshihiro Shimizu |
890ddd |
#define LEFT 1
|
|
Toshihiro Shimizu |
890ddd |
#define RIGHT 2
|
|
Toshihiro Shimizu |
890ddd |
#define LEFTUNBAL 3
|
|
Toshihiro Shimizu |
890ddd |
#define RIGHTUNBAL 4
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define LESS 3
|
|
Toshihiro Shimizu |
890ddd |
#define SAME 4
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NOTINS 0
|
|
Toshihiro Shimizu |
890ddd |
#define INS 1
|
|
Toshihiro Shimizu |
890ddd |
#define DEEPER 2
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define NODE_LIST 0
|
|
Toshihiro Shimizu |
890ddd |
#define TREE_LIST (NODE_LIST + (sizeof(NODE) != sizeof(TREE)))
|
|
Toshihiro Shimizu |
890ddd |
#define PATH_LIST (TREE_LIST + 1)
|
|
Toshihiro Shimizu |
890ddd |
#define FREE_LISTS (PATH_LIST + 1)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#define LONG_ALIGNED_SIZE(obj) \
|
|
Shinya Kitaoka |
120a6e |
((sizeof(obj) + sizeof(long) - 1) & ~(sizeof(long) - 1))
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define SIZEOF_NODE LONG_ALIGNED_SIZE(NODE)
|
|
Toshihiro Shimizu |
890ddd |
#define SIZEOF_TREE LONG_ALIGNED_SIZE(TREE)
|
|
Toshihiro Shimizu |
890ddd |
#define SIZEOF_PATH LONG_ALIGNED_SIZE(PATH)
|
|
Toshihiro Shimizu |
890ddd |
#define SIZEOF_LONG sizeof(long)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define PREALLOC_LONGS (0x7FF0 / SIZEOF_LONG)
|
|
Toshihiro Shimizu |
890ddd |
#define PREALLOC_SIZE (PREALLOC_LONGS * SIZEOF_LONG)
|
|
Toshihiro Shimizu |
890ddd |
#define MALLOC_LONGS (0x7FE0 / SIZEOF_LONG)
|
|
Toshihiro Shimizu |
890ddd |
#define MALLOC_SIZE (MALLOC_LONGS * SIZEOF_LONG)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static long Prealloc[PREALLOC_LONGS];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static void *Free_List[FREE_LISTS]; /* init to 0 by C */
|
|
Toshihiro Shimizu |
890ddd |
static char *Avail_Base = (char *)Prealloc;
|
|
Shinya Kitaoka |
120a6e |
static uint Avail_Size = PREALLOC_SIZE;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void *new_memory(uint size) {
|
|
Shinya Kitaoka |
120a6e |
char *base;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (Avail_Size >= SIZEOF_NODE) {
|
|
Shinya Kitaoka |
120a6e |
base = Avail_Base + (Avail_Size -= SIZEOF_NODE);
|
|
Shinya Kitaoka |
120a6e |
*(void **)base = Free_List[NODE_LIST];
|
|
Shinya Kitaoka |
120a6e |
Free_List[NODE_LIST] = (void *)base;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if ((Avail_Base = (char *)malloc(MALLOC_SIZE))) {
|
|
Shinya Kitaoka |
120a6e |
Avail_Size = MALLOC_SIZE - size;
|
|
Shinya Kitaoka |
120a6e |
return (void *)(Avail_Base + Avail_Size);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
Avail_Size = 0;
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#define ALLOC_OBJ(ptr, ptr_type, size, list) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (Free_List[list]) { \
|
|
Shinya Kitaoka |
120a6e |
(ptr) = (ptr_type)Free_List[list]; \
|
|
Shinya Kitaoka |
120a6e |
Free_List[list] = *(void **)(ptr); \
|
|
Shinya Kitaoka |
120a6e |
} else if (Avail_Size >= size) \
|
|
Shinya Kitaoka |
120a6e |
(ptr) = (ptr_type)(Avail_Base + (Avail_Size -= size)); \
|
|
Shinya Kitaoka |
120a6e |
else \
|
|
Shinya Kitaoka |
120a6e |
(ptr) = (ptr_type)new_memory(size); \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define FREE_OBJ(ptr, list) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
*(void **)(ptr) = Free_List[list]; \
|
|
Shinya Kitaoka |
120a6e |
Free_List[list] = (void *)(ptr); \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define ALLOC_NODE(node) ALLOC_OBJ(node, NODE *, SIZEOF_NODE, NODE_LIST)
|
|
Toshihiro Shimizu |
890ddd |
#define ALLOC_TREE(tree) ALLOC_OBJ(tree, TREE *, SIZEOF_TREE, TREE_LIST)
|
|
Toshihiro Shimizu |
890ddd |
#define ALLOC_PATH(path) ALLOC_OBJ(path, PATH *, SIZEOF_PATH, PATH_LIST)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define FREE_NODE(node) FREE_OBJ(node, NODE_LIST)
|
|
Toshihiro Shimizu |
890ddd |
#define FREE_TREE(tree) FREE_OBJ(tree, TREE_LIST)
|
|
Toshihiro Shimizu |
890ddd |
#define FREE_PATH(path) FREE_OBJ(path, PATH_LIST)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TREE *avl__tree(int treetype, uint keyoffs, int (*usrcmp)(void *, void *)) {
|
|
Shinya Kitaoka |
120a6e |
TREE *tree;
|
|
Shinya Kitaoka |
120a6e |
int keyinfo;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
keyinfo = treetype << 2;
|
|
Shinya Kitaoka |
120a6e |
switch (treetype) {
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_MBR:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_MBR:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= USR_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_PTR:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_PTR:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= USR_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_STR:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_STR:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= STR_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_LNG:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_LNG:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= VAL_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_INT:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_INT:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= VAL_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_SHT:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_SHT:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= VAL_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_ULN:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_ULN:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= COR_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_UIN:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_UIN:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= COR_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_USH:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_USH:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= VAL_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case AVL_NODUP_CHR:
|
|
Shinya Kitaoka |
120a6e |
case AVL_DUP_CHR:
|
|
Shinya Kitaoka |
120a6e |
keyinfo |= VAL_CMP;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ALLOC_TREE(tree)
|
|
Shinya Kitaoka |
120a6e |
if (!tree) return NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->root = NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->keyinfo = (ushort)keyinfo;
|
|
Shinya Kitaoka |
120a6e |
tree->keyoffs = (ushort)keyoffs;
|
|
Shinya Kitaoka |
120a6e |
tree->usrcmp = usrcmp;
|
|
Shinya Kitaoka |
120a6e |
tree->nodes = 0L;
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return tree;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static int rebalance(NODE **rootaddr) {
|
|
Shinya Kitaoka |
120a6e |
NODE *root = *rootaddr;
|
|
Shinya Kitaoka |
120a6e |
NODE *newroot;
|
|
Shinya Kitaoka |
120a6e |
NODE *half;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFTUNBAL:
|
|
Shinya Kitaoka |
120a6e |
switch (root->left->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT: /* simple rotation, tree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
newroot = root->left;
|
|
Shinya Kitaoka |
120a6e |
root->left = newroot->right;
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
newroot->right = root;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = newroot;
|
|
Shinya Kitaoka |
120a6e |
return LESS;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
case BAL: /* simple rotation, tree depth unchanged */
|
|
Shinya Kitaoka |
120a6e |
newroot = root->left;
|
|
Shinya Kitaoka |
120a6e |
root->left = newroot->right;
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
newroot->right = root;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = newroot;
|
|
Shinya Kitaoka |
120a6e |
return SAME;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
case RIGHT: /* double rotation */
|
|
Shinya Kitaoka |
120a6e |
half = root->left;
|
|
Shinya Kitaoka |
120a6e |
newroot = half->right;
|
|
Shinya Kitaoka |
120a6e |
root->left = newroot->right;
|
|
Shinya Kitaoka |
120a6e |
half->right = newroot->left;
|
|
Shinya Kitaoka |
120a6e |
switch (newroot->bal) {
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
half->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
half->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
half->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
newroot->left = half;
|
|
Shinya Kitaoka |
120a6e |
newroot->right = root;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = newroot;
|
|
Shinya Kitaoka |
120a6e |
return LESS;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHTUNBAL:
|
|
Shinya Kitaoka |
120a6e |
switch (root->right->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT: /* simple rotation, tree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
newroot = root->right;
|
|
Shinya Kitaoka |
120a6e |
root->right = newroot->left;
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
newroot->left = root;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = newroot;
|
|
Shinya Kitaoka |
120a6e |
return LESS;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
case BAL: /* simple rotation, tree depth unchanged */
|
|
Shinya Kitaoka |
120a6e |
newroot = root->right;
|
|
Shinya Kitaoka |
120a6e |
root->right = newroot->left;
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
newroot->left = root;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = newroot;
|
|
Shinya Kitaoka |
120a6e |
return SAME;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
case LEFT: /* double rotation */
|
|
Shinya Kitaoka |
120a6e |
half = root->right;
|
|
Shinya Kitaoka |
120a6e |
newroot = half->left;
|
|
Shinya Kitaoka |
120a6e |
root->right = newroot->left;
|
|
Shinya Kitaoka |
120a6e |
half->left = newroot->right;
|
|
Shinya Kitaoka |
120a6e |
switch (newroot->bal) {
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
half->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
half->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
half->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
newroot->right = half;
|
|
Shinya Kitaoka |
120a6e |
newroot->left = root;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = newroot;
|
|
Shinya Kitaoka |
120a6e |
return LESS;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
return SAME;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return ERROR;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static int insert_ptr(NODE **rootaddr, NODE *node,
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *), int dup) {
|
|
Shinya Kitaoka |
120a6e |
NODE *root = *rootaddr;
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
int ins;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
SET_PTRCMP(cmp, usrcmp, node->key.ptr, root->key.ptr)
|
|
Shinya Kitaoka |
120a6e |
if (cmp < 0) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left)
|
|
Shinya Kitaoka |
120a6e |
ins = insert_ptr(&root->left, node, usrcmp, dup);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
root->left = node;
|
|
Shinya Kitaoka |
120a6e |
ins = DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
switch (ins) {
|
|
Shinya Kitaoka |
120a6e |
case DEEPER:
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
return DEEPER;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
return rebalance(rootaddr) == LESS ? INS : DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case INS:
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case NOTINS:
|
|
Shinya Kitaoka |
120a6e |
return NOTINS;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (cmp > 0 || dup) {
|
|
Shinya Kitaoka |
120a6e |
if (root->right)
|
|
Shinya Kitaoka |
120a6e |
ins = insert_ptr(&root->right, node, usrcmp, dup);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
root->right = node;
|
|
Shinya Kitaoka |
120a6e |
ins = DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
switch (ins) {
|
|
Shinya Kitaoka |
120a6e |
case DEEPER:
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
return DEEPER;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
return rebalance(rootaddr) == LESS ? INS : DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case INS:
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case NOTINS:
|
|
Shinya Kitaoka |
120a6e |
return NOTINS;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return NOTINS;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static int insert_val(NODE **rootaddr, NODE *node, int dup) {
|
|
Shinya Kitaoka |
120a6e |
NODE *root = *rootaddr;
|
|
Shinya Kitaoka |
120a6e |
int ins;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (node->key.val < root->key.val) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left)
|
|
Shinya Kitaoka |
120a6e |
ins = insert_val(&root->left, node, dup);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
root->left = node;
|
|
Shinya Kitaoka |
120a6e |
ins = DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
switch (ins) {
|
|
Shinya Kitaoka |
120a6e |
case DEEPER:
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
return DEEPER;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
return rebalance(rootaddr) == LESS ? INS : DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case INS:
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case NOTINS:
|
|
Shinya Kitaoka |
120a6e |
return NOTINS;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (node->key.val > root->key.val || dup) {
|
|
Shinya Kitaoka |
120a6e |
if (root->right) {
|
|
Shinya Kitaoka |
120a6e |
ins = insert_val(&root->right, node, dup);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
root->right = node;
|
|
Shinya Kitaoka |
120a6e |
ins = DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
switch (ins) {
|
|
Shinya Kitaoka |
120a6e |
case DEEPER:
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
return DEEPER;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
return rebalance(rootaddr) == LESS ? INS : DEEPER;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
case INS:
|
|
Shinya Kitaoka |
120a6e |
return INS;
|
|
Shinya Kitaoka |
120a6e |
case NOTINS:
|
|
Shinya Kitaoka |
120a6e |
return NOTINS;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return NOTINS;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int avl_insert(TREE *tree, void *data) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
int keyinfo;
|
|
Shinya Kitaoka |
120a6e |
int ins;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ALLOC_NODE(node)
|
|
Shinya Kitaoka |
120a6e |
if (!node) return FALSE;
|
|
Shinya Kitaoka |
120a6e |
node->data = data;
|
|
Shinya Kitaoka |
120a6e |
node->left = NIL;
|
|
Shinya Kitaoka |
120a6e |
node->right = NIL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
keyinfo = tree->keyinfo;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
switch (KEYTYPE(keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case MBR_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.ptr = (void *)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case PTR_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.ptr = *(void **)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.ptr = *(void **)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LNG_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = *(long *)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case INT_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = *(int *)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case SHT_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = *(short *)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case ULN_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = CORRECT(*(ulong *)((char *)data + tree->keyoffs));
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case UIN_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = CORRECT(*(uint *)((char *)data + tree->keyoffs));
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USH_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = *(ushort *)((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case CHR_KEY:
|
|
Shinya Kitaoka |
120a6e |
node->key.val = *((char *)data + tree->keyoffs);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(node)
|
|
Shinya Kitaoka |
120a6e |
return FALSE;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) {
|
|
Shinya Kitaoka |
120a6e |
switch (LOCTYPE(keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
ins = insert_ptr(&tree->root, node, tree->usrcmp, NODUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
ins = insert_ptr(&tree->root, node, AVL_AVLCMP, NODUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
case VAL_NODUP:
|
|
Shinya Kitaoka |
120a6e |
ins = insert_val(&tree->root, node, NODUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USR_DUP:
|
|
Shinya Kitaoka |
120a6e |
ins = insert_ptr(&tree->root, node, tree->usrcmp, DUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_DUP:
|
|
Shinya Kitaoka |
120a6e |
ins = insert_ptr(&tree->root, node, AVL_AVLCMP, DUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_DUP:
|
|
Shinya Kitaoka |
120a6e |
case VAL_DUP:
|
|
Shinya Kitaoka |
120a6e |
ins = insert_val(&tree->root, node, DUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (ins == NOTINS) {
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(node)
|
|
Shinya Kitaoka |
120a6e |
return FALSE;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
tree->root = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
tree->nodes++;
|
|
Shinya Kitaoka |
120a6e |
if (tree->path) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(tree->path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return TRUE;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_EQ_NODUP(node, val, this) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (this < val) \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
else if (val < this) \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
else \
|
|
Shinya Kitaoka |
120a6e |
return node->data; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_EQ_DUP(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (this < val) \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
else if (val < this) \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
else { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
} \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_GE_NODUP(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (val < this) { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
} else if (this < val) \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
else \
|
|
Shinya Kitaoka |
120a6e |
return node->data; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_GE_DUP(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (this < val) \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
else { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
} \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_GT(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (val < this) { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
} else \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_LE_NODUP(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (this < val) { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
} else if (val < this) \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
else \
|
|
Shinya Kitaoka |
120a6e |
return node->data; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_LE_DUP(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (val < this) \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
else { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
} \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define SELECT_LT(node, val, this, save) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if (this < val) { \
|
|
Shinya Kitaoka |
120a6e |
save = node; \
|
|
Shinya Kitaoka |
120a6e |
node = node->right; \
|
|
Shinya Kitaoka |
120a6e |
} else \
|
|
Shinya Kitaoka |
120a6e |
node = node->left; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__locate(TREE *tree, long keyval) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
NODE *save;
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *);
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
switch (LOCTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_EQ_NODUP(node, cmp, 0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_EQ_NODUP(node, cmp, 0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_NODUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_EQ_NODUP(node, keyval, node->key.val);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USR_DUP:
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_EQ_DUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (save) {
|
|
Shinya Kitaoka |
120a6e |
return save->data;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_DUP:
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_EQ_DUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (save) {
|
|
Shinya Kitaoka |
120a6e |
return save->data;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_DUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_DUP:
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_EQ_DUP(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (save) {
|
|
Shinya Kitaoka |
120a6e |
return save->data;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__locate_ge(TREE *tree, long keyval) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
NODE *save;
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *);
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
switch (LOCTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_GE_NODUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_GE_NODUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_NODUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_GE_NODUP(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USR_DUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_GE_DUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_DUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_GE_DUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_DUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_DUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_GE_DUP(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return save ? save->data : NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__locate_gt(TREE *tree, long keyval) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
NODE *save;
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *);
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
switch (CMPTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_CMP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_GT(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_CMP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_GT(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_CMP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_CMP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_GT(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return save ? save->data : NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__locate_le(TREE *tree, long keyval) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
NODE *save;
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *);
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
switch (LOCTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_LE_NODUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_LE_NODUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_NODUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_LE_NODUP(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USR_DUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_LE_DUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_DUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_LE_DUP(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_DUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_DUP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_LE_DUP(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return save ? save->data : NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__locate_lt(TREE *tree, long keyval) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
NODE *save;
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *);
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
save = NIL;
|
|
Shinya Kitaoka |
120a6e |
switch (CMPTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_CMP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
cmp = (*usrcmp)((void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_LT(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_CMP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SET_STRCMP(cmp, (char *)keyval, (char *)node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
SELECT_LT(node, cmp, 0, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_CMP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_CMP:
|
|
Shinya Kitaoka |
120a6e |
while (node) {
|
|
Shinya Kitaoka |
120a6e |
SELECT_LT(node, keyval, node->key.val, save);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return save ? save->data : NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl_locate_first(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node, *leftnode;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
if (!node) return NIL;
|
|
Shinya Kitaoka |
120a6e |
while ((leftnode = node->left)) node = leftnode;
|
|
Shinya Kitaoka |
120a6e |
return node->data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl_locate_last(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node, *rightnode;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
if (!node) return NIL;
|
|
Shinya Kitaoka |
120a6e |
while ((rightnode = node->right)) node = rightnode;
|
|
Shinya Kitaoka |
120a6e |
return node->data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static NODE *leftmost(NODE **rootaddr) {
|
|
Shinya Kitaoka |
120a6e |
NODE *root = *rootaddr;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (root) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left) {
|
|
Shinya Kitaoka |
120a6e |
node = leftmost(&root->left);
|
|
Shinya Kitaoka |
120a6e |
if (node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* left subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return node;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = root->right;
|
|
Shinya Kitaoka |
120a6e |
root->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
return root;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static NODE *remove_ptr(NODE **rootaddr, void *keyptr,
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *), int dup) {
|
|
Shinya Kitaoka |
120a6e |
NODE *root = *rootaddr;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
SET_PTRCMP(cmp, usrcmp, keyptr, root->key.ptr)
|
|
Shinya Kitaoka |
120a6e |
if (cmp < 0) {
|
|
Shinya Kitaoka |
120a6e |
if (!root->left) return NIL;
|
|
Shinya Kitaoka |
120a6e |
node = remove_ptr(&root->left, keyptr, usrcmp, dup);
|
|
Shinya Kitaoka |
120a6e |
if (node && node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* left subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (cmp > 0) {
|
|
Shinya Kitaoka |
120a6e |
if (!root->right) return NIL;
|
|
Shinya Kitaoka |
120a6e |
node = remove_ptr(&root->right, keyptr, usrcmp, dup);
|
|
Shinya Kitaoka |
120a6e |
if (node && node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* right subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (dup && root->left &&
|
|
Shinya Kitaoka |
120a6e |
(node = remove_ptr(&root->left, keyptr, usrcmp, dup))) {
|
|
Shinya Kitaoka |
120a6e |
if (node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* left subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
node = root;
|
|
Shinya Kitaoka |
120a6e |
if (!node->right) {
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = node->left;
|
|
Shinya Kitaoka |
120a6e |
node->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
} else if (!node->left) {
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = node->right;
|
|
Shinya Kitaoka |
120a6e |
node->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
} else /* replace by the leftmost node of the right subtree */
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
root = leftmost(&node->right);
|
|
Shinya Kitaoka |
120a6e |
root->left = node->left;
|
|
Shinya Kitaoka |
120a6e |
root->right = node->right;
|
|
Shinya Kitaoka |
120a6e |
if (root->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* right subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (node->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(&root);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
root->bal = node->bal;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = root;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return node;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static NODE *remove_val(NODE **rootaddr, long keyval, int dup) {
|
|
Shinya Kitaoka |
120a6e |
NODE *root = *rootaddr;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (keyval < root->key.val) {
|
|
Shinya Kitaoka |
120a6e |
if (!root->left) return NIL;
|
|
Shinya Kitaoka |
120a6e |
node = remove_val(&root->left, keyval, dup);
|
|
Shinya Kitaoka |
120a6e |
if (node && node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* left subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (keyval > root->key.val) {
|
|
Shinya Kitaoka |
120a6e |
if (!root->right) return NIL;
|
|
Shinya Kitaoka |
120a6e |
node = remove_val(&root->right, keyval, dup);
|
|
Shinya Kitaoka |
120a6e |
if (node && node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* right subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (dup && root->left && (node = remove_val(&root->left, keyval, dup))) {
|
|
Shinya Kitaoka |
120a6e |
if (node->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* left subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (root->bal) {
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = RIGHTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(rootaddr);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
node = root;
|
|
Shinya Kitaoka |
120a6e |
if (!node->right) {
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = node->left;
|
|
Shinya Kitaoka |
120a6e |
node->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
} else if (!node->left) {
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = node->right;
|
|
Shinya Kitaoka |
120a6e |
node->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
} else /* replace by the leftmost node of the right subtree */
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
root = leftmost(&node->right);
|
|
Shinya Kitaoka |
120a6e |
root->left = node->left;
|
|
Shinya Kitaoka |
120a6e |
root->right = node->right;
|
|
Shinya Kitaoka |
120a6e |
if (root->bal == LESS) {
|
|
Shinya Kitaoka |
120a6e |
/* right subtree depth decreased */
|
|
Shinya Kitaoka |
120a6e |
switch (node->bal) {
|
|
Shinya Kitaoka |
120a6e |
case RIGHT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = BAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = LESS;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case BAL:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFT;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case LEFT:
|
|
Shinya Kitaoka |
120a6e |
root->bal = LEFTUNBAL;
|
|
Shinya Kitaoka |
120a6e |
node->bal = rebalance(&root);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
root->bal = node->bal;
|
|
Shinya Kitaoka |
120a6e |
node->bal = SAME;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*rootaddr = root;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return node;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__remove(TREE *tree, long keyval) {
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
void *data;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) {
|
|
Shinya Kitaoka |
120a6e |
switch (LOCTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
node = remove_ptr(&tree->root, (void *)keyval, tree->usrcmp, NODUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
node = remove_ptr(&tree->root, (void *)keyval, AVL_AVLCMP, NODUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_NODUP:
|
|
Shinya Kitaoka |
120a6e |
node = remove_val(&tree->root, keyval, NODUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USR_DUP:
|
|
Shinya Kitaoka |
120a6e |
node = remove_ptr(&tree->root, (void *)keyval, tree->usrcmp, DUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case STR_DUP:
|
|
Shinya Kitaoka |
120a6e |
node = remove_ptr(&tree->root, (void *)keyval, AVL_AVLCMP, DUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_DUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_DUP:
|
|
Shinya Kitaoka |
120a6e |
node = remove_val(&tree->root, keyval, DUP);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (node) {
|
|
Shinya Kitaoka |
120a6e |
tree->nodes--;
|
|
Shinya Kitaoka |
120a6e |
if (tree->path) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(tree->path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
data = node->data;
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(node)
|
|
Shinya Kitaoka |
120a6e |
return data;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void scan_subtree(NODE *root, void (*usrfun)(void *)) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left) scan_subtree(root->left, usrfun);
|
|
Shinya Kitaoka |
120a6e |
(*usrfun)(root->data);
|
|
Shinya Kitaoka |
120a6e |
if (root->right) scan_subtree(root->right, usrfun);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void backscan_subtree(NODE *root, void (*usrfun)(void *)) {
|
|
Shinya Kitaoka |
120a6e |
if (root->right) backscan_subtree(root->right, usrfun);
|
|
Shinya Kitaoka |
120a6e |
(*usrfun)(root->data);
|
|
Shinya Kitaoka |
120a6e |
if (root->left) backscan_subtree(root->left, usrfun);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void avl__scan(TREE *tree, void (*usrfun)(void *), int back) {
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) {
|
|
Shinya Kitaoka |
120a6e |
if (back)
|
|
Shinya Kitaoka |
120a6e |
backscan_subtree(tree->root, usrfun);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
scan_subtree(tree->root, usrfun);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl_first(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
PATH *path;
|
|
Shinya Kitaoka |
120a6e |
char *pathright;
|
|
Shinya Kitaoka |
120a6e |
NODE **pathnode;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!tree->root) return NIL;
|
|
Shinya Kitaoka |
120a6e |
if (!tree->path) {
|
|
Shinya Kitaoka |
120a6e |
ALLOC_PATH(path)
|
|
Shinya Kitaoka |
120a6e |
if (!path) return NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->path = path;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
path = tree->path;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
pathnode = &path->node[0];
|
|
Shinya Kitaoka |
120a6e |
pathright = &path->right[1];
|
|
Shinya Kitaoka |
120a6e |
*pathnode = NIL; /* sentinels */
|
|
Shinya Kitaoka |
120a6e |
*pathright = TRUE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = NIL;
|
|
Shinya Kitaoka |
120a6e |
*++pathright = FALSE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
while ((node = node->left)) {
|
|
Shinya Kitaoka |
120a6e |
*++pathright = FALSE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
path->pathright = pathright;
|
|
Shinya Kitaoka |
120a6e |
path->pathnode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
return (*pathnode)->data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl_last(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
PATH *path;
|
|
Shinya Kitaoka |
120a6e |
char *pathright;
|
|
Shinya Kitaoka |
120a6e |
NODE **pathnode;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!tree->root) return NIL;
|
|
Shinya Kitaoka |
120a6e |
if (!tree->path) {
|
|
Shinya Kitaoka |
120a6e |
ALLOC_PATH(path)
|
|
Shinya Kitaoka |
120a6e |
if (!path) return NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->path = path;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
path = tree->path;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
pathnode = &path->node[0];
|
|
Shinya Kitaoka |
120a6e |
pathright = &path->right[1];
|
|
Shinya Kitaoka |
120a6e |
*pathnode = NIL; /* sentinels */
|
|
Shinya Kitaoka |
120a6e |
*pathright = FALSE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = NIL;
|
|
Shinya Kitaoka |
120a6e |
*++pathright = TRUE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
while ((node = node->right)) {
|
|
Shinya Kitaoka |
120a6e |
*++pathright = TRUE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
path->pathright = pathright;
|
|
Shinya Kitaoka |
120a6e |
path->pathnode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
return (*pathnode)->data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#define DOWN_RIGHT_OR_BREAK(node, pathright, pathnode) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if ((node = node->right)) { \
|
|
Shinya Kitaoka |
120a6e |
*++pathright = TRUE; \
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node; \
|
|
Shinya Kitaoka |
120a6e |
} else \
|
|
Shinya Kitaoka |
120a6e |
break; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define DOWN_LEFT_OR_BREAK(node, pathright, pathnode) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
if ((node = node->left)) { \
|
|
Shinya Kitaoka |
120a6e |
*++pathright = FALSE; \
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node; \
|
|
Shinya Kitaoka |
120a6e |
} else \
|
|
Shinya Kitaoka |
120a6e |
break; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define START_OK_AND_RETURN(path, _pathright, _pathnode) \
|
|
Shinya Kitaoka |
120a6e |
{ \
|
|
Shinya Kitaoka |
120a6e |
path->pathright = _pathright; \
|
|
Shinya Kitaoka |
120a6e |
path->pathnode = _pathnode; \
|
|
Shinya Kitaoka |
120a6e |
return (*_pathnode)->data; \
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__start(TREE *tree, long keyval, int back) {
|
|
Shinya Kitaoka |
120a6e |
PATH *path;
|
|
Shinya Kitaoka |
120a6e |
char *pathright;
|
|
Shinya Kitaoka |
120a6e |
NODE **pathnode;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
char *saveright;
|
|
Shinya Kitaoka |
120a6e |
NODE **savenode;
|
|
Shinya Kitaoka |
120a6e |
int (*usrcmp)(void *, void *);
|
|
Shinya Kitaoka |
120a6e |
int cmp;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!tree->root) return NIL;
|
|
Shinya Kitaoka |
120a6e |
if (!tree->path) {
|
|
Shinya Kitaoka |
120a6e |
ALLOC_PATH(path)
|
|
Shinya Kitaoka |
120a6e |
if (!path) return NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->path = path;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
path = tree->path;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
pathnode = &path->node[0];
|
|
Shinya Kitaoka |
120a6e |
pathright = &path->right[1];
|
|
Shinya Kitaoka |
120a6e |
saveright = NIL;
|
|
Shinya Kitaoka |
120a6e |
savenode = NIL;
|
|
Shinya Kitaoka |
120a6e |
*pathnode = NIL; /* sentinels */
|
|
Shinya Kitaoka |
120a6e |
*pathright = !back;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = NIL;
|
|
Shinya Kitaoka |
120a6e |
*++pathright = back;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node = tree->root;
|
|
Shinya Kitaoka |
120a6e |
switch (LOCTYPE(tree->keyinfo)) {
|
|
Shinya Kitaoka |
120a6e |
case USR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
case STR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
if (back) {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
SET_PTRCMP(cmp, usrcmp, (void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
if (cmp > 0) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else if (cmp < 0) {
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
START_OK_AND_RETURN(path, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
SET_PTRCMP(cmp, usrcmp, (void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
if (cmp < 0) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else if (cmp > 0) {
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
START_OK_AND_RETURN(path, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_NODUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_NODUP:
|
|
Shinya Kitaoka |
120a6e |
if (back) {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
if (keyval > node->key.val) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else if (keyval < node->key.val) {
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
START_OK_AND_RETURN(path, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
if (keyval < node->key.val) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else if (keyval > node->key.val) {
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
START_OK_AND_RETURN(path, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case USR_DUP:
|
|
Shinya Kitaoka |
120a6e |
case STR_DUP:
|
|
Shinya Kitaoka |
120a6e |
usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
if (back) {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
SET_PTRCMP(cmp, usrcmp, (void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
if (cmp >= 0) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
SET_PTRCMP(cmp, usrcmp, (void *)keyval, node->key.ptr);
|
|
Shinya Kitaoka |
120a6e |
if (cmp <= 0) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case COR_DUP:
|
|
Shinya Kitaoka |
120a6e |
keyval = CORRECT(keyval);
|
|
Shinya Kitaoka |
120a6e |
// fallthrough
|
|
Shinya Kitaoka |
120a6e |
case VAL_DUP:
|
|
Shinya Kitaoka |
120a6e |
if (back) {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
if (keyval >= node->key.val) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
if (keyval <= node->key.val) {
|
|
Shinya Kitaoka |
120a6e |
saveright = pathright;
|
|
Shinya Kitaoka |
120a6e |
savenode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
DOWN_LEFT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
DOWN_RIGHT_OR_BREAK(node, pathright, pathnode);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (savenode) {
|
|
Shinya Kitaoka |
120a6e |
path->pathright = saveright;
|
|
Shinya Kitaoka |
120a6e |
path->pathnode = savenode;
|
|
Shinya Kitaoka |
120a6e |
return (*savenode)->data;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl_next(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
PATH *path;
|
|
Shinya Kitaoka |
120a6e |
char *pathright;
|
|
Shinya Kitaoka |
120a6e |
NODE **pathnode;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
path = tree->path;
|
|
Shinya Kitaoka |
120a6e |
if (!path) return NIL;
|
|
Shinya Kitaoka |
120a6e |
pathright = path->pathright;
|
|
Shinya Kitaoka |
120a6e |
pathnode = path->pathnode;
|
|
Shinya Kitaoka |
120a6e |
if ((node = (*pathnode)->right)) {
|
|
Shinya Kitaoka |
120a6e |
*++pathright = TRUE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node;
|
|
Shinya Kitaoka |
120a6e |
while ((node = node->left)) {
|
|
Shinya Kitaoka |
120a6e |
*++pathright = FALSE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
while (*pathright) {
|
|
Shinya Kitaoka |
120a6e |
--pathright;
|
|
Shinya Kitaoka |
120a6e |
--pathnode;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
--pathright;
|
|
Shinya Kitaoka |
120a6e |
--pathnode;
|
|
Shinya Kitaoka |
120a6e |
if (!*pathnode) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
path->pathright = pathright;
|
|
Shinya Kitaoka |
120a6e |
path->pathnode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
return (*pathnode)->data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl_prev(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
PATH *path;
|
|
Shinya Kitaoka |
120a6e |
char *pathright;
|
|
Shinya Kitaoka |
120a6e |
NODE **pathnode;
|
|
Shinya Kitaoka |
120a6e |
NODE *node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
path = tree->path;
|
|
Shinya Kitaoka |
120a6e |
if (!path) return NIL;
|
|
Shinya Kitaoka |
120a6e |
pathright = path->pathright;
|
|
Shinya Kitaoka |
120a6e |
pathnode = path->pathnode;
|
|
Shinya Kitaoka |
120a6e |
if ((node = (*pathnode)->left)) {
|
|
Shinya Kitaoka |
120a6e |
*++pathright = FALSE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node;
|
|
Shinya Kitaoka |
120a6e |
while ((node = node->right)) {
|
|
Shinya Kitaoka |
120a6e |
*++pathright = TRUE;
|
|
Shinya Kitaoka |
120a6e |
*++pathnode = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
while (!*pathright) {
|
|
Shinya Kitaoka |
120a6e |
--pathright;
|
|
Shinya Kitaoka |
120a6e |
--pathnode;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
--pathright;
|
|
Shinya Kitaoka |
120a6e |
--pathnode;
|
|
Shinya Kitaoka |
120a6e |
if (!*pathnode) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
path->pathright = pathright;
|
|
Shinya Kitaoka |
120a6e |
path->pathnode = pathnode;
|
|
Shinya Kitaoka |
120a6e |
return (*pathnode)->data;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void avl_stop(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
if (tree->path) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(tree->path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static uint Offset;
|
|
Toshihiro Shimizu |
890ddd |
static void *Save;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void link_subtree(NODE *node) {
|
|
Shinya Kitaoka |
120a6e |
if (node->right) link_subtree(node->right);
|
|
Shinya Kitaoka |
120a6e |
*(void **)((char *)node->data + Offset) = Save;
|
|
Shinya Kitaoka |
120a6e |
Save = node->data;
|
|
Shinya Kitaoka |
120a6e |
if (node->left) link_subtree(node->left);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void backlink_subtree(NODE *node) {
|
|
Shinya Kitaoka |
120a6e |
if (node->left) backlink_subtree(node->left);
|
|
Shinya Kitaoka |
120a6e |
*(void **)((char *)node->data + Offset) = Save;
|
|
Shinya Kitaoka |
120a6e |
Save = node->data;
|
|
Shinya Kitaoka |
120a6e |
if (node->right) backlink_subtree(node->right);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void *avl__link(TREE *tree, uint ptroffs, int back) {
|
|
Shinya Kitaoka |
120a6e |
Offset = ptroffs;
|
|
Shinya Kitaoka |
120a6e |
Save = NIL;
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) {
|
|
Shinya Kitaoka |
120a6e |
if (back)
|
|
Shinya Kitaoka |
120a6e |
backlink_subtree(tree->root);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
link_subtree(tree->root);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return Save;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void release_subtree(NODE *root, void (*usrfun)(void *)) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left) release_subtree(root->left, usrfun);
|
|
Shinya Kitaoka |
120a6e |
if (root->right) release_subtree(root->right, usrfun);
|
|
Shinya Kitaoka |
120a6e |
(*usrfun)(root->data);
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(root)
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void reset_subtree(NODE *root) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left) reset_subtree(root->left);
|
|
Shinya Kitaoka |
120a6e |
if (root->right) reset_subtree(root->right);
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(root)
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void avl_release(TREE *tree, void (*usrfun)(void *)) {
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) release_subtree(tree->root, usrfun);
|
|
Shinya Kitaoka |
120a6e |
tree->root = NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->nodes = 0;
|
|
Shinya Kitaoka |
120a6e |
if (tree->path) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(tree->path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void avl_reset(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) reset_subtree(tree->root);
|
|
Shinya Kitaoka |
120a6e |
tree->root = NIL;
|
|
Shinya Kitaoka |
120a6e |
tree->nodes = 0;
|
|
Shinya Kitaoka |
120a6e |
if (tree->path) {
|
|
Shinya Kitaoka |
120a6e |
FREE_PATH(tree->path)
|
|
Shinya Kitaoka |
120a6e |
tree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void avl_close(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) reset_subtree(tree->root);
|
|
Shinya Kitaoka |
120a6e |
if (tree->path) FREE_PATH(tree->path)
|
|
Shinya Kitaoka |
120a6e |
tree->keyinfo = (ushort)ERROR;
|
|
Shinya Kitaoka |
120a6e |
FREE_TREE(tree)
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static int copy_subtree(NODE *newroot, NODE *root) {
|
|
Shinya Kitaoka |
120a6e |
newroot->key = root->key;
|
|
Shinya Kitaoka |
120a6e |
newroot->data = root->data;
|
|
Shinya Kitaoka |
120a6e |
newroot->bal = root->bal;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (root->left) {
|
|
Shinya Kitaoka |
120a6e |
ALLOC_NODE(newroot->left)
|
|
Shinya Kitaoka |
120a6e |
if (!newroot->left) return FALSE;
|
|
Shinya Kitaoka |
120a6e |
if (!copy_subtree(newroot->left, root->left)) {
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(newroot->left);
|
|
Shinya Kitaoka |
120a6e |
return FALSE;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
newroot->left = NIL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (root->right) {
|
|
Shinya Kitaoka |
120a6e |
ALLOC_NODE(newroot->right)
|
|
Shinya Kitaoka |
120a6e |
if (!newroot->right) return FALSE;
|
|
Shinya Kitaoka |
120a6e |
if (!copy_subtree(newroot->right, root->right)) {
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(newroot->right);
|
|
Shinya Kitaoka |
120a6e |
return FALSE;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
newroot->right = NIL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return TRUE;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TREE *avl_copy(TREE *tree) {
|
|
Shinya Kitaoka |
120a6e |
TREE *newtree;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ALLOC_TREE(newtree)
|
|
Shinya Kitaoka |
120a6e |
if (!newtree) return NIL;
|
|
Shinya Kitaoka |
120a6e |
newtree->keyinfo = tree->keyinfo;
|
|
Shinya Kitaoka |
120a6e |
newtree->keyoffs = tree->keyoffs;
|
|
Shinya Kitaoka |
120a6e |
newtree->usrcmp = tree->usrcmp;
|
|
Shinya Kitaoka |
120a6e |
newtree->nodes = tree->nodes;
|
|
Shinya Kitaoka |
120a6e |
newtree->path = NIL;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) {
|
|
Shinya Kitaoka |
120a6e |
ALLOC_NODE(newtree->root)
|
|
Shinya Kitaoka |
120a6e |
if (!copy_subtree(newtree->root, tree->root)) {
|
|
Shinya Kitaoka |
120a6e |
FREE_NODE(newtree->root)
|
|
Shinya Kitaoka |
120a6e |
avl_close(newtree);
|
|
Shinya Kitaoka |
120a6e |
return NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
newtree->root = NIL;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return newtree;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static void **Dat;
|
|
Toshihiro Shimizu |
890ddd |
static int *Lev;
|
|
Toshihiro Shimizu |
890ddd |
static int *Pos;
|
|
Toshihiro Shimizu |
890ddd |
static int Nod;
|
|
Toshihiro Shimizu |
890ddd |
static int Max_Lev;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
static void dump_subtree(struct avl_node *root, int lev, int pos) {
|
|
Shinya Kitaoka |
120a6e |
if (root->left) dump_subtree(root->left, lev + 1, pos * 2);
|
|
Shinya Kitaoka |
120a6e |
Dat[Nod] = root->data;
|
|
Shinya Kitaoka |
120a6e |
Lev[Nod] = lev;
|
|
Shinya Kitaoka |
120a6e |
Pos[Nod] = pos;
|
|
Shinya Kitaoka |
120a6e |
if (lev > Max_Lev) Max_Lev = lev;
|
|
Shinya Kitaoka |
120a6e |
Nod++;
|
|
Shinya Kitaoka |
120a6e |
if (root->right) dump_subtree(root->right, lev + 1, pos * 2 + 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int avl_dump(TREE *tree, void **dat_vect, int *lev_vect, int *pos_vect) {
|
|
Shinya Kitaoka |
120a6e |
Dat = dat_vect;
|
|
Shinya Kitaoka |
120a6e |
Lev = lev_vect;
|
|
Shinya Kitaoka |
120a6e |
Pos = pos_vect;
|
|
Shinya Kitaoka |
120a6e |
Nod = 0;
|
|
Shinya Kitaoka |
120a6e |
Max_Lev = -1;
|
|
Shinya Kitaoka |
120a6e |
if (tree->root) dump_subtree(tree->root, 0, 0);
|
|
Shinya Kitaoka |
120a6e |
return Max_Lev + 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*===========================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
#ifdef LEVO
|
|
Shinya Kitaoka |
120a6e |
int avl_porting_problems(void) {
|
|
Shinya Kitaoka |
120a6e |
long lng1, lng2;
|
|
Shinya Kitaoka |
120a6e |
ushort ush1, ush2;
|
|
Shinya Kitaoka |
120a6e |
char chr1, chr2;
|
|
Shinya Kitaoka |
120a6e |
void *ptr1, *ptr2;
|
|
Shinya Kitaoka |
120a6e |
struct s {
|
|
Shinya Kitaoka |
120a6e |
char c[4];
|
|
Shinya Kitaoka |
120a6e |
} * ps;
|
|
Shinya Kitaoka |
120a6e |
int problems;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define PROBLEM(n) (problems |= 1 | (1 << (n)))
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
problems = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Avl_Dummy[0] = 0.0;
|
|
Shinya Kitaoka |
120a6e |
Avl_Dummy[1] = 0.0;
|
|
Shinya Kitaoka |
120a6e |
((char *)Avl_Dummy)[1] = 0x15;
|
|
Shinya Kitaoka |
120a6e |
ptr1 = (void *)((char *)Avl_Dummy + 1);
|
|
Shinya Kitaoka |
120a6e |
lng1 = (long)ptr1;
|
|
Shinya Kitaoka |
120a6e |
ptr2 = (void *)lng1;
|
|
Shinya Kitaoka |
120a6e |
if (*(char *)ptr2 != (char)0x15) PROBLEM(1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ps = (struct s *)malloc(sizeof(struct s));
|
|
Shinya Kitaoka |
120a6e |
ps->c[0] = 0;
|
|
Shinya Kitaoka |
120a6e |
ps->c[1] = 0x15;
|
|
Shinya Kitaoka |
120a6e |
ps->c[2] = 0;
|
|
Shinya Kitaoka |
120a6e |
ps->c[3] = 0;
|
|
Shinya Kitaoka |
120a6e |
ptr1 = (void *)&ps->c[1];
|
|
Shinya Kitaoka |
120a6e |
lng1 = (long)ptr1;
|
|
Shinya Kitaoka |
120a6e |
ptr2 = (void *)lng1;
|
|
Shinya Kitaoka |
120a6e |
if (*(char *)ptr2 != (char)0x15) PROBLEM(2);
|
|
Shinya Kitaoka |
120a6e |
free(ps);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
chr1 = 1;
|
|
Shinya Kitaoka |
120a6e |
chr2 = 250;
|
|
Shinya Kitaoka |
120a6e |
lng1 = chr1;
|
|
Shinya Kitaoka |
120a6e |
lng2 = chr2;
|
|
Shinya Kitaoka |
120a6e |
if ((chr1 > chr2) && (lng1 < lng2) || (chr1 < chr2) && (lng1 > lng2))
|
|
Shinya Kitaoka |
120a6e |
PROBLEM(3);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (sizeof(long) == sizeof(short)) PROBLEM(4);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (sizeof(char) != 1) PROBLEM(5);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ush1 = (ushort)-1;
|
|
Shinya Kitaoka |
120a6e |
ush2 = (ushort)-2;
|
|
Shinya Kitaoka |
120a6e |
lng1 = CORRECT(ush1);
|
|
Shinya Kitaoka |
120a6e |
lng2 = CORRECT(ush2);
|
|
Shinya Kitaoka |
120a6e |
if (!(lng1 > lng2)) PROBLEM(6);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
lng1 = CORRECT(0L);
|
|
Shinya Kitaoka |
120a6e |
lng2 = lng1 - 1;
|
|
Shinya Kitaoka |
120a6e |
if (!((lng1 < 0) && (lng2 > 0))) PROBLEM(7);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return problems;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#define CDB_TCALLOC(ptr, elem) \
|
|
Shinya Kitaoka |
120a6e |
{ (ptr) = (void *)calloc((elem), sizeof(*(ptr))); }
|
|
Shinya Kitaoka |
120a6e |
#define CDB_TMALLOC(ptr, elem) \
|
|
Shinya Kitaoka |
120a6e |
{ (ptr) = (void *)malloc((elem) * sizeof(*(ptr))); }
|
|
Shinya Kitaoka |
120a6e |
#define CDB_TREALLOC(ptr, elem) \
|
|
Shinya Kitaoka |
120a6e |
{ (ptr) = (void *)realloc((ptr), (elem) * sizeof(*(ptr))); }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
#define GET_STRING_FIELD(P, FIELD) (P ? (P->FIELD ? P->FIELD : "") : "")
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define AVL_FOR(tree, p) for ((p) = avl_first(tree); (p); (p) = avl_next(tree))
|
|
Shinya Kitaoka |
120a6e |
typedef struct {
|
|
Shinya Kitaoka |
120a6e |
int index;
|
|
Shinya Kitaoka |
120a6e |
char *name;
|
|
Toshihiro Shimizu |
890ddd |
} COLOR_NAME;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
typedef struct {
|
|
Shinya Kitaoka |
120a6e |
char *name;
|
|
Shinya Kitaoka |
120a6e |
char *value;
|
|
Toshihiro Shimizu |
890ddd |
} CDB_PARAM;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
typedef struct {
|
|
Shinya Kitaoka |
120a6e |
char *name;
|
|
Shinya Kitaoka |
120a6e |
int num_params;
|
|
Shinya Kitaoka |
120a6e |
CDB_PARAM *param;
|
|
Toshihiro Shimizu |
890ddd |
} CDB_EFFECT;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
char *strsave(const char *str) {
|
|
Shinya Kitaoka |
120a6e |
char *neww;
|
|
Shinya Kitaoka |
120a6e |
if (!str) return 0;
|
|
Shinya Kitaoka |
120a6e |
neww = malloc(strlen(str) + 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
strcpy(neww, str);
|
|
Shinya Kitaoka |
120a6e |
return neww;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---------------------------------------------------------------------------*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
char *strnsave(const char *str, int n) {
|
|
Shinya Kitaoka |
120a6e |
char *neww;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
neww = malloc(n + 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
strncpy(neww, str, n);
|
|
Shinya Kitaoka |
120a6e |
neww[n] = '\0';
|
|
Shinya Kitaoka |
120a6e |
return neww;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TREE *cdb_decode_all(char *names_in_plt_file, TCM_INFO tcm) {
|
|
Shinya Kitaoka |
120a6e |
TREE *tree;
|
|
Shinya Kitaoka |
120a6e |
char *c1, *c2, *endcol, *endstr, *ct;
|
|
Shinya Kitaoka |
120a6e |
char tmp[100];
|
|
Shinya Kitaoka |
120a6e |
int i, p;
|
|
Shinya Kitaoka |
120a6e |
CDB_TREE_ITEM *item;
|
|
Shinya Kitaoka |
120a6e |
CDB_EFFECT *effect;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tree = avl_tree_nodup_int(CDB_TREE_ITEM, index);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
item = NIL;
|
|
Shinya Kitaoka |
120a6e |
endstr = strchr(names_in_plt_file, '\0');
|
|
Shinya Kitaoka |
120a6e |
c1 = names_in_plt_file;
|
|
Shinya Kitaoka |
120a6e |
c2 = NIL;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < tcm.n_colors + tcm.n_pencils; i++) {
|
|
Shinya Kitaoka |
120a6e |
CDB_TCALLOC(item, 1)
|
|
Shinya Kitaoka |
120a6e |
item->index = i;
|
|
Shinya Kitaoka |
120a6e |
// if (i < tcm.n_colors)
|
|
Shinya Kitaoka |
120a6e |
// item->index = TCM_COLOR_INDEX (tcm, i);
|
|
Shinya Kitaoka |
120a6e |
// else
|
|
Shinya Kitaoka |
120a6e |
// item->index = TCM_PENCIL_INDEX (tcm, i - tcm.n_colors);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
endcol = strchr(c1, '|');
|
|
Shinya Kitaoka |
120a6e |
if (!endcol) endcol = endstr;
|
|
Shinya Kitaoka |
120a6e |
c2 = strchr(c1, '\t');
|
|
Shinya Kitaoka |
120a6e |
if (!c2) c2 = endcol;
|
|
Shinya Kitaoka |
120a6e |
if (*c2 == '\t') {
|
|
Shinya Kitaoka |
120a6e |
if (c2 - c1 == 1 && *c1 == '*')
|
|
Shinya Kitaoka |
120a6e |
item->group = strsave("");
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
item->group = strnsave(c1, c2 - c1);
|
|
Shinya Kitaoka |
120a6e |
c1 = c2 + 1;
|
|
Shinya Kitaoka |
120a6e |
c2 = strchr(c1, '\t');
|
|
Shinya Kitaoka |
120a6e |
if (!c2) c2 = endcol;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
item->group = strsave("");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
while (*c1 == '<' && c1[1] == '!') {
|
|
Shinya Kitaoka |
120a6e |
c1 += 2;
|
|
Shinya Kitaoka |
120a6e |
ct = strstr(c1, "!>");
|
|
Shinya Kitaoka |
120a6e |
if (!ct) goto error;
|
|
Shinya Kitaoka |
120a6e |
if (*c1 == 'A') {
|
|
Shinya Kitaoka |
120a6e |
c1++;
|
|
Shinya Kitaoka |
120a6e |
item->accelerator = strnsave(c1, ct - c1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/* else if (*c1 == 'to be defined')... */
|
|
Shinya Kitaoka |
120a6e |
c1 = ct + 2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (c2 - c1 == 1 && *c1 == '*')
|
|
Shinya Kitaoka |
120a6e |
item->name = strsave("");
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
item->name = strnsave(c1, c2 - c1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (*c2 == '\t')
|
|
Shinya Kitaoka |
120a6e |
c1 = c2 + 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
c1 = c2;
|
|
Shinya Kitaoka |
120a6e |
if (!*c1) {
|
|
Shinya Kitaoka |
120a6e |
} else if (*c1 == '|')
|
|
Shinya Kitaoka |
120a6e |
c1++;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
item->effects = avl_tree_nodup_str(CDB_EFFECT, name);
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
ct = strstr(c1, " ! ");
|
|
Shinya Kitaoka |
120a6e |
if (ct) NOT_MORE_THAN(ct, endcol)
|
|
Shinya Kitaoka |
120a6e |
ct = strstr(c1, "#! ");
|
|
Shinya Kitaoka |
120a6e |
if (ct) NOT_MORE_THAN(ct, endcol)
|
|
Shinya Kitaoka |
120a6e |
c2 = strchr(c1, '#');
|
|
Shinya Kitaoka |
120a6e |
if (!c2 || c2 >= endcol) break;
|
|
Shinya Kitaoka |
120a6e |
CDB_TCALLOC(effect, 1)
|
|
Shinya Kitaoka |
120a6e |
effect->name = strnsave(c1, c2 - c1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
c1 = c2 + 1;
|
|
Shinya Kitaoka |
120a6e |
c2 = strchr(c1, '#');
|
|
Shinya Kitaoka |
120a6e |
if (!c2) goto error;
|
|
Shinya Kitaoka |
120a6e |
strncpy(tmp, c1, c2 - c1);
|
|
Shinya Kitaoka |
120a6e |
tmp[c2 - c1] = '\0';
|
|
Shinya Kitaoka |
120a6e |
effect->num_params = atoi(tmp);
|
|
Shinya Kitaoka |
120a6e |
if (effect->num_params) CDB_TCALLOC(effect->param, effect->num_params)
|
|
Shinya Kitaoka |
120a6e |
c1 = c2 + 1;
|
|
Shinya Kitaoka |
120a6e |
for (p = 0; p < effect->num_params; p++) {
|
|
Shinya Kitaoka |
120a6e |
c2 = strchr(c1, '#');
|
|
Shinya Kitaoka |
120a6e |
if (!c2) goto error;
|
|
Shinya Kitaoka |
120a6e |
effect->param[p].name = strnsave(c1, c2 - c1);
|
|
Shinya Kitaoka |
120a6e |
c1 = c2 + 1;
|
|
Shinya Kitaoka |
120a6e |
c2 = (p == effect->num_params - 1) ? endcol : strstr(c1, " : ");
|
|
Shinya Kitaoka |
120a6e |
if (!c2) goto error;
|
|
Shinya Kitaoka |
120a6e |
effect->param[p].value = strnsave(c1, c2 - c1);
|
|
Shinya Kitaoka |
120a6e |
ct = effect->param[p].value + strlen(effect->param[p].value) - 1;
|
|
Shinya Kitaoka |
120a6e |
while (ct >= effect->param[p].value && (*ct == ' ' || *ct == '\t'))
|
|
Shinya Kitaoka |
120a6e |
*ct-- = '\0';
|
|
Shinya Kitaoka |
120a6e |
c1 = c2 + 3;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
avl_insert(item->effects, effect);
|
|
Shinya Kitaoka |
120a6e |
item->num_effects++;
|
|
Shinya Kitaoka |
120a6e |
if (*endcol != '|')
|
|
Shinya Kitaoka |
120a6e |
c1 = endcol + 3;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
c1 = endcol + 1;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
avl_insert(tree, item);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return tree;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
error:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
printf("error parsing color names and fx\n");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return tree;
|
|
Toshihiro Shimizu |
890ddd |
}
|