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

tdtRepStr *akxc_rep_str_new(iKeyLen,iExt,iRangeExt)
int iKeyLen,iExt,iRangeExt;
{
	tdtRepStr *tpRep;

	if (iKeyLen < 0) return NULL;
	if (iExt <= 10) iExt = 100;
	if (iRangeExt <= 0) iRangeExt = iExt;
	if (tpRep=(tdtRepStr *)Malloc(sizeof(tdtRepStr))) {
		memset(tpRep,0,sizeof(tdtRepStr));
		tpRep->rs_ext = iExt;
		tpRep->rs_range_ext = iRangeExt;

		if (!(tpRep->rs_xh = akxs_xhash_new(iKeyLen,iExt,0))) {
			XERROROUTL5(200,"key hash init error",0,0,0,0,0);
			Free(tpRep);
			tpRep = NULL;
		}
	}
	return tpRep;
}

int akxc_rep_set_parm(n,argv1,argv,argl,parm)
int  n,argl[];
char *argv1[],*argv[],*parm;
{
	char *p1,*p2,*p3,*pp;
	int  len,len1,len2,len3;

	if (n < 1 || !argv1 || !argv || !parm) return -1;
	len = 0;
	pp = parm;
	p1 = argv1[0];
	len1 = strlen(p1);
	if (!memicmp(p1,"0x",2)) {
		len1 = akxcctox(p1+2,len1-2,pp);
		pp[len1] = '\0';
		p1 = pp;
		pp += len1 + 1;
		len += len1 + 1;
	}
	if (n >= 2) {
		p2 = argv1[1];
		len2 = strlen(p2);
		if (!memicmp(p2,"0x",2)) {
			len2 = akxcctox(p2+2,len2-2,pp);
			pp[len2] = '\0';
			p2 = pp;
			pp += len2 + 1;
			len += len2 + 1;
		}
	}
	else {
		len2 = 0;
		p2 = pp;
		*pp++ = '\0';
		len++;
	}
	if (n <= 2) {
		argv[0] = p1;
		argv[1] = p2;
	}
	else {	/* n >= 3 */
		p3 = argv1[2];
		len3 = strlen(p3);
		if (!memicmp(p3,"0x",2)) {
			len3 = akxcctox(p3+2,len3-2,pp);
			pp[len3] = '\0';
			p3 = pp;
			len += len3 + 1;
		}
	/*
		ret = -3;
		if (len1 != len2) goto Err;
		if (n>=4 && len3!=len1) goto Err;
		if (len1>3 || len2>3 || len3>3) goto Err;
	*/
		argv[0] = p1;
		argv[1] = p2;
		argv[2] = p3;
		if (argl) {
			argl[0] = len1;
			argl[1] = len2;
			argl[2] = len3;
			if (n >= 4) {
				argl[3] = atoi(argv[3]);
			}
			else argl[3] = 1;
		}
		argv[3] = NULL;
	}
	return len;
}

int akxc_rep_add_file(tpRep,tfile)
tdtRepStr *tpRep;
char *tfile;
{
	FILE *fp;
	char buf[128],parm[256],*argv[4],*p1,*p2,*p3,*pp;
	int  len,n,i,ret,len1,len2,len3,argl[4];

	if (!tpRep || !tfile) return -1;
	if (!(fp=fopen(tfile,"r"))) {
		XERROROUTL5(200,"%s open error",tfile,0,0,0,0);
		return -2;
    }

	while ((len = akxa_read_line(buf,sizeof(buf),fp)) > 0) {
		n = akxtgetargv2(buf,argv,4,parm,sizeof(parm),1);
		if (n > 0) {
			ret = akxc_rep_set_parm(n,argv,argv,argl,buf);
			if (ret < 0) goto Err;
			if (n <= 2) {
				if ((ret=akxc_rep_add_rep(tpRep,2,argv,NULL)) < 0) goto Err;
			}
			else {
				if ((ret=akxc_rep_add_range(tpRep,4,argv,argl)) < 0) goto Err;
			}
		}
	}
	ret = 0;
Err:
	fclose(fp);
	return ret;
}

