qse/qse/lib/utl/tgp.c
2009-09-16 04:01:02 +00:00

261 lines
4.5 KiB
C

/*
* $Id$
*/
#include <qse/utl/tgp.h>
#include "../cmn/mem.h"
#include "tgp.h"
QSE_IMPLEMENT_COMMON_FUNCTIONS (tgp)
qse_tgp_t* qse_tgp_open (qse_mmgr_t* mmgr, qse_size_t xtn)
{
qse_tgp_t* tgp;
if (mmgr == QSE_NULL)
{
mmgr = QSE_MMGR_GETDFL();
QSE_ASSERTX (mmgr != QSE_NULL,
"Set the memory manager with QSE_MMGR_SETDFL()");
if (mmgr == QSE_NULL) return QSE_NULL;
}
tgp = (qse_tgp_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_tgp_t) + xtn);
if (tgp == QSE_NULL) return QSE_NULL;
if (qse_tgp_init (tgp, mmgr) == QSE_NULL)
{
QSE_MMGR_FREE (tgp->mmgr, tgp);
return QSE_NULL;
}
return tgp;
}
void qse_tgp_close (qse_tgp_t* tgp)
{
qse_tgp_fini (tgp);
QSE_MMGR_FREE (tgp->mmgr, tgp);
}
qse_tgp_t* qse_tgp_init (qse_tgp_t* tgp, qse_mmgr_t* mmgr)
{
QSE_MEMSET (tgp, 0, sizeof(*tgp));
tgp->mmgr = mmgr;
return tgp;
}
void qse_tgp_fini (qse_tgp_t* tgp)
{
}
int qse_tgp_geterrnum (qse_tgp_t* tgp)
{
return tgp->errnum;
}
static int getc (qse_tgp_t* tgp, qse_char_t* c)
{
if (tgp->ib.pos >= tgp->ib.len)
{
qse_ssize_t n;
n = tgp->ih.func (QSE_TGP_IO_READ, tgp->ih.arg, tgp->ib.ptr, QSE_COUNTOF(tgp->ib.ptr));
if (n < 0) return -1;
else if (n == 0)
{
*c = QSE_CHAR_EOF;
return 0;
}
else
{
tgp->ib.pos = 0;
tgp->ib.len = n;
}
}
*c = tgp->ib.ptr[tgp->ib.pos++];
return 1;
}
static int putc (qse_tgp_t* tgp, qse_char_t c)
{
if (tgp->ob.len >= QSE_COUNTOF(tgp->ob.ptr))
{
qse_ssize_t n;
/* TODO: submit on a newline as well */
n = tgp->oh.func (QSE_TGP_IO_WRITE, tgp->oh.arg, tgp->ob.ptr, QSE_COUNTOF(tgp->ob.ptr));
if (n < 0) return -1;
else if (n == 0) return 0;
}
tgp->ob.ptr[tgp->ob.len++] = c;
return 1;
}
static int runc (qse_tgp_t* tgp, qse_char_t c)
{
if (tgp->rb.len >= QSE_COUNTOF(tgp->rb.ptr))
{
qse_ssize_t n;
n = tgp->rh.func (QSE_TGP_IO_WRITE, tgp->rh.arg, tgp->rb.ptr, tgp->rb.len);
if (n < 0) return -1;
else if (n == 0) return 0;
tgp->rh.func (QSE_TGP_IO_READ, tgp->rh.arg, tgp->rb.ptr, tgp->rb.len);
}
tgp->rb.ptr[tgp->rb.len++] = c;
return 1;
}
int qse_tgp_run (qse_tgp_t* tgp)
{
qse_bool_t in_tag = QSE_FALSE;
qse_char_t c;
int n;
tgp->ib.pos = 0;
tgp->ib.len = 0;
tgp->ob.len = 0;
tgp->rb.len = 0;
n = tgp->ih.func (QSE_TGP_IO_OPEN, tgp->ih.arg, QSE_NULL, 0);
if (n == -1)
{
/* error */
return -1;
}
if (n == 0)
{
/* reached end of input upon opening the file... */
tgp->ih.func (QSE_TGP_IO_CLOSE, tgp->ih.arg, QSE_NULL, 0);
return 0;
}
n = tgp->oh.func (QSE_TGP_IO_OPEN, tgp->oh.arg, QSE_NULL, 0);
if (n == -1)
{
tgp->ih.func (QSE_TGP_IO_CLOSE, tgp->ih.arg, QSE_NULL, 0);
return -1;
}
if (n == 0)
{
/* reached end of input upon opening the file... */
tgp->oh.func (QSE_TGP_IO_CLOSE, tgp->oh.arg, QSE_NULL, 0);
tgp->ih.func (QSE_TGP_IO_CLOSE, tgp->ih.arg, QSE_NULL, 0);
return 0;
}
while (1)
{
n = getc (tgp, &c);
if (n == -1) return -1;
if (n == 0) break;
if (c == QSE_T('<'))
{
n = getc (tgp, &c);
if (n == -1) return -1;
if (n == 0)
{
putc (tgp, QSE_T('<'));
break;
}
if (c == QSE_T('?'))
{
if (in_tag)
{
/* ERROR - netsted tag */
return -1;
}
else in_tag = QSE_TRUE;
}
else
{
if (putc (tgp, QSE_T('<')) <= 0) return -1;
if (putc (tgp, c) <= 0) return -1;
}
}
else if (c == QSE_T('?'))
{
n = getc (tgp, &c);
if (n == -1) return -1;
if (n == 0)
{
if (putc (tgp, QSE_T('<')) <= 0) return -1;
break;
}
if (c == QSE_T('>'))
{
if (in_tag) in_tag = QSE_FALSE;
else
{
/* ERROR - unpaired tag close */
return -1;
}
}
else
{
if (putc (tgp, QSE_T('?')) <= 0) return -1;
if (putc (tgp, c) <= 0) return -1;
}
}
else if (in_tag)
{
runc (tgp, c);
}
else
{
if (putc (tgp, c) <= 0) return -1;
}
}
tgp->oh.func (QSE_TGP_IO_CLOSE, tgp->oh.arg, QSE_NULL, 0);
tgp->ih.func (QSE_TGP_IO_CLOSE, tgp->ih.arg, QSE_NULL, 0);
return 0;
}
void qse_tgp_attachin (qse_tgp_t* tgp, qse_tgp_io_t io, void* arg)
{
tgp->ih.func = io;
tgp->ih.arg = arg;
}
void qse_tgp_detachin (qse_tgp_t* tgp)
{
tgp->ih.func = QSE_NULL;
tgp->ih.arg = QSE_NULL;
}
void qse_tgp_attachout (qse_tgp_t* tgp, qse_tgp_io_t io, void* arg)
{
tgp->oh.func = io;
tgp->oh.arg = arg;
}
void qse_tgp_detachout (qse_tgp_t* tgp)
{
tgp->oh.func = QSE_NULL;
tgp->oh.arg = QSE_NULL;
}
void qse_tgp_attachexec (qse_tgp_t* tgp, qse_tgp_io_t io, void* arg)
{
tgp->rh.func = io;
tgp->rh.arg = arg;
}
void qse_tgp_detachexec (qse_tgp_t* tgp)
{
tgp->rh.func = QSE_NULL;
tgp->rh.arg = QSE_NULL;
}