/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/



#ifndef ___FAVT_H___
#define ___FAVT_H___

/* FAVT ERROR CODE */

#define AVT_E_NO_OBJ		(-1)
#define AVT_E_LOAD_ERROR_1	(-2)
#define AVT_E_LOAD_ERROR_2	(-3)
#define AVT_E_BOUND		(-4)

#include	"pdb.h"

#define FAVT_CACHE_SIZE	100

typedef struct favt_header {
	struct favt_header *	next;
	struct favt_header * 	prev;
	PDB *			p;
	unsigned int		fofs;
	short			type;
	unsigned short		flags;
#define FAF_DIRTY	0x0001
#define FAF_LOCK	0x0002
} FAVT_HEADER;

typedef struct favt_ptr {
	unsigned int		fofs;
	int			type;
	void *			ptr;
	unsigned short		flags;
} FAVT_PTR;

typedef struct favt_node {
	FAVT_HEADER	h;
	FAVT_PTR	small;
	FAVT_PTR	large;
	FAVT_PTR *	parent;
	struct favt_root * root;
	int		level;
	int		data_len;
	void *		data;
} FAVT_NODE;

typedef struct favt_root {
	FAVT_HEADER	h;
	int		type;
	void		(*endian_func)();
	FAVT_PTR	node;
} FAVT_ROOT;

typedef struct bound_list {
	struct bound_list *	next;
	void *			data;
	int			data_len;
} BOUND_LIST;

FAVT_ROOT * favt_alloc_root(PDB *,int,void (*)());
FAVT_NODE * favt_alloc_node(FAVT_ROOT *,void *,int);
FAVT_NODE * favt_insert(int * errp,FAVT_ROOT *,FAVT_PTR *,FAVT_NODE * ,int (*)());
FAVT_NODE * favt_delete(int * errp,FAVT_ROOT *,FAVT_PTR *,void *,int (*)());
FAVT_NODE * favt_search(int * errp,FAVT_ROOT * p,FAVT_NODE * a,void * data,int (*cmp)());
BOUND_LIST *
	favt_bound_search(int * errp,FAVT_ROOT *,FAVT_NODE *,void *,void *,int (*)());
void free_bound_list(BOUND_LIST *);
FAVT_ROOT * get_root(int * errp,PDB *,unsigned int,void (*)());
void favt_test(int * errp,FAVT_ROOT * p,FAVT_NODE * a,int (*cmp)());
FAVT_NODE * root_node(int * errp,FAVT_ROOT * r);
void favt_free_root(FAVT_ROOT * rt);
void favt_free_node(FAVT_NODE * rt);
int favt_trace_from_large(int * errp,FAVT_ROOT * p,FAVT_NODE * a,int (*func)(),void * work);
int favt_trace_from_small(int * errp,FAVT_ROOT * p,FAVT_NODE * a,int (*func)(),void * work);
void favt_lock(FAVT_HEADER *);
void favt_unlock(FAVT_HEADER *);
void init_favt();

int cmp_favt(FAVT_HEADER * a,FAVT_HEADER * b);
void insert_favt_tree(FAVT_HEADER * h);
void delete_favt_tree(PDB * p,unsigned int fofs);
void insert_favt_ring(FAVT_HEADER * h);
void delete_favt_ring(FAVT_HEADER * h);
void _touch_ring(void * h);
void touch_ring(void * h1,void * h2);
FAVT_PTR get_favt_ptr(unsigned int fofs,int type);
void get_favt_ptr2(FAVT_PTR * ptr,FAVT_NODE * n);
void set_favt_ptr(FAVT_PTR * d,FAVT_PTR s);
FAVT_HEADER * favt_load(int * errp,PDB * p,FAVT_ROOT * rt,unsigned int fofs,FAVT_PTR * parent);
int favt_write_node(FAVT_HEADER * h);
void change_endian_favt_node(PN_FAVT_NODE * n);
int favt_write_root(FAVT_HEADER * h);
void change_endian_favt_root(PN_FAVT_ROOT * r);
int favt_write(FAVT_HEADER * h);
int check_dirty(FAVT_HEADER * h,unsigned short reset);
int free_favt_cache(FAVT_HEADER * h);
void clear_cache();
void flush_favt_cache(PDB * p);
FAVT_NODE * g_ptr(int * errp,FAVT_ROOT * rt,FAVT_PTR * ptr);
FAVT_NODE * small_node(int * errp,FAVT_ROOT * rt,FAVT_NODE * n);
FAVT_NODE * large_node(int * errp,FAVT_ROOT * rt,FAVT_NODE * n);
void favt_valance(int * errp,FAVT_ROOT * p,FAVT_PTR * favtp);
void favt_alloc_header(PDB * p,FAVT_HEADER * ret,PN_HEADER * h);
void cc_node(char * str,FAVT_NODE * n);
void cc_root(char * str,FAVT_ROOT * r);
void check_cache(char * str);


#endif