int akxc_rep_add_rep(tpRep,argc,argv,argl)
tdtRepStr *tpRep;
char *argv[];
int  *argl,argc;
{
	char *p1,*p2,*p;
	int len1,len2,klen,index,iMaxOld,ret;
	XHASHB *xha;

	if (!tpRep || !argv || argc<2) return -1;

	p1 = argv[0];
	p2 = argv[1];
	if (!p1 || !p2) return -1;

	if (!(xha=tpRep->rs_xh)) return -1;
	if (!(klen = xha->xha_keylen)) {
		if (argl) {
			if ((len1 = argl[0]) >= 0) {
				p = p1;
				if (p1=Malloc(len1+1)) strnzcpy(p1,p,len1);
				else return -1;
			}
		}
	}
	else if (klen > 0) {
		if (argl) {
			len1 = argl[0];
			if (len1 < 0) len1 = strlen(p1);
		}
		else len1 = strlen(p1);
		p = p1;
		if (p1=Malloc(len1+1)) {
			if (len1 < klen) memset(p1+len1,0,klen-len1);
			else len1 = klen;
			memcpy(p1,p,len1);
		}
		else return -1;
	}
	else return -1;

	if (argl) {
		len2 = argl[1];
		if (len2 < 0) len2 = strlen(p2);
	}
	else len2 = strlen(p2);

	index = akxs_xhash(xha,'s',p1);
	if (index <= 0) {
		if (!index) index = -1;
		return index;
	}
	if (index >= tpRep->rs_max) {
		iMaxOld = tpRep->rs_max;
		tpRep->rs_max += tpRep->rs_ext;
		if (tpRep->rs_pprep) {
			tpRep->rs_pprep=(char **)Realloc(tpRep->rs_pprep,tpRep->rs_max*sizeof(char *));
		}
		else {
			tpRep->rs_pprep=(char **)Malloc(tpRep->rs_max*sizeof(char *));
		}
		if (tpRep->rs_pprep)
			memset(&tpRep->rs_pprep[iMaxOld],0,tpRep->rs_ext*sizeof(char *));
	}
	ret = 0;
	if (tpRep->rs_pprep) {
		if (p=Malloc(len2+1)) {
			tpRep->rs_pprep[index-1] = p;
			strnzcpy(p,p2,len2);
		}
		else ret = -1;
	}
	else ret = -1;
XDEBUGOUTL5(200,"_addrep:imax=%d p1=[%s] index=%d p2=[%s]",tpRep->rs_max,p1,index,p2,0);
	return ret;
}

static UINT4 _cnvul(p,len)
char *p;
int  len;
{
	char w[4];
	UINT4 ul;

	memset(w,0,4);
	if (len>4) memcpy(w,p+len-4,4);
	else memcpy(w+4-len,p,len);
	memcpy(&ul,w,4);
	return ntohl(ul);
}

int akxc_rep_add_range(tpRep,argc,argv,argl)
tdtRepStr *tpRep;
char *argv[];
int  *argl,argc;
{
	int iMaxOld,i;
	char *p1,*p2,*p3,*p4,*wargv[2];
	int  len1,len2,len3,intval,wargl[2];

	if (argc <= 2) return akxc_rep_add_rep(tpRep,argc,argv,argl);

	if (!tpRep || !argv) return -1;

	p1 = argv[0];
	p2 = argv[1];
	p3 = argv[2];
	if (!p1 || !p2 || !p3) return -2;

	intval = 1;
	if (argl) {
		len1 = argl[0];
		len2 = argl[1];
		len3 = argl[2];
		if (len1 < 0) len1 = strlen(p1);
		if (len2 < 0) len2 = strlen(p2);
		if (len3 < 0) len3 = strlen(p3);
		if (argc >= 4) {
			intval = argl[3];
			if (intval<0 && (p4=argv[3])) intval = atoi(p4);
		}
	}
	else {
		len1 = strlen(p1);
		len2 = strlen(p2);
		len3 = strlen(p3);
		if (argc>=4 && (p4=argv[3])) intval = atoi(p4);
	}

	if (len1==len2 && !memcmp(p1,p2,len1)) {
		wargv[0] = argv[0];
		wargv[1] = argv[2];
		wargl[0] = argl[0];
		wargl[1] = argl[2];
		return akxc_rep_add_rep(tpRep,2,wargv,wargl);
	}
/*
	if (intval < 0) return -3;
*/
	i = tpRep->rs_range_used++;
	if (tpRep->rs_range_used > tpRep->rs_range_max) {
		iMaxOld = tpRep->rs_range_max;
		tpRep->rs_range_max += tpRep->rs_ext;
		if (tpRep->rs_range) {
			tpRep->rs_range=(tdtRepRange *)Realloc(tpRep->rs_range,tpRep->rs_range_max*sizeof(tdtRepRange));
		}
		else {
			tpRep->rs_range=(tdtRepRange *)Malloc(tpRep->rs_range_max*sizeof(tdtRepRange));
		}
		if (tpRep->rs_range)
			memset(&tpRep->rs_range[iMaxOld],0,tpRep->rs_ext*sizeof(tdtRepRange));
	}
	if (!tpRep->rs_range) return -4;
	tpRep->rs_range[i].rr_scmp = _cnvul(p1,len1);
	tpRep->rs_range[i].rr_ecmp = _cnvul(p2,len2);
	tpRep->rs_range[i].rr_srep = _cnvul(p3,len3);
	tpRep->rs_range[i].rr_intval = intval;
XDEBUGOUTL5(200,"_addrange:i=%d rr_scmp=%08x rr_ecmp=%08x rr_srep=%08x rr_intval=%d",i,
	tpRep->rs_range[i].rr_scmp,
	tpRep->rs_range[i].rr_ecmp,
	tpRep->rs_range[i].rr_srep,
	tpRep->rs_range[i].rr_intval);
	return 0;
}

