static char sccsid[]="%Z% %M% %I% %E% %U%";
#include "akxcommon.h"

int akxtmmanfunc(cmd,pM,s,len,_opt_malloc)
int  cmd;	/* 0/1/2=non/set/cpy */
MCAT *pM;
char *s;
int len;
char *(*_opt_malloc)();
{
	char *p;
	int extlen,alen;

	if (!pM) return -1;
/*
if (_opt_malloc) printf("akxtmmanfunc: len=%d\n",len);
*/
	if ((cmd && !s) || len<=0) return (pM->mc_ipos);
	if (!(extlen=pM->mc_extlen)) extlen = 65536;
	if (pM->mc_alclen<=0 || !pM->mc_bufp) {
		pM->mc_alclen = 0;
		pM->mc_extcnt = 0;
		pM->mc_ipos   = 0;
		while (pM->mc_ipos+len > pM->mc_alclen) {
			if (pM->mc_maxcnt>0 && pM->mc_extcnt>=pM->mc_maxcnt) return -16;
			pM->mc_alclen += extlen;
			pM->mc_extcnt++;
		}
		alen = pM->mc_alclen;
		if (_opt_malloc) {
/*
printf("akxtmmanfunc:1: alen=%d\n",alen);
*/
			if (!(p = _opt_malloc(pM->mc_id[1],alen))) return -4;
		}
		else {
			if (!(p = Malloc(alen))) return -4;
		}
		pM->mc_bufp = p;
	}
	if (pM->mc_ipos+len > pM->mc_alclen) {
		while (pM->mc_ipos+len > pM->mc_alclen) {
			if (pM->mc_maxcnt>0 && pM->mc_extcnt>=pM->mc_maxcnt) return -16;
			pM->mc_alclen += extlen;
			pM->mc_extcnt++;
		}
		alen = pM->mc_alclen;
		if (_opt_malloc) {
/*
printf("akxtmmanfunc:2: alen=%d\n",alen);
*/
			if (!(p = _opt_malloc(pM->mc_id[1],alen))) return -8;
			memcpy(p,pM->mc_bufp,pM->mc_ipos);
		}
		else {
			if (!(p = Realloc(pM->mc_bufp,alen))) return -8;
		}
		pM->mc_bufp = p;
	}
	if (cmd == 1)
		memset(pM->mc_bufp+pM->mc_ipos,*s,len);
	else if (cmd == 2)
		memcpy(pM->mc_bufp+pM->mc_ipos,s,len);
	pM->mc_ipos += len;
	return (pM->mc_ipos);
}

int akxtmman(cmd,pM,s,len)
int  cmd;	/* 0/1/2=non/set/cpy */
MCAT *pM;
char *s;
int len;
{
	return akxtmmanfunc(cmd,pM,s,len,NULL);
}

int akxtmcat(pM,s,len)
MCAT *pM;
char *s;
int len;
{
	return akxtmman(2,pM,s,len);
}

int akxtmset(pM,c,len)
MCAT *pM;
int  c;
int len;
{
	char s[1];

	s[0] = c;
	return akxtmman(1,pM,s,len);
}

int akxtmexp(pM,len)
MCAT *pM;
int len;
{
	return akxtmman(0,pM,0,len);
}

int akxtmcatz(pM,s,len)
MCAT *pM;
char *s;
int len;
{
	int n,ipos;

	n = pM->mc_ipos;
	if (len < 0) return n;
	else if (!len) s = "";
	else if (!s) return n;
	ipos = akxtmman(0,pM,0,len+1);
	if (ipos > 0) {
		ipos--;
		pM->mc_ipos = ipos;
		memzcpy(pM->mc_bufp+n,s,len);
	}
	return ipos;
}

int akxtmcats(pM,s)
MCAT *pM;
char *s;
{
	if (!s) s = "";
	return akxtmcatz(pM,s,strlen(s));
}

int akxtmcat2(pM,s,len)
MCAT2 *pM;
char *s;
int len;
{
	return akxtmmanfunc(2,pM,s,len,pM->mc_malloc);
}

int akxtmcats2(pM,s)
MCAT2 *pM;
char *s;
{
	if (!s) s = "";
	return akxtmcatz2(pM,s,strlen(s));
}

