static char sccsid[]="%Z% %M% %I% %E% %U%";
/************************************************************************/
/*																		*/
/*	akxssrch.c															*/
/*																		*/
/*	作成 : 2001/02/15 Akito Kobayashi									*/
/*	更新 : 2019/08/23 Akito Kobayashi Add akxs_seqr_str(),				*/
/*								,akxs_seqr_str_num(),akxs_seqr_str2()	*/
/*	更新 : 2019/09/09 Akito Kobayashi Add akxs_iseq(),akxs_ins_sseq()   */
/*        ,akxs_ins_sseq_array(),akxs_ins_shseq(),akxs_ins_shseq_array()*/
/************************************************************************/
/*	  error code : -185210101〜-185219999		*/
#include "akxcommon.h"

static int _seqsr();
static int _seqss();
static int _seqsd();
static int _seqsi();

/*	01	*/
int akxs_seqs(func,hashbp)
char func;
HASHB *hashbp;
{
	int i;

	if (!hashbp) return -185210101;
/*
printf("akxs_seqs: func=%c hashbp->ha_prereg=%08x\n",func,hashbp->ha_prereg);
*/
	switch (func) {
	  case 'r':
	  case 'R':
			i=_seqsr(hashbp);
			break;
	  case 's':
	  case 'S':
			i=_seqss(hashbp);
			break;
	  case 'd':
	  case 'D':
			i=_seqsd(hashbp);
			break;
	  case 'i':
	  case 'I':
			i=_seqsi(hashbp);
			break;
	  default:
			i=-2;
	}
	return i;
}

/*	02	*/
static int _seqsi(hp)
HASHB *hp;
{
	int mx,i,j,klen,len1,aux;
	char *rp,**rpp;

	i = 0;	/* 2021.7.17 add mx */
	if ((mx=hp->ha_maxreg)<=0) i -= 4;
	if (!hp->ha_reg) i -= 8;
	if (!hp->ha_next) i -= 16;

	if (i >= 0) {
		klen = hp->ha_keylen;
		rp = hp->ha_reg;
		if (klen > 0) {
			len1 = klen + 1;
			for (j=0;j<mx;j++) {
				*rp = 0;
				rp += len1;
			}
		}
		else {
			memset(rp,0,(mx+1)*(sizeof(int)+1));
			if (!((aux=hp->ha_aux) & (AKX_HASX_OPT_USE_MALLOC | AKX_HASX_OPT_TMP_MALLOC))) {
				rpp = (char **)rp;
				if (aux & AKX_HASX_OPT_RESET_MEM) akxm_cct_reset((tdtCONSTCT *)rpp[0]);
				else rpp[0] = (char *)akxm_cct_mem_new(mx*32);
			}
		}
		memset(hp->ha_next,0,mx+1);
		hp->ha_aux = 0;
	}
	if (i < 0) i += -18521020;
	return i;
}

/*	03	*/
static int _seqss(hp)
HASHB *hp;
{
	int i,lklen,opt,lalen;
	char *p,*kp,**rpp,*np,*rp;
	short klen;
	tdtAllocCtl *pAC;
	char  *(*m_alloc)();
	tdtCONSTCT *pConstCt;

	if (i = _seqsr(hp)) return i;

	np = (char *)hp->ha_next;
/*
printf("_seqss: hp->ha_aux=%d\n",hp->ha_aux);
*/
#if 1	/* 2021.7.17 */
	for (i=1;i<=hp->ha_aux;i++) {
		if (!np[i]) break;
	}
	if (i > hp->ha_maxreg) return 0;
	if (i > hp->ha_aux) hp->ha_aux++;
/*
printf("_seqss: i=%d hp->ha_aux=%d\n",i,hp->ha_aux);
*/
#else
	for (i=0;i<hp->ha_aux;i++) {
		if (!np[i]) break;
	}
	if (i >= hp->ha_maxreg) return 0;
	if (i >= hp->ha_aux) hp->ha_aux++;
#endif
	rp = hp->ha_reg;
	rpp = (char **)rp;
	klen = hp->ha_keylen;
	kp = hp->ha_key;
	if (klen > 0) {
		p = rp + (i-1)*(klen+1);
		memzcpy(p,kp,klen);
/*
printf("_seqss: p=[%s]\n",p);
*/
		np[i] = 1;
	}
	else {
		if (!klen) {
			lalen = strlen(kp) + 1;
		}
		else if (klen > 0) {
			lalen = klen;
		}
		else {
			memcpy(&lklen,kp,sizeof(int));
			if (lklen < 0) return -32;
			lalen = lklen + sizeof(int);
		}
		if (hp->ha_id[1] == 'M') {
			pAC = (tdtAllocCtl *)hp->ha_reg;
			m_alloc = pAC->ac_malloc;
			pConstCt = pAC->ac_constct;
			p = akxm_malloc_constct(m_alloc,pConstCt,lalen);
		}
		else if (rpp[0]) {
			p = akxm_cct_malloc(rpp[0],lalen);
		}
		else {
			p = rpp[i];
			if (p) p = Realloc(p,lalen);
			else p = Malloc(lalen);
		}
		if (p) {
			if (klen < 0) {
				memcpy(p,&lklen,sizeof(int));
				memcpy(p+sizeof(int),kp,lklen);
			}
			else memcpy(p,kp,lalen);
		/*	if (opt = hp->ha_prereg) opt >>= 16;	*/
			np[i] = 1/* | opt*/;
			rpp[i] = p;
/*
printf("seqss:i=%d kp=[%s] np[i]=%08x\n",i,p,np[i]);
*/
		}
		else i = -33;
	}
	return i;		/* 2021.7.17 i+1 --> i */
}