int akxc_rep_str_free(tpRep)
tdtRepStr *tpRep;
{
	int i;

	if (!tpRep) return -1;
	if (tpRep->rs_xh) akxs_xhash_free(tpRep->rs_xh);
	if (tpRep->rs_pprep) {
		for (i=0;i<tpRep->rs_max;i++)
			if (tpRep->rs_pprep[i]) Free(tpRep->rs_pprep[i]);
		Free(tpRep->rs_pprep);
	}
	if (tpRep->rs_range) Free(tpRep->rs_range);
	Free(tpRep);
	return 0;
}

int akxc_rep_str(tpRep,opt,in_cod,out_cod)
tdtRepStr *tpRep;
int  opt;
char *in_cod,*out_cod;
{
	int i,j,ret,intval;
	UINT4 ul,ulw;
	char w[5];

	if (!tpRep || !in_cod || !out_cod) return -1;

XDEBUGOUTL5(200,"akxc_rep_str:opt=%d in_cod=[%s]",opt,in_cod,0,0,0);
	i = akxs_xhash(tpRep->rs_xh,'r',in_cod);
	if (i > 0) {
		strcpy(out_cod,tpRep->rs_pprep[i-1]);
		if (opt & 0x01) i = strlen(out_cod);
XDEBUGOUTL5(200,"akxc_rep_str:XHash:out_cod=[%s] ret=%d",out_cod,i,0,0,0);
		return i;
	}
	ret = 0;
	ul = _cnvul(in_cod,strlen(in_cod));
	for (i=0;i<tpRep->rs_range_used;i++) {
		if (ul>=tpRep->rs_range[i].rr_scmp && ul<=tpRep->rs_range[i].rr_ecmp) {
			if (intval=tpRep->rs_range[i].rr_intval)
				ul = tpRep->rs_range[i].rr_srep
				   + (ul - tpRep->rs_range[i].rr_scmp)*intval;
			else
				ul = tpRep->rs_range[i].rr_srep;
			ulw = htonl(ul);
			memcpy(w,&ulw,4);
			w[4] = '\0';
			for (j=0;j<4;j++) {
				if (w[j]) {
					strcpy(out_cod,w+j);
					break;
				}
			}
			ret = i + 1;
			if (opt & 0x01) ret = strlen(out_cod);
XDEBUGOUTL5(200,"akxc_rep_str:Range:out_cod=[%s] ret=%d",out_cod,ret,0,0,0);
			return ret;
		}
	}
	if (opt & 0x02) strcpy(out_cod,in_cod);
	else *out_cod = '\0';
	if (opt & 0x01) ret = strlen(out_cod);
XDEBUGOUTL5(200,"akxc_rep_str:not found:out_cod=[%s] ret=%d",out_cod,ret,0,0,0);
	return ret;
}
