static char sccsid[]="%Z% %M% %I% %E% %U%";
/************************************************/
/*												*/
/*	akxsRb.c									*/
/*												*/
/*		coded by A.Kobayashi 2010.5.20			*/
/*												*/
/************************************************/
#include "akxcommon.h"

tdtRbCtl *akxs_rb_new2(lBS,lRM,m_alloc,pConstCt)
int lBS,lRM;
char *(*m_alloc)();
tdtCONSTCT *pConstCt;
{
	tdtRbCtl *pCt;
	tdtRbChain *p1,*p2;
	int ret;

	pCt = (tdtRbCtl *)akxm_malloc_constct(m_alloc,pConstCt,sizeof(tdtRbCtl));
	if (!pCt) return NULL;
	memset(pCt,0,sizeof(tdtRbCtl));
	pCt->rb_bfsz = lBS;
	pCt->rb_max = lRM;
	ret = akxm_malloc_constct_pp(m_alloc,pConstCt,sizeof(tdtRbChain),(char *)&p1);
	if (!p1) {
		if (!ret) Free(pCt);
		return NULL;
	}
	pCt->rb_cur = pCt->rb_waddr = pCt->rb_raddr = p1;
	p1->rbc_buf = NULL;
	ret = akxm_malloc_constct_pp(m_alloc,pConstCt,sizeof(tdtRbChain),(char *)&p2);
	if (!p2) {
		if (!ret) {
			Free(pCt);
			Free(p1);
		}
		return NULL;
	}
	pCt->rb_wpriv = p2;
	p2->rbc_buf = NULL;
	p1->rbc_next = p2;
	p2->rbc_next = p1;
	pCt->rb_num = 2;
	pCt->rb_malloc = m_alloc;
	pCt->rb_constct = pConstCt;
	return pCt;
}

tdtRbCtl *akxs_rb_new(lBS,lRM)
int lBS,lRM;
{
	return akxs_rb_new2(lBS,lRM,NULL,NULL);
}

char *akxs_rb_get(pCt)
tdtRbCtl *pCt;
{
	if (!pCt) return NULL;
	return pCt->rb_raddr->rbc_buf;
}

char *akxs_rb_get_n(pCt)
tdtRbCtl *pCt;
{
	char *p;
	tdtRbChain *pr;

	if (!pCt) return NULL;
	
	if (!(pr = pCt->rb_raddr)) return NULL;
	if (p=pr->rbc_buf) {
		pr->rbc_buf = NULL;
		pCt->rb_raddr = pr->rbc_next;
		pCt->rb_used--;
	}
	pCt->rb_cur = pCt->rb_raddr;
	pCt->rb_pos = 0;
	return p;
}

char *akxs_rb_set_n(pCt, addr)
tdtRbCtl *pCt;
char *addr;
{
	tdtRbChain *pw, *pn, *pp;
/*
printf("akxs_rb_set_n: pCt=%08x addr=%08x\n",pCt,addr);
*/
	if (!pCt || !addr) return NULL;

	if (!(pw = pCt->rb_waddr)) return NULL;
	if (pw->rbc_buf) {
		pn = (tdtRbChain *)akxm_malloc_constct(pCt->rb_malloc,pCt->rb_constct,sizeof(tdtRbChain));
		if (!pn) return NULL;
		pp = pCt->rb_wpriv;
		pCt->rb_waddr = pp->rbc_next = pn;
		pn->rbc_next = pw;
		pw = pCt->rb_waddr;
		pCt->rb_num++;
	}
	pw->rbc_buf = addr;
	pCt->rb_waddr = pw->rbc_next;
	pCt->rb_wpriv = pw;
	pCt->rb_used++;
	return addr;
}

int akxs_rb_free(pCt)
tdtRbCtl *pCt;
{
	tdtRbChain *pw, *pn, *pp;
	char *(*m_alloc)();

	if (!pCt) return -1;
	m_alloc = pCt->rb_malloc;
	if (pp = pCt->rb_wpriv) {
		pw = pp->rbc_next;
		pp->rbc_next = NULL;
		while (pw) {
			pn = pw->rbc_next;
			if (!m_alloc) Free(pw);
			pw = pn;
		}
	}
	if (!m_alloc) Free(pCt);
	return 0;
}

int akxs_rb_buf_free(pCt)
tdtRbCtl *pCt;
{
	char *p;
	char *(*m_alloc)();

	if (!pCt) return -1;

	m_alloc = pCt->rb_malloc;
	while (p=akxs_rb_get_n(pCt)) {
		if (!m_alloc) Free(p);
	}
	return 0;
}