int akxtmcatz2(pM,s,len)
MCAT2 *pM;
char *s;
int len;
{
	int n,ipos;

	n = pM->mc_ipos;
	if (len < 0) return n;
	else if (!len) s = "";
	else if (!s) return n;
	ipos = akxtmmanfunc(0,pM,0,len+1,pM->mc_malloc);
	if (ipos > 0) {
		ipos--;
		pM->mc_ipos = ipos;
		memzcpy(pM->mc_bufp+n,s,len);
	}
	return ipos;
}

int akxtmcati(pM)
MCAT *pM;
{
	if (!pM) return -1;
	pM->mc_ipos = 0;
}

int akxtmcat2i(pM)
MCAT2 *pM;
{
	if (!pM) return -1;
	pM->mc_ipos = 0;
}

static int _alloc_link_cmb(pM)
MCAT3 *pM;
{
	char *p;
	int extlen,alen;
	tdtCMBCTL *cmb,*cur;

	if (!(extlen=pM->mc_extlen)) extlen = 65536;
	pM->mc_alclen = extlen;
	pM->mc_extcnt++;
	if (pM->mc_maxcnt>0 && pM->mc_extcnt>=pM->mc_maxcnt) return -16;
	alen = pM->mc_alclen + sizeof(tdtCMBCTL);
	if (pM->mc_malloc) {
		if (!(p = pM->mc_malloc(pM->mc_id[1],alen))) return -4;
	}
	else {
		if (!(p = Malloc(alen))) return -4;
	}
	cmb = (tdtCMBCTL *)p;
	cmb->cbc_buf    = p + sizeof(tdtCMBCTL);
	cmb->cbc_next   = NULL;
	cmb->cbc_msize  = pM->mc_alclen;
	cmb->cbc_rem    = cmb->cbc_msize;
	cmb->cbc_mcount = 0;
	cmb->cbc_unused = 0;
	if (!pM->mc_cmb) {
		pM->mc_cmb = cmb;
	}
	else {
		cur = pM->mc_cur;
		cur->cbc_next = cmb;
	}
	pM->mc_cur = cmb;
	pM->mc_bufp = cmb->cbc_buf;
	return 0;
}

int akxtmcat3(pM,s,len0)
MCAT3 *pM;
char *s;
int len0;
{
	int ret,len;
	tdtCMBCTL *cmb;

	if (!pM) return -1;
	len = len0;
	if (!s || len<=0) return pM->mc_ipos;
	if (pM->mc_alclen<=0 || !pM->mc_bufp) {
		pM->mc_alclen = 0;
		pM->mc_extcnt = 0;
		pM->mc_ipos   = 0;
		if ((ret=_alloc_link_cmb(pM)) < 0) return ret;
	}
	while (len > 0) {
		cmb = pM->mc_cur;
		if (cmb->cbc_rem < len) {
			memcpy(pM->mc_bufp+cmb->cbc_unused,s,cmb->cbc_rem);
			cmb->cbc_unused = cmb->cbc_msize;
			len -= cmb->cbc_rem;
			s   += cmb->cbc_rem;
			cmb->cbc_rem = 0;
			if ((ret=_alloc_link_cmb(pM)) < 0) return ret;
		}
		else {
			memcpy(pM->mc_bufp+cmb->cbc_unused,s,len);
			len = 0;
		}
	}
	pM->mc_ipos += len;
	return pM->mc_ipos;
}

int akxtmcats3(pM,s)
MCAT3 *pM;
char *s;
{
	if (!s) s = "";
	return akxtmcatz3(pM,s,strlen(s));
}

int akxtmcatz3(pM,s,len)
MCAT3 *pM;
char *s;
int len;
{
	int n,ret;

	if ((n=akxtmcat3(pM,s,len)) >= 0) {
		ret = akxtmcat3(pM,"",1);
		if (ret >= 0) n += ret;
		else n = ret;
	}
	return n;
}

char *akxtmcata3(pM)
MCAT3 *pM;
{
	tdtCMBCTL *cmb;
	int len,ret;
	char *p,*pp;

	if (!pM) return NULL;
	len = pM->mc_ipos;
	if (pM->mc_malloc) p = pM->mc_malloc(pM->mc_id[1],len);
	else p = Malloc(len);
	if (pp=p) {
		cmb = pM->mc_cmb;
		while (cmb) {
			memcpy(pp,cmb->cbc_buf,cmb->cbc_unused);
			pp += cmb->cbc_unused;
			cmb = cmb->cbc_next;
		}
	}
	return p;
}
