added qse_sed_io_std_t and related code

This commit is contained in:
2011-09-18 09:41:26 +00:00
parent 0d4ea6aab9
commit ecaed2c2b3
13 changed files with 513 additions and 237 deletions

View File

@ -26,8 +26,15 @@
struct xtn_t
{
const qse_char_t* infile;
const qse_char_t* outfile;
struct
{
qse_sed_iostd_t* in;
qse_sed_iostd_t* out;
qse_sed_iostd_t* in_cur;
qse_size_t in_mempos;
qse_str_t* out_memstr;
} e;
};
typedef struct xtn_t xtn_t;
@ -63,6 +70,166 @@ int qse_sed_compstd (qse_sed_t* sed, const qse_char_t* sptr)
return qse_sed_comp (sed, sptr, qse_strlen(sptr));
}
static qse_sio_t* open_sio (qse_sed_t* sed, const qse_char_t* file, int flags)
{
qse_sio_t* sio;
sio = qse_sio_open (sed->mmgr, 0, file, flags);
if (sio == QSE_NULL)
{
qse_cstr_t ea;
ea.ptr = file;
ea.len = qse_strlen (file);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea);
}
return sio;
}
static void close_main_stream (
qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io)
{
if (io->type == QSE_SED_IOSTD_FILE)
{
qse_sio_t* sio = (qse_sio_t*)arg->handle;
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
}
}
static int open_main_input_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io)
{
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
QSE_ASSERT (io != QSE_NULL);
switch (io->type)
{
case QSE_SED_IOSTD_SIO:
arg->handle = io->u.sio;
break;
case QSE_SED_IOSTD_FILE:
if (io->u.file == QSE_NULL)
{
arg->handle = qse_sio_in;
}
else
{
qse_sio_t* sio;
sio = open_sio (sed, io->u.file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
if (sio == QSE_NULL) return -1;
arg->handle = sio;
}
break;
case QSE_SED_IOSTD_MEM:
/* don't store anything to arg->handle */
xtn->e.in_mempos = 0;
break;
}
return 0;
}
static int open_main_output_stream (qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_sed_iostd_t* io)
{
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
QSE_ASSERT (io != QSE_NULL);
switch (io->type)
{
case QSE_SED_IOSTD_SIO:
arg->handle = io->u.sio;
break;
case QSE_SED_IOSTD_FILE:
if (io->u.file == QSE_NULL)
{
arg->handle = qse_sio_out;
}
else
{
qse_sio_t* sio;
sio = open_sio (sed, io->u.file,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL) return -1;
arg->handle = sio;
}
break;
case QSE_SED_IOSTD_MEM:
/* don't store anything to arg->handle */
xtn->e.out_memstr = qse_str_open (sed->mmgr, 0, 512);
if (xtn->e.out_memstr == QSE_NULL)
{
qse_sed_seterrnum (sed, QSE_SED_ENOMEM, QSE_NULL);
return -1;
}
break;
}
return 0;
}
static qse_ssize_t read_main_input_stream (
qse_sed_t* sed, qse_sed_io_arg_t* arg, qse_char_t* buf, qse_size_t len)
{
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
qse_sed_iostd_t* io, * next;
void* old, * new;
qse_ssize_t n = 0;
if (len > QSE_TYPE_MAX(qse_ssize_t)) len = QSE_TYPE_MAX(qse_ssize_t);
do
{
io = xtn->e.in_cur;
QSE_ASSERT (io != QSE_NULL);
if (io->type == QSE_SED_IOSTD_MEM)
{
n = 0;
while (xtn->e.in_mempos < io->u.mem.len && n < len)
buf[n++] = io->u.mem.ptr[xtn->e.in_mempos++];
}
else n = qse_sio_getsn (arg->handle, buf, len);
if (n != 0) break;
/* end of file on the current input stream */
next = xtn->e.in_cur + 1;
if (next->type == QSE_SED_IOSTD_NULL)
{
/* no next stream available - return 0 */
break;
}
old = arg->handle;
/* try to open the next input stream */
if (open_main_input_stream (sed, arg, next) <= -1)
{
/* failed to open the next input stream */
n = -1;
break;
}
new = arg->handle;
arg->handle = old;
close_main_stream (sed, arg, io);
arg->handle = new;
xtn->e.in_cur++;
}
while (1);
return n;
}
static qse_ssize_t xin (
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg,
qse_char_t* buf, qse_size_t len)
@ -77,67 +244,53 @@ static qse_ssize_t xin (
if (arg->path == QSE_NULL)
{
/* main data stream */
if (xtn->infile == QSE_NULL) sio = qse_sio_in;
if (xtn->e.in == QSE_NULL) arg->handle = qse_sio_in;
else
{
sio = qse_sio_open (
sed->mmgr,
0,
xtn->infile,
QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL)
{
/* set the error message explicitly
* as the file name is different from
* the standard console name (NULL) */
qse_cstr_t ea;
ea.ptr = xtn->infile;
ea.len = qse_strlen (xtn->infile);
qse_sed_seterrnum (sed,QSE_SED_EIOFIL, &ea);
return -1;
}
if (open_main_input_stream (sed, arg, xtn->e.in_cur) <= -1) return -1;
}
}
else
{
sio = qse_sio_open (
sed->mmgr,
0,
arg->path,
QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
);
sio = open_sio (sed, arg->path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
if (sio == QSE_NULL) return -1;
arg->handle = sio;
}
if (sio == QSE_NULL) return -1;
arg->handle = sio;
return 1;
}
case QSE_SED_IO_CLOSE:
{
sio = (qse_sio_t*)arg->handle;
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
if (arg->path == QSE_NULL)
{
/* main data stream */
if (xtn->e.in) close_main_stream (sed, arg, xtn->e.in_cur);
}
else
{
sio = (qse_sio_t*)arg->handle;
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
}
return 0;
}
case QSE_SED_IO_READ:
{
qse_ssize_t n = qse_sio_getsn (arg->handle, buf, len);
if (n == -1)
if (arg->path == QSE_NULL)
{
if (arg->path == QSE_NULL && xtn->infile != QSE_NULL)
{
qse_cstr_t ea;
ea.ptr = xtn->infile;
ea.len = qse_strlen (xtn->infile);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea);
}
/* main data stream */
if (xtn->e.in == QSE_NULL)
return qse_sio_getsn (arg->handle, buf, len);
else
return read_main_input_stream (sed, arg, buf, len);
}
else
{
return qse_sio_getsn (arg->handle, buf, len);
}
return n;
}
default:
@ -149,8 +302,8 @@ static qse_ssize_t xout (
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg,
qse_char_t* dat, qse_size_t len)
{
qse_sio_t* sio;
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
qse_sio_t* sio;
switch (cmd)
{
@ -158,74 +311,76 @@ static qse_ssize_t xout (
{
if (arg->path == QSE_NULL)
{
if (xtn->outfile == QSE_NULL) sio = qse_sio_out;
if (xtn->e.out == QSE_NULL) arg->handle = qse_sio_out;
else
{
sio = qse_sio_open (
sed->mmgr,
0,
xtn->outfile,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL)
{
/* set the error message explicitly
* as the file name is different from
* the standard console name (NULL) */
qse_cstr_t ea;
ea.ptr = xtn->outfile;
ea.len = qse_strlen (xtn->outfile);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea);
return -1;
}
if (open_main_output_stream (sed, arg, xtn->e.out) <= -1) return -1;
}
}
else
{
sio = qse_sio_open (
sed->mmgr,
0,
arg->path,
sio = open_sio (
sed, arg->path,
QSE_SIO_WRITE |
QSE_SIO_CREATE |
QSE_SIO_TRUNCATE |
QSE_SIO_IGNOREMBWCERR
);
if (sio == QSE_NULL) return -1;
arg->handle = sio;
}
if (sio == QSE_NULL) return -1;
arg->handle = sio;
return 1;
}
case QSE_SED_IO_CLOSE:
{
sio = (qse_sio_t*)arg->handle;
qse_sio_flush (sio);
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
if (arg->path == QSE_NULL)
{
if (xtn->e.out) close_main_stream (sed, arg, xtn->e.out);
}
else
{
sio = (qse_sio_t*)arg->handle;
qse_sio_flush (sio);
if (sio != qse_sio_in && sio != qse_sio_out && sio != qse_sio_err)
qse_sio_close (sio);
}
return 0;
}
case QSE_SED_IO_WRITE:
{
qse_ssize_t n = qse_sio_putsn (arg->handle, dat, len);
if (n == -1)
if (arg->path == QSE_NULL)
{
if (arg->path == QSE_NULL && xtn->infile != QSE_NULL)
/* main data stream */
if (xtn->e.out == QSE_NULL)
return qse_sio_putsn (arg->handle, dat, len);
else
{
qse_cstr_t ea;
ea.ptr = xtn->infile;
ea.len = qse_strlen (xtn->infile);
qse_sed_seterrnum (sed, QSE_SED_EIOFIL, &ea);
qse_sed_iostd_t* io = xtn->e.out;
if (io->type == QSE_SED_IOSTD_MEM)
{
if (len > QSE_TYPE_MAX(qse_ssize_t)) len = QSE_TYPE_MAX(qse_ssize_t);
if (qse_str_ncat (xtn->e.out_memstr, dat, len) == (qse_size_t)-1)
{
qse_sed_seterrnum (sed, QSE_SED_ENOMEM, QSE_NULL);
return -1;
}
return len;
}
else
{
return qse_sio_putsn (arg->handle, dat, len);
}
}
}
return n;
else
{
return qse_sio_putsn (arg->handle, dat, len);
}
}
default:
@ -233,10 +388,69 @@ static qse_ssize_t xout (
}
}
int qse_sed_execstd (qse_sed_t* sed, const qse_char_t* infile, const qse_char_t* outfile)
int qse_sed_execstd (
qse_sed_t* sed, qse_sed_iostd_t in[], qse_sed_iostd_t* out)
{
int n;
xtn_t* xtn = (xtn_t*) QSE_XTN (sed);
xtn->infile = infile;
xtn->outfile = outfile;
return qse_sed_exec (sed, xin, xout);
if (in)
{
qse_size_t i;
if (in[0].type == QSE_SED_IOSTD_NULL)
{
/* if 'in' is specified, it must contains at least one
* valid entry */
qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL);
return -1;
}
for (i = 0; in[i].type != QSE_SED_IOSTD_NULL; i++)
{
if (in[i].type != QSE_SED_IOSTD_SIO &&
in[i].type != QSE_SED_IOSTD_FILE &&
in[i].type != QSE_SED_IOSTD_MEM)
{
qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL);
return -1;
}
}
}
if (out)
{
if (out->type != QSE_SED_IOSTD_SIO &&
out->type != QSE_SED_IOSTD_FILE &&
out->type != QSE_SED_IOSTD_MEM)
{
qse_sed_seterrnum (sed, QSE_SED_EINVAL, QSE_NULL);
return -1;
}
}
QSE_MEMSET (&xtn->e, 0, QSE_SIZEOF(xtn->e));
xtn->e.in = in;
xtn->e.out = out;
xtn->e.in_cur = in;
n = qse_sed_exec (sed, xin, xout);
if (n >= 0 && out && out->type == QSE_SED_IOSTD_MEM)
{
QSE_ASSERT (xtn->e.out_memstr != QSE_NULL);
qse_str_yield (xtn->e.out_memstr, &out->u.mem, 0);
}
if (xtn->e.out_memstr) qse_str_close (xtn->e.out_memstr);
/* if some output without a newline is emitted before
* last flush, they can be lost because qse_sio_out
* is not explicitly closed() with qse_sio_close()
* which in turn calls qse_sio_flush(). let's call it
* here directly. I don't care whether some other
* threads could have written to this. */
qse_sio_flush (qse_sio_out);
return n;
}