int akxs_rb_all_free(pCt)
tdtRbCtl *pCt;
{
	int  iRc;

	if (!(iRc = akxs_rb_buf_free(pCt))) iRc = akxs_rb_free(pCt);

	return iRc;
}

char *akxs_rb_set_t(pCt, addr)
tdtRbCtl *pCt;
char *addr;
{
	tdtRbChain *pw, *pn, *pp;

	if (!pCt || !addr) return NULL;
	if (!akxs_rb_get(pCt)) return akxs_rb_set_n(pCt,addr);

	pw = pCt->rb_waddr;
	while ((pp=pw->rbc_next) != pCt->rb_raddr) {
		pw = pp;
	}

	if (pw->rbc_buf) {
		pn = (tdtRbChain *)akxm_malloc_constct(pCt->rb_malloc,pCt->rb_constct,sizeof(tdtRbChain));
		if (!pn) return NULL;
		pw->rbc_next = pn;
		pn->rbc_next = pp;
		pw = pn;
		pCt->rb_num++;
	}
	pw->rbc_buf = addr;
	if (pCt->rb_raddr == pCt->rb_waddr) {
		pCt->rb_waddr = pw;
	}
	pCt->rb_raddr = pw;
	pCt->rb_used++;
	pCt->rb_cur = pCt->rb_raddr;
	pCt->rb_pos = 0;
	return addr;
}

char *akxs_rb_read(pCt, cmd)
tdtRbCtl *pCt;
int	 cmd;
{
	tdtRbChain *pr;
	char *p=NULL;

	if (pCt) {
		if (!cmd) {
			pr = pCt->rb_raddr;
			pCt->rb_pos = 0;
		}
		else {
			if (pCt->rb_pos >= pCt->rb_used) return NULL;
			if (pCt->rb_pos) {
				pr = pCt->rb_cur;
				pCt->rb_cur = pr->rbc_next;
			}
			else pCt->rb_cur = pCt->rb_raddr;
			pr = pCt->rb_cur;
			pCt->rb_pos++;
		}
		p = pr->rbc_buf;
	}
	return p;
}

int akxs_rb_exchg(pCt1, pCt2, opt)
tdtRbCtl *pCt1,*pCt2;
int opt;
{
	tdtRbCtl tCtW;

	if (!pCt1 || !pCt2) return -1;
	tCtW  = *pCt1;
	*pCt1 = *pCt2;
	*pCt2 = tCtW;
	return 0;
}

int akxs_rb_used(pCt)
tdtRbCtl *pCt;
{
	if (!pCt) return -1;
	return pCt->rb_used;
}

char *akxs_rb_srch(pCt, addr, compar)
tdtRbCtl *pCt;
char *addr;
int (*compar)();
{
	int f;
	tdtRbChain *pr;
	char *p;

	if (!pCt || !addr) return NULL;
	if (!compar) compar = strcmp;
	pr = pCt->rb_raddr;
	while (p=pr->rbc_buf) {
		if (!compar(addr,p)) return p;
		pr = pr->rbc_next;
		if (pr == pCt->rb_waddr) break;
	}
	return NULL;
}

/************************************************/
/*												*/
/*		List									*/
/*												*/
/************************************************/
tdtRbCtl *akxs_list_new2(lBS,lRM,m_alloc,pConstCt)
int lBS,lRM;
char *(*m_alloc)();
tdtCONSTCT *pConstCt;
{
	tdtRbCtl *pCt;

	pCt = (tdtRbCtl *)akxm_malloc_constct(m_alloc,pConstCt,sizeof(tdtRbCtl));
	if (!pCt) return NULL;
	memset(pCt,0,sizeof(tdtRbCtl));
	pCt->rb_bfsz = lBS;
	pCt->rb_max = lRM;
	pCt->rb_malloc = m_alloc;
	return pCt;
}

tdtRbCtl *akxs_list_new(lBS,lRM)
int lBS,lRM;
{
	return akxs_list_new2(lBS,lRM,NULL,NULL);
}

int akxs_list_free(pCt,free_func)
tdtRbCtl *pCt;
int (*free_func)();
{
	tdtRbChain *pw, *pn, *pp;
	char *p;
	char *(*m_alloc)();

	if (!pCt) return -1;
	m_alloc = pCt->rb_malloc;
	while (akxs_list_get(pCt,&p) > 0) {
		if (p) {
			if (free_func) free_func(p);
			else if (!m_alloc) Free(p);
		}
	}
	if (!m_alloc) Free(pCt);
	return 0;
}