/*	04	*/
static int _seqsr(hp)
HASHB *hp;
{
	int i;
	char *p,*kp,**rpp,*np,*rp;
	short len,klen;
	int  ldlen,lklen,opt;

	rp = hp->ha_reg;
	rpp = (char **)rp;
	np = (char *)hp->ha_next;
	if (!(kp = hp->ha_key)) return -185210401;
	if ((klen=hp->ha_keylen) < 0) {
		memcpy(&lklen,kp,sizeof(int));
		if (lklen < 0) return -185210402;
		kp += sizeof(int);
	}
/*
printf("seqr: klen=%d kp=[%s]\n",klen,kp);
*/
	opt = hp->ha_prereg;
#if 1	/* 2021.7.17 */
	for (i=1;i<=hp->ha_aux;i++) {
#else
	for (i=0;i<hp->ha_aux;i++) {
#endif
		if (!np[i]) ;
		else if (klen > 0) {
			p = rp + (i-1)*(klen+1);
			if (!akxs_opt_memcmp(p,kp,klen,opt)) break;
		}
		else {
			if (!(p = rpp[i])) ;
			else if (!klen) {
/*
printf("seqr:i=%d p=[%s] kp=[%s] opt=%08x\n",i,p,kp,opt);
*/
				if (!akxs_opt_strcmp(p,kp,opt)) break;
			}
			else {
				memcpy(&ldlen,p,sizeof(int));
				if (lklen == ldlen) {
					if (!akxs_opt_memcmp(p+sizeof(int),kp,lklen,opt)) break;
				}
			}
		}
	}
#if 1	/* 2021.7.17 */
	if (i > hp->ha_aux) i = 0;
#else
	if (i >= hp->ha_aux) i = -1;
#endif

	return i;		/* 2021.7.17 i+1 --> i */
}

/*	05	*/
static int _seqsd(hp)
HASHB *hp;
{
	int i;
	char *np;

	i = hp->ha_hix;
	if (i > 0 ) {
		if (i > hp->ha_aux) return -185210501;
	}
	else {
		if ((i=_seqsr(hp)) <= 0) return i;
	}
	np = (char *)hp->ha_next;
	np[i] = 0;		/* 2021.7.17 i-1 --> i */
	return i;
}

/*	06	*/
/********1*********2*********3*********4*********5*********7*/
/* 引数 : iOpt    : オプション								*/
/*					0x01 : ignore case						*/
/*					0x02 : ignore 半角/倍角					*/
/*					0x08 : not use akxm_cct_malloc()		*/
/*						   m_alloc<>NULL のときは、off扱い	*/
/* 返却 : ハッシュ構造体									*/
/*		  ha_id[0] = 'S' ignore case  のときは、's'			*/
/*		  ha_id[1] = 'Q' m_alloc<>NULLのときは、'M'			*/
/************************************************************/
HASHB *akxs_seqsm_new(sKeyLen,lMaxReg,iOpt,m_alloc,pConstCt)
short sKeyLen;
int  lMaxReg,iOpt;
char    *(*m_alloc)();
tdtCONSTCT *pConstCt;
{
	HASHB *tph;
	int l;
	char c,**rpp;
	tdtAllocCtl *pAC;
/*
printf("akxs_seqsm_new: sKeyLen=%d lMaxReg=%d iOpt=%08x m_alloc=%08x\n",sKeyLen,lMaxReg,iOpt,m_alloc);
*/
	if (lMaxReg <= 0) return NULL;
	if (!(tph=(HASHB *)akxm_malloc_constct(m_alloc,pConstCt,sizeof(HASHB)))) return NULL;
	memset(tph,0,sizeof(HASHB));
	c = 'S';
	if (iOpt & AKX_HASX_OPT_CASE_KEY) c = tolower(c);
	tph->ha_id[0] = c;
	c = 'Q';
	if (m_alloc) {
		c = 'M';
		iOpt &= AKX_HASX_OPT_USE_MALLOC;
		iOpt |= AKX_HASX_OPT_TMP_MALLOC;
	}
	tph->ha_id[1] = c;
	tph->ha_keylen = sKeyLen;
	tph->ha_maxreg = lMaxReg;
	tph->ha_prereg = iOpt;
	tph->ha_aux    = iOpt;
/*
printf("akxs_seqs_new: sKeyLen=%d lMaxReg=%d id[1]=%c\n",sKeyLen,lMaxReg,tph->ha_id[1]);
*/
#if 1	/* 2021.9.16 */
	if (sKeyLen > 0) l = lMaxReg*(sKeyLen+1);
	else l = (lMaxReg+1)*(sizeof(char *)+1);
	if (!(tph->ha_reg=akxm_malloc_constct(m_alloc,pConstCt,l))) {
#else
	if (!(tph->ha_reg=Malloc((lMaxReg+1)*sizeof(char *)))) {	/* 2021.7.17 lMaxReg --> lMaxReg+1 */
#endif
		akxs_seqs_free(tph);
		return NULL;
	}
#if 1	/* 2021.9.16 */
	if (!(tph->ha_next=(int *)akxm_malloc_constct(m_alloc,pConstCt,lMaxReg+1))) {
#else
	if (!(tph->ha_next=(int *)Malloc(lMaxReg+1))) {	/* 2021.7.17 lMaxReg --> lMaxReg+1 */
#endif
		akxs_seqs_free(tph);
		return NULL;
	}
	if (akxs_seqs('i',tph)) {
		akxs_seqs_free(tph);
		return NULL;
	}
	/* (iOpt & AKX_HASX_OPT_USE_MALLOC)==0 && (iOpt & AKX_HASX_OPT_TMP_MALLOC)==0 のときは、
	    上記で、rpp[0]は、akxm_cct_mem_new()で、設定されている */
	if (m_alloc) {
		if (!(pAC = (tdtAllocCtl *)akxm_malloc_constct(m_alloc,pConstCt,sizeof(tdtAllocCtl)))) {
			errno = -1107;
			akxs_seqs_free(tph);
			return NULL;
		}
		pAC->ac_malloc = m_alloc;
		pAC->ac_constct = pConstCt;
		rpp = (char **)tph->ha_reg;
		rpp[0] = (char *)pAC;
	}
	/* rpp[0] ==NULL : keyはMalloc()する。klenでkeyの保存形式が変わる。
	   m_alloc==NULL : rpp[0] : akxm_cct_mem_new()で、設定されている。
	   m_alloc<>NULL : rpp[0] : pACになっている。 */
	return tph;
}

/*	07	*/
HASHB *akxs_seqs_new(sKeyLen,lMaxReg)
short sKeyLen;
int  lMaxReg;
{
	return akxs_seqsm_new(sKeyLen,lMaxReg,0,NULL,NULL);
}

/*	08	*/
int akxs_seqs_free(hp)
HASHB *hp;
{
#if 1	/* 2021.7.17 */
	int i;
	char **rp;
#endif
	if (hp) {
#if 1	/* 2021.9.16 */
		if (hp->ha_id[1]=='M' && hp->ha_reg) {
			akxs_free_reg(hp->ha_maxreg,hp->ha_keylen,hp->ha_reg);
		}
#else
#if 1	/* 2021.7.17 */
		if (rp = (char **)hp->ha_reg) {
			for (i=1;i<=hp->ha_aux;i++) {
				if (rp[i]) Free(rp[i]);
			}
			Free(rp);
		}
#else
		if (hp->ha_reg) Free(hp->ha_reg);
		if (hp->ha_next) Free(hp->ha_next);
#endif
#endif
		Free(hp);
	}
	return 0;
}

static int _xseqs_chk();
static int _xseqs_used();
static int _xseqs_max();

/*	11	*/
/********1*********2*********3*********4*********5*********7*/
/* 引数 : iOpt    : オプション								*/
/*					0x01 : ignore case						*/
/*					0x02 : ignore 半角/倍角					*/
/*					0x08 : not use akxm_cct_malloc()		*/
/*						   m_alloc<>NULL のときは、off扱い	*/
/************************************************************/
XHASHB *akxs_xseqsm_new2(sKeyLen,lMaxReg,lDatLen,iOpt,m_alloc,pConstCt)
short sKeyLen;
int  lMaxReg,lDatLen,iOpt;
char    *(*m_alloc)();
tdtCONSTCT *pConstCt;
{
	XHASHB *p;
	int l;
	char c;

	if (lMaxReg <= 0) {
		errno = -185211101;
		return NULL;
	}
	if (!(p=(XHASHB *)akxm_malloc_constct(m_alloc,pConstCt,sizeof(XHASHB)))) {
		errno = -185211102;
		return NULL;
	}

	if (sKeyLen>0 && sKeyLen<=sizeof(long)) c = 'L';
	else if (sKeyLen>sizeof(long) && sKeyLen<=sizeof(long)*2) c = '2';
	else c = 'X';
/*
printf("akxs_xseqs_new2: sKeyLen=%d lMaxReg=%d lDatLen=%d id[1]=%c\n",sKeyLen,lMaxReg,lDatLen,c);
*/
	if (m_alloc) {
		iOpt &= ~AKX_HASX_OPT_USE_MALLOC;
		iOpt |= AKX_HASX_OPT_TMP_MALLOC;
	}
	p->xha_id[0] = 'S';
	p->xha_id[1] = c;
	p->xha_keylen = sKeyLen;
	p->xha_maxreg = lMaxReg;
	p->xha_prereg = 0;
	p->xha_datlen = lDatLen;
	p->xha_option = iOpt;
	p->xha_xhix   = 0;
	p->xha_hashb  = NULL;
	p->xha_xhnext = NULL;
	p->xha_datreg = NULL;
	p->xha_malloc = m_alloc;
	p->xha_constct= pConstCt;
	return p;
}

/*	12	*/
XHASHB *akxs_xseqs_new2(sKeyLen,lMaxReg,lDatLen,iOpt)
short sKeyLen;
int  lMaxReg,lDatLen,iOpt;
{
	return akxs_xseqsm_new2(sKeyLen,lMaxReg,lDatLen,iOpt,NULL,NULL);
}

/*	13	*/
XHASHB *akxs_xseqs_new(sKeyLen,lMaxReg)
short sKeyLen;
int  lMaxReg;
{
	return akxs_xseqs_new2(sKeyLen,lMaxReg,-2,0);
}

/*	14	*/
int akxs_xseqs_free(tp_xseqsb)
XHASHB *tp_xseqsb;
{
	HASHB *tph;
	char *p;

	if (tp_xseqsb) {
		if (tph=tp_xseqsb->xha_hashb) {
			akxs_seqs_free(tph);
		}
		if (!tp_xseqsb->xha_malloc && (p=tp_xseqsb->xha_datreg)) {
			akxs_free_reg(tp_xseqsb->xha_maxreg,tp_xseqsb->xha_datlen,p);
		}
		akxs_xseqs_free(tp_xseqsb->xha_xhnext);
		Free(tp_xseqsb);
	}
	return 0;
}

/*	15	*/
int akxs_xseqs2(tp_xseqsb,cCmnd,cpKey,cppDat)
XHASHB *tp_xseqsb;
char cCmnd, *cpKey;
char **cppDat;		/* cCmnd='S'or's'のときは、(char *)と読み替える */
{
	XHASHB *tpcur,*tpnext;
	int l,i,offset,len;
	HASHB *tph,ha;
	int ret,opt;
	char cCmd,c,cc;
/*
printf("akxs_xseqs2:Enter cCmnd=%c cpKey=[%s] cppDat=[%s]\n",cCmnd,cpKey,cppDat);
*/
	if (!tp_xseqsb) return -185211501;
	cCmd = akxcupper(cCmnd);
	if ((cCmd=='R'||cCmd=='P'||cCmd=='K') && cppDat) *cppDat = NULL;
	switch (cCmd) {
		case 'R':
		case 'S':
		case 'D':
			if (tp_xseqsb->xha_xhix) return _xseqs_chk(tp_xseqsb,cCmd,cpKey,cppDat);
			break;
		case 'K':
		case 'P':
			return _xseqs_chk(tp_xseqsb,cCmd,cpKey,cppDat);
		case 'U':
			return _xseqs_used(tp_xseqsb);
		case 'M':
			return _xseqs_max(tp_xseqsb);
		default:
			return -185211502;
	}
	if (!cpKey) return -185211503;
	l = 0;
	offset = 0;
	tpnext = tp_xseqsb;
	while (tpnext) {
		tpcur = tpnext;
		if (!(tph=tpcur->xha_hashb)) {
			if (cCmd == 'R' || cCmd == 'D') return 0;
			if (tph=akxs_seqsm_new(tpcur->xha_keylen,tpcur->xha_maxreg,
			                       tpcur->xha_option,tpcur->xha_malloc,tpcur->xha_constct))
				tpcur->xha_hashb = tph;
			else return errno;
			tph->ha_prereg = tpcur->xha_prereg;
			cc = tpcur->xha_id[0];
			c = toupper(cc);
			if (c != cc) tph->ha_prereg |= AKX_ARGV_USE_ICMP;
/*
printf("akxs_xseqs2: cCmd=%c tph->ha_prereg=%08x\n",cCmd,tph->ha_prereg);
*/
		}
		tph->ha_key = cpKey;
		tph->ha_hix = 0;
		if (cCmd=='S' && cppDat && tpcur->xha_datlen == -2 && tph->ha_id[1]=='L')
			tph->ha_next = (int *)cppDat;
		if (i=akxs_seqs(cCmd,tph)) {
/*
printf("akxs_xseqs2:akxs_seqs i=%d\n",i);
*/
			if (i>0) {
				if ((ret=akxs_dreg_proc(tpcur,cCmd,i,cppDat))<0) return ret;
				i += offset;
/*
printf("akxs_xseqs2:akxs_dreg_proc i=%d\n",i);
*/
			}
			return i;
		}
		tpnext = tpcur->xha_xhnext;
		offset += tpcur->xha_maxreg;
	}
	if (cCmd == 'R' || cCmd == 'D') return i;
	if (!(tpnext=(XHASHB *)akxm_malloc_constct(tpcur->xha_malloc,tpcur->xha_constct,sizeof(XHASHB)))) return -76;
	tpcur->xha_xhnext = tpnext;
	memcpy(tpnext,tpcur,sizeof(XHASHB));
	tpnext->xha_xhix = l;
	tpnext->xha_hashb = NULL;
	tpnext->xha_xhnext = NULL;
	tpnext->xha_datreg = NULL;
	if ((i = akxs_xseqs2(tpnext,cCmd,cpKey,cppDat))>0) i += offset;
	tpnext->xha_xhix = 0;
	return i;
}

/*	16	*/
int akxs_xseqs(tp_xseqsb,cCmd,cpKey)
XHASHB *tp_xseqsb;
char cCmd, *cpKey;
{
	return akxs_xseqs2(tp_xseqsb,cCmd,cpKey,NULL);
}

/*	17	*/
static int _xseqs_chk(tp_xseqsb,cCmd,cpKey,cppDat)
XHASHB *tp_xseqsb;
char cCmd, *cpKey,**cppDat;
{
	XHASHB *tpcur;
	int i,offset,max,next,ix;
	HASHB *tph;
	int ret;
	char cCmdw;

	ret = -185211701;
	i = tp_xseqsb->xha_xhix;
	tp_xseqsb->xha_xhix = 0;
	offset = 0;
	tpcur = tp_xseqsb;
	max = tpcur->xha_maxreg;
	while (tpcur) {
		next = offset + max;
		if (next >= i) {
			ret = 0;
			if (tph=tpcur->xha_hashb) {
				tph->ha_hix = ix = i - offset;
				if (cCmd != 'P') tph->ha_key = cpKey;
				else if (cCmd=='S' && cppDat && tpcur->xha_datlen == -2 && tph->ha_id[1]=='L')
					tph->ha_next = (int *)cppDat;
				ret = akxs_seqs(cCmd,tph);
				if (ret > 0) {
					if ((cCmdw=cCmd)=='P' || cCmdw=='K') cCmdw = 'R';
					if ((ret=akxs_dreg_proc(tpcur,cCmdw,ix,cppDat))<0) return ret;
					if ((cCmd == 'P') && cpKey) *(char **)cpKey = tph->ha_key;
					return i;
				}
			}
			break;
		}
		tpcur = tpcur->xha_xhnext;
		offset = next;
	}
	return ret;
}

/*	18	*/
static int _xseqs_used(tp_xseqsb)
XHASHB *tp_xseqsb;
{
	XHASHB *tpcur;
	int ret,count;
	HASHB *tph;

	count = 0;
	tpcur = tp_xseqsb;
	while (tpcur) {
		tpcur->xha_xhix = 0;
		if (tph=tpcur->xha_hashb) {
			ret = akxs_seqs('U',tph);
			tpcur->xha_xhix = ret;
			if (ret > 0) count += ret;
		}
		tpcur = tpcur->xha_xhnext;
	}
	return count;
}

/*	19	*/
static int _xseqs_max(tp_xseqsb)
XHASHB *tp_xseqsb;
{
	XHASHB *tpcur;
	int ret,m;
	HASHB *tph;

	m = 0;
	tpcur = tp_xseqsb;
	while (tpcur) {
		m += tpcur->xha_maxreg;
		tpcur = tpcur->xha_xhnext;
	}
	return m;
}

/*	20	*/
int akxs_seqr_ptr(ptra,max_ptra,ptr)
char *ptra[],*ptr;
int max_ptra;
{
	int i,ii;
/*
printf("akxs_seqr_ptr: ptr=%08x\n",ptr);
*/
	if (!ptra) return -185212001;
	else if (!ptr) return 0;
	ii = 0;
	for (i=0;i<max_ptra;i++) {
		if (ptra[i] == ptr) {
/*
printf("akxs_seqr_ptr: found ptr=%08x i=%d\n",ptr,i);
*/
			ii= i + 1;
			break;
		}
	}
	return ii;
}

/*	51	*/
/********************************************************************/
/*  機能 : 単純配列またはグループ構成の配列中の文字列または番号等を	*/
/*		   サーチする												*/
/*	*stra[]=														*/
/*		{"0","SYSCODE",""											*/
/*		,"1","EUC-JP","EUCJP","EUC",""								*/
/*		,"2","CP932","SJIS","S-JIS",""								*/
/*		,"3","ISO-2022-JP-3","JIS",""								*/
/*		,"4","CP939","EBCDIC",""									*/
/*		,"5","UTF-8","UTF8",""										*/
/*		,NULL};														*/
/*	引数 : IN : stra[]   : サーチ対象文字列ポインタ配列				*/
/*						   1groupは、空文字で終わる					*/
/*				max_stra : straのサーチ対象要素数					*/
/*							< 0 : NULLで終了						*/
/*				str      : サーチ文字列								*/
/*				opt      : オプション								*/
/*							= 0x10 : grouping						*/
/*							= 0x20 : グループ先頭はサーチしない		*/
/*									 0x10はONと見なす				*/
/*							= 0x01 : ignore case					*/
/*							= 0x02 : ignore 全角半角				*/
/*							= 0x04 : 全角処理あり					*/
/*							= 0x08 : 前方一致						*/
/*				posa[]  : 一致位置									*/
/*							posa[1] : 一致したstraの位置 (先頭が1)	*/
/*						  opt=0x0X									*/
/*							posa[0] : 0								*/
/*						  opt=0x1X のみ								*/
/*							posa[0] : group先頭のstraの位置			*/
/*						  opt=0x2X									*/
/*							posa[0] : group no.(最初のgroupが1)		*/
/*	返却 : = 0 : 一致しなかった										*/
/*		   > 0 : 一致したstraの位置 (先頭が1)						*/
/*				   opt=0x10のみONのとき、group no. (最初のgroupが1)	*/
/*				   opt=0x20がONのとき、group先頭のstraの位置		*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/08/23 Akito Kobayashi								*/
/*	更新 : 2022/06/08 Akito Kobayashi								*/
/*	更新 : 2022/11/01 Akito Kobayashi								*/
/********************************************************************/
int akxs_seqr_str_grp(stra,max_stra,str,opt,posa)
char *stra[],*str;
int max_stra,opt,posa[];
{
	int i,ii,ig,opt1,opt2,iNUM,i0,i3;
	int i2;	/* group先頭のstraの位置 */
	char **pp,*p;
/*
printf("akxs_seqr_str: max_stra=%d opt=%08x\n",max_stra,opt);
*/
	if (!stra || !str) return -185215101;
	if (!max_stra) return 0;
	opt1 = opt & 0x10;
	opt2 = opt & 0x20;
	if (opt2) opt1 = 0x10;
	ii = 0;
	ig = 0;
	if (opt1) ig = 1;
	iNUM = 0;
	if (opt2) iNUM = 1;
/*
printf("akxs_seqr_str: opt1=%d opt2=%d iNUM=%d str=[%s]\n",opt1,opt2,iNUM,str);
*/
	if (posa) {
		posa[1] = posa[0] = 0;
	}
	i0 = 0;
	i2 = 1;
	for (i=0,pp=stra;;i++,pp++) {
		p = *pp;
		if (max_stra >= 0) {
			if (i >= max_stra) break;
		}
		else if (!p) break;
		if (p) {
/*
printf("akxs_seqr_str: i=%d ig=%d i0=%d p=[%s]\n",i,ig,i0,p);
*/
			if (opt1 && !*p) {
				ig++;
				i2 = i + 2;	/* iの次がgroup先頭であり、i2はstraの先頭を1と数えるので2を加える */
				if (opt2) iNUM = 1;
			}
			else if (opt2 && iNUM) {
			/*	i0 = i + 1;	del 2022.11.01*/
				iNUM = 0;
			}
			else if (!akxs_opt_strcmp(p,str,opt)) {
/*
printf("akxs_seqr_str: found i=%d ig=%d\n",i,ig);
*/
#if 1	/* 2022.11.01 */
				if (opt1) {
					if (opt2) {
						ii = i2;
						i3 = ig;
					}
					else {
						ii = ig;
						i3 = i2;
					}
				}
				else {
					ii= i + 1;
					i3 = 0;
				}
				if (posa) {
					posa[0] = i3;
					posa[1] = i + 1;
				}
#else
				if (i0 > 0) ii = i0;
				else if (opt1) ii = ig;
				else ii= i + 1;
				if (posa) {
					posa[0] = ig;
					posa[1] = i + 1;
				}
#endif
				break;
			}
		}
	}
/*
printf("akxs_seqr_str: ii=%d\n",ii);
*/
	return ii;
}

/*	52	*/
int akxs_seqr_str(stra,max_stra,str,opt)
char *stra[],*str;
int max_stra,opt;
{
	return akxs_seqr_str_grp(stra,max_stra,str,opt,NULL);
}

/*	53	*/
/********************************************************************/
/*  機能 : グループ構成の配列中の番号等をサーチする					*/
/*  引数 : IN : stra[]   : サーチ対象文字列ポインタ配列				*/
/*						   group構成であり、1groupは空文字で終わる	*/
/*				max_stra : straのサーチ対象要素数					*/
/*							< 0 : NULLで終了						*/
/*				str      : サーチ文字列								*/
/*				opt      : オプション								*/
/*							= 0x01 : ignore case					*/
/*							= 0x02 : ignore 全角半角				*/
/*							= 0x04 : 全角処理あり					*/
/*							= 0x08 : 前方一致						*/
/*  返却 : = 0 : 一致しなかった										*/
/*		   > 0 : 一致したstraの番号等の位置(先頭が1)				*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/08/23 Akito Kobayashi								*/
/********************************************************************/
int akxs_seqr_str_num(stra,max_stra,str,opt)
char *stra[],*str;
int max_stra,opt;
{
	int i,ii,iNUM;
	char **pp,*p;
/*
printf("akxs_seqr_str_num: max_stra=%d opt=%08x\n",max_stra,opt);
*/
	if (!stra || !str) return -185215301;
	if (!max_stra) return 0;
	iNUM = 1;
/*
printf("akxs_seqr_str_num: iNUM=%d str=[%s]\n",iNUM,str);
*/
	ii = 0;
	for (i=0,pp=stra;;i++,pp++) {
		p = *pp;
		if (max_stra >= 0) {
			if (i >= max_stra) break;
		}
		else if (!p) break;
		if (p) {
/*
printf("akxs_seqr_str_num: i=%d iNUM=%d p=[%s]\n",i,iNUM,p);
*/
			if (!*p) {
				iNUM = 1;
			}
			else if (iNUM) {
				if (!akxs_opt_strcmp(p,str,opt)) {
					ii = i + 1;
/*
printf("akxs_seqr_str_num: found i=%d ig=%d\n",i,ig);
*/
					break;
				}
				iNUM = 0;
			}
		}
	}
/*
printf("akxs_seqr_str_num: ii=%d\n",ii);
*/
	return ii;
}

/*	54	*/
/********************************************************************/
/*  機能 : 番号等と文字列のペアの配列中の文字列または番号等を		*/
/*		   サーチする												*/
/*		*stra[]={"1","AAAAA","3","BBBBB","4","CCCC",NULL}			*/
/*  引数 : IN : stra[]   : サーチ対象文字列ポインタ配列				*/
/*						   番号等と文字列のペア						*/
/*				max_stra : straのサーチ対象要素数					*/
/*							< 0 : NULLで終了						*/
/*				str      : サーチ文字列または整数					*/
/*				opt      : オプション								*/
/*							= 0x40 : 番号等をサーチ 				*/
/*							= 0x80 : 番号等は整数	 				*/
/*							= 0x01 : ignore case					*/
/*							= 0x02 : ignore 全角半角				*/
/*							= 0x04 : 全角処理あり					*/
/*							= 0x08 : 前方一致						*/
/*  返却 : = 0 : 一致しなかった										*/
/*		   > 0 : 一致したstraの番号等の位置(先頭が1)				*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/08/23 Akito Kobayashi								*/
/********************************************************************/
int akxs_seqr_str2(stra,max_stra,str,opt)
char *stra[],*str;
int max_stra,opt;
{
	int i,ii,ig,opt4,intval,i1,iNUM,i0,opt8,k;
	char **pp,*p,*p0,*p1;
/*
printf("akxs_seqr_str2: max_stra=%d opt=%08x\n",max_stra,opt);
*/
	if (!stra || !str) return -185215401;
	opt4 = opt & 0x40;
	opt8 = opt & 0x80;
	if (!max_stra) return 0;
	else if (max_stra > 0) {
		max_stra &= ~0x01;
		if (!max_stra) return 0;
	}
/*
printf("akxs_seqr_str2: str=[%s] max_stra=%d opt4=%d\n",str,max_stra,opt4);
*/
	ii = 0;
	for (i=0,pp=stra;;i+=2) {
		p  = *pp++;
		p1 = *pp++;
		if (max_stra >= 0) {
			if (i >= max_stra) break;
		}
		else if (!p) break;
		if (p) {
/*
printf("akxs_seqr_str2: i=%d p=[%s] p1=[%s]\n",i,p,p1);
*/
			if (opt4) p1 = p;
/*
printf("akxs_seqr_str: p1=[%s]\n",p1);
*/
			if (opt8) {
				k = !(str == p1);
			}
			else {
				k = akxs_opt_strcmp(p1,str,opt);
			}
			if (!k) {
/*
printf("akxs_seqr_str2: found i=%d ig=%d\n",i,ig);
*/
				ii= i + 1;
				break;
			}
		}
	}
/*
printf("akxs_seqr_str2: ii=%d\n",ii);
*/
	return ii;
}

/*	56	*/
/********************************************************************/
/*  機能 : Integer配列中をサーチする								*/
/*  引数 : IN : ia[]   : サーチ対象Integer配列						*/
/*				max_ia : iaのサーチ対象要素数						*/
/*				val    : サーチInteger値							*/
/*				opt    : 比較オプション								*/
/*						 = 0 : ==									*/
/*						 = 1 : &									*/
/*						 = 2 : !=									*/
/*						 = 3 : 超えない最大値						*/
/*							   返却値= 0 : 先頭がvalを超えている	*/
/*  返却 : = 0 : 一致しなかった										*/
/*		   > 0 : 一致したiaの位置(先頭が1)							*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/09/09 Akito Kobayashi								*/
/********************************************************************/
int akxs_iseq_opt(ia,max_ia,val,opt)
int ia[],max_ia,val,opt;
{
	int i,ii,iai,match;

	if (!ia) return -185215601;
	match = ii = 0;
	for (i=0;i<max_ia;i++) {
		iai = ia[i];
		if (!opt) {
			if (iai == val) match = 1;
		}
		else if (opt == 1) {
			if (iai & val) match = 1;
		}
		else if (opt == 2) {
			if (iai != val) match = 1;
		}
		else if (opt == 3) {
			if (iai > val) {
				ii = i;
				break;
			}
		}
		if (match) {
			ii = i + 1;
			break;
		}
	}
	if (opt==3 && i>=max_ia) ii = max_ia;
	return ii;
}

/*	57	*/
int akxs_iseq(ia,max_ia,val)
int ia[],max_ia,val;
{
	return akxs_iseq_opt(ia,max_ia,val,0);
}

/*	58	*/
/********************************************************************/
/*  機能 : 文字列の指定要素位置に文字列要素を挿入する				*/
/*  引数 : IN : da     : 挿入先文字列へのポインタ					*/
/*				d_pos  : 挿入要素位置 (先頭が0)						*/
/*						   <0のときは、0と見なす					*/
/*				max_da : 挿入先文字列の要素数						*/
/*						   <0のときは、0と見なす					*/
/*				s_val  : 挿入元文字列要素へのポインタ				*/
/*				size   : 要素バイト数								*/
/*  返却 : > 0 : 挿入後の要素数 (max_da+1)							*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/09/09 Akito Kobayashi								*/
/********************************************************************/
int akxs_ins_sseq(da,d_pos,max_da,s_val,size)
char *da,*s_val;
int   d_pos,max_da,size;
{
	int i;
	char *pd;

	if (!da || !s_val) return -185215801;
	if (max_da < 0) max_da = 0;
	if (d_pos < 0) d_pos = 0;
	pd = da + (max_da - 1)*size;
	if (max_da>0 && d_pos>=0 && d_pos<max_da) {
		for (i=d_pos;i<max_da;i++,pd-=size) {
			memcpy(pd+size,pd,size);
		}
	}
	memcpy(pd+size,s_val,size);
	return ++max_da;
}

/*	61	*/
/********1*********2*********3*********4*********5*********6*********/
/*  機能 : 文字列の指定要素位置に文字列要素を挿入する				*/
/*  引数 : IN : da     : 挿入先文字列へのポインタ					*/
/*				d_pos  : 挿入先要素位置 (先頭が0)					*/
/*						   <0のときは、0と見なす					*/
/*				max_da : 挿入先文字列の要素数						*/
/*						   <0のときは、0と見なす					*/
/*				sa     : 挿入元文字列要素へのポインタ				*/
/*				s_pos  : 挿入元要素位置 (先頭が0)					*/
/*				n_sa   : 挿入する文字列の要素数						*/
/*						   <=0のときは、何もしない					*/
/*				size   : 要素バイト数								*/
/*				opt    : 挿入元要素クリアオプション					*/
/*						   <=0 : クリアしない						*/
/*						   = 1 : 半角スペースでクリアする			*/
/*						   > 1 : ゼロでクリアする					*/
/*  返却 : > 0 : 挿入した文字列の要素数 (n_sa)						*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/09/09 Akito Kobayashi								*/
/********************************************************************/
int akxs_ins_sseq_array(da,d_pos,max_da,sa,s_pos,n_sa,size,opt)
char *da,*sa;
int   d_pos,max_da,s_pos,n_sa,size,opt;
{
	int i;
	char *ps,pad;

	if (!da || !sa) return -185216101;
	if (s_pos < 0) s_pos = 0;
	if (opt == 1) pad = ' ';
	else if (opt > 1)pad = '\0';
	ps = sa + s_pos*size;
	for (i=0;i<n_sa;i++) {
		max_da = akxs_ins_sseq(da,d_pos,max_da,ps,size);
		if (opt > 0) memset(ps,pad,size);
		d_pos++;
		ps += size;
	}
	return n_sa;
}

/*	62	*/
/********************************************************************/
/*  機能 : short配列の指定要素位置にshort要素を挿入する				*/
/*  引数 : IN : da     : 挿入先short配列へのポインタ				*/
/*				d_pos  : 挿入先要素位置 (先頭が0)					*/
/*						   <0のときは、0と見なす					*/
/*				max_da : 挿入先short配列の要素数					*/
/*						   <0のときは、0と見なす					*/
/*				s_val  : 挿入元short値								*/
/*  返却 : > 0 : 挿入後の要素数 (max_da+1)							*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/09/09 Akito Kobayashi								*/
/********************************************************************/
int akxs_ins_shseq(da,d_pos,max_da,s_val)
short da[],s_val;
int   d_pos,max_da;
{
#if 1
	return akxs_ins_sseq(da,d_pos,max_da,&s_val,sizeof(short));
#else
	int i;
	short *pd;

	if (max_da < 0) max_da = 0;
	if (d_pos < 0) d_pos = 0;
	pd = da + max_da - 1;
	if (max_da>0 && d_pos>=0 && d_pos<max_da) {
		for (i=d_pos;i<max_da;i++,pd--) {
			*(pd+1) = *pd;
		}
	}
	*(pd+1) = s_val;
	return ++max_da;
#endif
}

/*	63	*/
/********1*********2*********3*********4*********5*********6*********/
/*  機能 : short配列の指定要素位置にshort配列要素を挿入する			*/
/*  引数 : IN : da     : 挿入先short配列へのポインタ				*/
/*				d_pos  : 挿入先要素位置 (先頭が0)					*/
/*						   <0のときは、0と見なす					*/
/*				max_da : 挿入先short配列の要素数					*/
/*						   <0のときは、0と見なす					*/
/*				sa     : 挿入元short配列要素へのポインタ			*/
/*				s_pos  : 挿入元要素位置 (先頭が0)					*/
/*				n_sa   : 挿入する文字列の要素数						*/
/*						   <=0のときは、何もしない					*/
/*				size   : 要素バイト数								*/
/*				opt    : 挿入元要素クリアオプション					*/
/*						   <=0 : クリアしない						*/
/*						   >=1 : ゼロでクリアする					*/
/*  返却 : > 0 : 挿入した文字列の要素数 (n_sa)						*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2019/09/09 Akito Kobayashi								*/
/********************************************************************/
int akxs_ins_shseq_array(da,d_pos,max_da,sa,s_pos,n_sa,opt)
short da[],sa[];
int   d_pos,max_da,s_pos,n_sa,opt;
{
#if 1
	if (opt == 1) opt = 2;
	return akxs_ins_sseq_array(da,d_pos,max_da,sa,s_pos,n_sa,sizeof(short),opt);
#else
	int i;
	short *ps;

	if (s_pos < 0) s_pos = 0;
	ps = sa + s_pos;
	for (i=0;i<n_sa;i++) {
		max_da = akxs_ins_shseq(da,d_pos,max_da,*ps);
		if (opt) *ps = 0;
		d_pos++;
		ps++;
	}
	return n_sa;
#endif
}

/*	66	*/
/********1*********2*********3*********4*********5*********6*********/
/*  機能 : メモリー中の文字列を行単位でサーチする					*/
/*  引数 : IN : pat     : サーチする文字列へのポインタ				*/
/*				pat_len : サーチする文字列の長さ(バイト)			*/
/*				mem     : サーチ対象文字列へのポインタ				*/
/*				mem_len : サーチ対象文字列の長さ(バイト)			*/
/*  返却 : > 0 : patに一致した行の先頭位置(memの先頭を1バイト目とする)*/
/*		   < 0 : ポインタがNULL										*/
/*	作成 : 2020/12/XX Akito Kobayashi								*/
/********************************************************************/
int akxs_sseq_mline(pat,patlen,mem,memlen)
char *pat,*mem;
int patlen,memlen;
{
	SSP_S ssp;
	int ret,sp,len;

	if (!pat || !mem) return -185216601;
	ret = 0;
/*
printf("akxs_sseq_mline: patlen=%d pat=[%s]\n",patlen,pat);
*/
	if (patlen>0 && memlen>=patlen) {
		memset(&ssp,0,sizeof(SSP_S));
		sp = 0;
		while ((len=akxtmgetline(mem, memlen, &ssp)) >= 0 ) {
/*
printf("akxs_sseq_mline: len=%d ssp.wd=[%s]\n",len,strmem(ssp.wd,len));
*/
			if (len==patlen && !memcmp(ssp.wd,pat,patlen)) {
				ret = sp + 1;
				break;
			}
			sp = ssp.sp;
		}
	}
	return ret;
}

/*	71	*/
XHASHB *akxs_xseqlm_new(max_reg,m_alloc,pConstCt)
int max_reg;
char *(*m_alloc)();
tdtCONSTCT *pConstCt;
{
	XHASHB *p;

	if (!(p=(XHASHB *)akxm_malloc_constct(m_alloc,pConstCt,sizeof(HASHB)))) {
		errno = -1303;
		return NULL;
	}
	return 0;
}

/*	72	*/
HASHB *akxs_seqlm_new(max_reg,m_alloc,pConstCt)
int max_reg;
char *(*m_alloc)();
tdtCONSTCT *pConstCt;
{
	HASHB *hp;
	char *p;
	int len;

	len = sizeof(HASHB) + max_reg*(sizeof(long)+1) + 1;
	if (!(p=akxm_malloc_constct(m_alloc,pConstCt,len))) {
		errno = -185215201;
		return NULL;
	}
	memset(p,0,len);
	hp = (HASHB *)p;
	hp->ha_id[0] = 'S';
	hp->ha_id[1] = 'L';
	hp->ha_maxreg = max_reg;
	p += sizeof(HASHB);
	hp->ha_reg = p;
	p += max_reg*sizeof(long);
	hp->ha_key = p;
	akxs_seql_i(hp);
	return hp;
}

/*	73	*/
int akxs_seql_i(ha)
HASHB *ha;
{
	int max_reg;

	if ((max_reg=ha->ha_maxreg) <= 0) return -185215304;
	memset(ha->ha_reg,0,max_reg *sizeof(long));
	memset(ha->ha_key,0,max_reg);
	return 0;
}

/*	74	*/
int akxs_seql_r(ha,lVal)
HASHB *ha;
long lVal;
{
	int i,ii;
	long *pV;
	char *p;

	ii = 0;
	pV = (long *)ha->ha_reg;
	p  = ha->ha_key;
	for (i=0;i<ha->ha_maxreg;i++,p++,pV++) {
		if (*p && *pV==lVal) {
			ii = i + 1;
			break;
		}
	}
	return ii;
}

/*	75	*/
int akxs_seql_s(ha,lVal)
HASHB *ha;
long lVal;
{
	int i,ii;
	long *pV;
	char *p;

	if (!(ii = akxs_seql_r(ha,lVal))) {
		p = ha->ha_key;
		i = akxstrnlen(p,ha->ha_maxreg);
		if (i < ha->ha_maxreg) {
			pV = (long *)ha->ha_reg;
			pV[i] = lVal;
			*(p+i) = '1';
			ii = i + 1;
		}
	}
	return ii;
}

/*	76	*/
int akxs_seql_d(ha,lVal)
HASHB *ha;
long lVal;
{
	int i,ii;
	long *pV;
	char *p;

	if ((ii=akxs_seql_r(ha,lVal)) > 0) {
		i = ii - 1;
		pV = (long *)ha->ha_reg;
		pV[i] = 0;
		p = ha->ha_key;
		*(p+i) = '\0';
	}
	return ii;
}