int akxs_list_get(pCt,pp)
tdtRbCtl *pCt;
char **pp;
{
	tdtRbChain *pr;

	if (!pCt) return -1;
	
	if (pr = pCt->rb_raddr) {
		*pp = pr->rbc_buf;
		pCt->rb_raddr = pr->rbc_next;
		pCt->rb_used--;
		if (pr == pCt->rb_waddr) pCt->rb_waddr = NULL;
		Free(pr);
		return 1;
	}
	else return 0;
}

int akxs_list_set(pCt, addr)
tdtRbCtl *pCt;
char *addr;
{
	tdtRbChain *pw, *pn;

	if (!pCt) return -1;

	pn = (tdtRbChain *)akxm_malloc_constct(pCt->rb_malloc,pCt->rb_constct,sizeof(tdtRbChain));
	if (!pn) return 0;
	pn->rbc_buf = addr;
	pn->rbc_next = NULL;
	if (pw = pCt->rb_waddr) pw->rbc_next = pn;
	else pCt->rb_raddr = pn;
	pCt->rb_waddr = pn;
	pCt->rb_used++;
	return 1;
}

int akxs_list_srch(pCt, addr, compar, opt)
tdtRbCtl *pCt;
char *addr;
int (*compar)();
int opt;
{
	int f;
	tdtRbChain *pr,*pre;
	char *p;

	if (!pCt) return -1;
	pre = NULL;
	pr = pCt->rb_raddr;
	while (pr) {
		if (compar) f = !compar(addr,pr->rbc_buf);
		else f = (addr == pr->rbc_buf);
		if (f) {
			if (opt) {
				if (pre) pre->rbc_next = pr->rbc_next;
				else pCt->rb_raddr = pr->rbc_next;
				if (!pr->rbc_next) pCt->rb_waddr = pre;
				pCt->rb_used--;
			}
			pCt->rb_cur = pr;
			return 1;
		}
		pre = pr;
		pr = pr->rbc_next;
	}
	return 0;
}

int akxs_list_read(pCt, cmd, pp)
tdtRbCtl *pCt;
int     cmd;
char   **pp;
{
	tdtRbChain *pr;

	if (!pCt) return -1;

	if (!cmd) {
		pCt->rb_cur = NULL;
	}
	else {
		if (cmd > 0) {
			if (pr = pCt->rb_cur) pr = pr->rbc_next;
			else pr = pCt->rb_raddr;
		}
		else {
			if (!(pr = pCt->rb_cur)) pr = pCt->rb_raddr;
		}
		if (pr) {
			pCt->rb_cur = pr;
			*pp = pr->rbc_buf;
			return 1;
		}
	}
	return 0;
}

/************************************************/
/*												*/
/*		Stack									*/
/*												*/
/************************************************/
/********1*********2*********3*********4*********5*********6*********/
/*	機能 : スタック構造体を初期化									*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*				max_stack	: スタックの							*/
/*		   OUT: stack		: スタック構造体のメンバ				*/
/*								stack->wdmax = max_stack			*/
/*								stack->sp = 0						*/
/*								((char **)stack->wd)[] = NULL		*/
/*	返却 : = 0 正常													*/
/*		   =-2 max_stack <= 0										*/
/*	作成 : 2014/12/01 Akito Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
int akxs_stack_init(SSPL_S *stack,int max_stack)
{
	int ret;

	ret = 0;
	if (max_stack <= 0) ret -= 2;
	if (ret == 0) {
		stack->wdmax = max_stack;
		stack->sp = 0;
		mem_set_addr((char **)stack->wd,NULL,max_stack);
	}
	return ret;
}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 : スタック構造体を作成し、初期化							*/
/*	引数 : IN : max_stack	: スタックの							*/
/*		   OUT: stack		: スタック構造体のメンバ				*/
/*								stack->wdmax = max_stack			*/
/*								stack->sp = 0						*/
/*								((char **)stack->wd)[] = NULL		*/
/*	返却 : != NULL 正常												*/
/*		   =  NULL エラー											*/
/*	作成 : 2020/01/27 Akito Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
SSPL_S *akxs_stack_new(int max_stack)
{
	SSPL_S *stack;
	int ret;

	stack = NULL;
	if (max_stack > 0) {
		if (stack = (SSPL_S *)Malloc(sizeof(SSPL_S))) {
			if (stack->wd = Malloc(sizeof(char *)*max_stack)) {
				akxs_stack_init(stack,max_stack);
			}
			else {
				Free(stack);
				stack = NULL;
			}
		}
	}
	return stack;
}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 : スタック構造体を開放する									*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*	返却 : = 0 正常													*/
/*		   =-1 stack = NULL											*/
/*	作成 : 2020/01/27 Akito Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
int akxs_stack_free(SSPL_S *stack)
{
	int ret;

	ret = 0;
	if (stack) {
		Free(stack->wd);
		Free(stack);
	}
	else ret = -1;
	return ret;
}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 スタックに積む												*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*				val			: スタックに積む値						*/
/*		   OUT: stack		: スタック構造体のメンバ				*/
/*							  ((char **)stack->wd)[stack->sp] = val */
/*							  stack->sp++							*/
/*	返却 :	= 0 : 正常												*/
/*			=-1 : stack = NULL										*/
/*			=-4 : スタックオーバ									*/
/*	作成 :2014/12/01 AkitoKobayashi									*/
/*	更新 :															*/
/********************************************************************/
int akxs_stack_push(SSPL_S *stack,char *val)
{
	int ret;
	char **p;

	ret = 0;
	if (stack) {
		if (stack->sp >= stack->wdmax)
			ret = -4;
		else {
			p = (char **)(stack->wd);
			p[stack->sp] = val;
			stack->sp++;
		}
	}
	else ret = -1;
	return ret;
}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 : スタックをのぞく、または、スタックから取り出す			*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*				val			: スタックの値への参照					*/
/*				isPeek		: Peekフラグ							*/
/*								= 0 : スタックから取り出す			*/
/*								!=0 : スタックをのぞく				*/
/*		   OUT: stack		: スタック構造体のメンバ				*/
/*							  スタックから取り出すと､				*/
/*								stack->sp--							*/
/*	返却 :	= 0 : 正常												*/
/*			=-1 : stack = NULL										*/
/*			=-8 : スタックは空										*/
/*	作成 : 2014/12/01 Akito Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
static int _PopPeekStack(SSPL_S *stack,char **val,int isPeek)
{
	int ret;
	char **p;

	ret = 0;
	if (stack && val) {
		if (stack->sp <= 0)
			ret = -8;
		else {
			p = (char **)(stack->wd);
			*val = p[stack->sp - 1];
			if (isPeek == 0) stack->sp--;
		}
	}
	else ret = -1;
	return ret;
}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 : スタックから取り出す										*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*				val			: スタックの値への参照					*/
/*		   OUT: val			: 取り出した値							*/
/*				stack		: スタック構造体のメンバ				*/
/*								stack->sp--							*/
/*	返却 :	= 0 : 正常												*/
/*			=-1 : stack = NULL										*/
/*			=-8 : スタックは空										*/
/*	作成 : 2014/12/01 Akito Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
int akxs_stack_pop(SSPL_S *stack,char **val)
{

	return _PopPeekStack(stack, val, 0);

}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 : スタックをのぞく											*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*				val			: スタックの値への参照					*/
/*		   OUT: val			: のぞいた値							*/
/*	返却 :	= 0 : 正常												*/
/*			=-1 : stack = NULL										*/
/*			=-8 : スタックは空										*/
/*	作成 : 2014/12/01 Akito Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
int akxs_stack_peek(SSPL_S *stack,char **val)
{

	return _PopPeekStack(stack, val, 1);

}

/********1*********2*********3*********4*********5*********6*********/
/*	機能 :スタックをサーチし、なければ登録する						*/
/*	引数 : IN : stack		: スタック構造体への参照				*/
/*				val			: スタックに登録する値					*/
/*				Optional 	: opt 0x01=1 : 登録する					*/
/*		   OUT: stack		: スタック構造体のメンバ				*/
/*							  登録したときは、						*/
/*							  ((char **)stack->wd)[stack->sp] = val */
/*							  stack->sp++							*/
/*	返却 :	> 0 : 登録位置 + 1										*/
/*			=-4 : スタックオーバ									*/
/*			=-8 : スタックは空										*/
/*	作成 : 2018/03/15 Aki to Kobayashi								*/
/*	更新 :															*/
/********************************************************************/
int akxs_statck_srch(SSPL_S *stack,char *val,int opt)
{
	int ret,i;
	char **p;

	ret = 0;
	if (stack && val) {
		p = (char **)(stack->wd);
		for (i = 0; i< stack->sp - 1; i++) {
			if (p[i] == val) {
				ret = i + 1;
				break;
			}
		}
		if (opt & 0x01) ret = akxs_stack_push(stack, val);
	}
	else ret = -1;
	return ret;
}
