2013-03-13 15:57:50 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2019-06-06 05:28:23 +00:00
|
|
|
Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved.
|
2013-03-13 15:57:50 +00:00
|
|
|
|
2014-11-19 14:42:24 +00:00
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
2013-03-13 15:57:50 +00:00
|
|
|
|
2014-11-19 14:42:24 +00:00
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2013-03-13 15:57:50 +00:00
|
|
|
*/
|
|
|
|
|
2018-07-14 17:05:08 +00:00
|
|
|
#include "xli-prv.h"
|
2013-03-13 15:57:50 +00:00
|
|
|
#include <qse/xli/stdxli.h>
|
|
|
|
#include <qse/cmn/path.h>
|
2016-04-29 03:55:42 +00:00
|
|
|
#include "../cmn/mem-prv.h"
|
2013-03-13 15:57:50 +00:00
|
|
|
|
|
|
|
typedef struct xtn_t
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
qse_xli_iostd_t* x;
|
|
|
|
|
|
|
|
union
|
|
|
|
{
|
2013-05-15 12:05:24 +00:00
|
|
|
/*
|
|
|
|
nothing to maintain for file here
|
|
|
|
*/
|
|
|
|
|
2013-03-13 15:57:50 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
const qse_char_t* ptr;
|
|
|
|
const qse_char_t* end;
|
|
|
|
} str;
|
|
|
|
} u;
|
|
|
|
} in;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
qse_xli_iostd_t* x;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
qse_sio_t* sio;
|
|
|
|
} file;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
qse_str_t* buf;
|
|
|
|
} str;
|
|
|
|
} u;
|
|
|
|
} out;
|
|
|
|
} s;
|
|
|
|
|
|
|
|
qse_xli_ecb_t ecb;
|
|
|
|
} xtn_t;
|
|
|
|
|
2019-06-24 14:24:14 +00:00
|
|
|
#if defined(QSE_HAVE_INLINE)
|
|
|
|
static QSE_INLINE xtn_t* GET_XTN(qse_xli_t* xli) { return (xtn_t*)((qse_uint8_t*)qse_xli_getxtn(xli) - QSE_SIZEOF(xtn_t)); }
|
|
|
|
#else
|
|
|
|
#define GET_XTN(xli) ((xtn_t*)((qse_uint8_t*)qse_xli_getxtn(xli) - QSE_SIZEOF(xtn_t)))
|
|
|
|
#endif
|
|
|
|
|
2015-06-12 13:11:50 +00:00
|
|
|
qse_xli_t* qse_xli_openstd (qse_size_t xtnsize, qse_size_t rootxtnsize, qse_xli_errnum_t* errnum)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
2015-06-12 13:11:50 +00:00
|
|
|
return qse_xli_openstdwithmmgr (QSE_MMGR_GETDFL(), xtnsize, rootxtnsize, errnum);
|
2013-03-13 15:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void fini_xtn (qse_xli_t* xli)
|
|
|
|
{
|
|
|
|
/* nothing to do */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void clear_xtn (qse_xli_t* xli)
|
|
|
|
{
|
|
|
|
/* nothing to do */
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:11:50 +00:00
|
|
|
qse_xli_t* qse_xli_openstdwithmmgr (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_size_t rootxtnsize, qse_xli_errnum_t* errnum)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
|
|
|
qse_xli_t* xli;
|
|
|
|
xtn_t* xtn;
|
|
|
|
|
|
|
|
/* create an object */
|
2019-06-24 14:24:14 +00:00
|
|
|
xli = qse_xli_open(mmgr, QSE_SIZEOF(xtn_t) + xtnsize, rootxtnsize, errnum);
|
2013-03-13 15:57:50 +00:00
|
|
|
if (xli == QSE_NULL) goto oops;
|
|
|
|
|
2019-06-24 14:24:14 +00:00
|
|
|
xli->_instsize += QSE_SIZEOF(xtn_t);
|
|
|
|
|
2013-03-13 15:57:50 +00:00
|
|
|
/* initialize extension */
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn = GET_XTN(xli);
|
2015-06-12 13:11:50 +00:00
|
|
|
/* the extension area has been cleared in qse_httpd_open().
|
|
|
|
* QSE_MEMSET (xtn, 0, QSE_SIZEOF(*xtn));*/
|
2013-03-13 15:57:50 +00:00
|
|
|
|
|
|
|
xtn->ecb.close = fini_xtn;
|
|
|
|
xtn->ecb.clear = clear_xtn;
|
|
|
|
qse_xli_pushecb (xli, &xtn->ecb);
|
|
|
|
|
|
|
|
return xli;
|
|
|
|
|
|
|
|
oops:
|
|
|
|
if (xli) qse_xli_close (xli);
|
|
|
|
return QSE_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static qse_sio_t* open_sio (qse_xli_t* xli, const qse_char_t* file, int flags)
|
|
|
|
{
|
|
|
|
qse_sio_t* sio;
|
2019-06-24 14:24:14 +00:00
|
|
|
sio = qse_sio_open(qse_xli_getmmgr(xli), 0, file, flags);
|
2013-03-13 15:57:50 +00:00
|
|
|
if (sio == QSE_NULL)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t errarg;
|
2018-01-09 10:45:43 +00:00
|
|
|
errarg.ptr = (qse_char_t*)file;
|
2013-03-13 15:57:50 +00:00
|
|
|
errarg.len = qse_strlen(file);
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &errarg);
|
|
|
|
}
|
|
|
|
return sio;
|
|
|
|
}
|
|
|
|
|
2014-07-08 14:30:42 +00:00
|
|
|
static qse_cstr_t sio_std_names[] =
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
|
|
|
{ QSE_T("stdin"), 5 },
|
|
|
|
{ QSE_T("stdout"), 6 },
|
|
|
|
{ QSE_T("stderr"), 6 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static qse_sio_t* open_sio_std (qse_xli_t* xli, qse_sio_std_t std, int flags)
|
|
|
|
{
|
|
|
|
qse_sio_t* sio;
|
2019-06-24 14:24:14 +00:00
|
|
|
sio = qse_sio_openstd (qse_xli_getmmgr(xli), 0, std, flags);
|
2013-05-15 14:20:29 +00:00
|
|
|
if (sio == QSE_NULL) qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &sio_std_names[std]);
|
2013-03-13 15:57:50 +00:00
|
|
|
return sio;
|
|
|
|
}
|
|
|
|
|
2013-05-15 12:05:24 +00:00
|
|
|
static qse_ssize_t sf_in_open (qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
2013-05-15 14:20:29 +00:00
|
|
|
if (arg->prev == QSE_NULL)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
2013-05-15 12:05:24 +00:00
|
|
|
qse_xli_iostd_t* psin = xtn->s.in.x;
|
|
|
|
|
2013-06-29 17:01:32 +00:00
|
|
|
QSE_ASSERT (arg == &xli->rio.top);
|
2013-05-15 14:20:29 +00:00
|
|
|
|
2013-05-15 12:05:24 +00:00
|
|
|
switch (psin->type)
|
|
|
|
{
|
|
|
|
/* normal source files */
|
|
|
|
case QSE_XLI_IOSTD_FILE:
|
|
|
|
if (psin->u.file.path == QSE_NULL ||
|
|
|
|
(psin->u.file.path[0] == QSE_T('-') &&
|
|
|
|
psin->u.file.path[1] == QSE_T('\0')))
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
2013-05-15 12:05:24 +00:00
|
|
|
/* no path name or - -> stdin */
|
2013-10-21 14:53:53 +00:00
|
|
|
arg->handle = open_sio_std (xli, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_LINEBREAK);
|
2013-03-13 15:57:50 +00:00
|
|
|
}
|
2013-05-15 12:05:24 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
arg->handle = open_sio (xli, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH);
|
|
|
|
}
|
|
|
|
if (arg->handle == QSE_NULL) return -1;
|
|
|
|
if (psin->u.file.cmgr) qse_sio_setcmgr (arg->handle, psin->u.file.cmgr);
|
2013-05-15 14:20:29 +00:00
|
|
|
|
|
|
|
/* update the object name to something more specific */
|
|
|
|
arg->name = psin->u.file.path;
|
|
|
|
if (arg->name == QSE_NULL) arg->name = sio_std_names[QSE_SIO_STDIN].ptr;
|
|
|
|
|
2013-05-15 12:05:24 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
case QSE_XLI_IOSTD_STR:
|
|
|
|
xtn->s.in.u.str.ptr = psin->u.str.ptr;
|
|
|
|
xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
|
|
|
return -1;
|
2013-03-13 15:57:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* handle the included file - @include */
|
2013-05-15 14:20:29 +00:00
|
|
|
const qse_char_t* path;
|
2013-03-13 15:57:50 +00:00
|
|
|
qse_char_t fbuf[64];
|
|
|
|
qse_char_t* dbuf = QSE_NULL;
|
|
|
|
|
|
|
|
QSE_ASSERT (arg->name != QSE_NULL);
|
|
|
|
|
2013-05-15 12:05:24 +00:00
|
|
|
path = arg->name;
|
2013-05-15 14:20:29 +00:00
|
|
|
if (arg->prev->handle)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
2013-05-15 14:20:29 +00:00
|
|
|
const qse_char_t* outer;
|
2013-05-15 12:05:24 +00:00
|
|
|
|
2013-05-15 14:20:29 +00:00
|
|
|
outer = qse_sio_getpath (arg->prev->handle);
|
2013-03-13 15:57:50 +00:00
|
|
|
|
2013-05-15 14:20:29 +00:00
|
|
|
if (outer)
|
|
|
|
{
|
|
|
|
const qse_char_t* base;
|
|
|
|
|
|
|
|
/* i'm being included from another file */
|
2019-08-28 15:14:22 +00:00
|
|
|
base = qse_basename(outer);
|
2013-05-15 14:20:29 +00:00
|
|
|
if (base != outer && arg->name[0] != QSE_T('/'))
|
2013-05-15 12:05:24 +00:00
|
|
|
{
|
2013-05-15 14:20:29 +00:00
|
|
|
qse_size_t tmplen, totlen, dirlen;
|
2013-05-15 12:05:24 +00:00
|
|
|
|
2013-05-15 14:20:29 +00:00
|
|
|
dirlen = base - outer;
|
|
|
|
|
|
|
|
totlen = qse_strlen(arg->name) + dirlen;
|
|
|
|
if (totlen >= QSE_COUNTOF(fbuf))
|
|
|
|
{
|
|
|
|
dbuf = qse_xli_allocmem (
|
|
|
|
xli, QSE_SIZEOF(qse_char_t) * (totlen + 1)
|
|
|
|
);
|
|
|
|
if (dbuf == QSE_NULL) return -1;
|
|
|
|
|
|
|
|
path = dbuf;
|
|
|
|
}
|
|
|
|
else path = fbuf;
|
|
|
|
|
|
|
|
tmplen = qse_strncpy ((qse_char_t*)path, outer, dirlen);
|
|
|
|
qse_strcpy ((qse_char_t*)path + tmplen, arg->name);
|
2013-05-15 12:05:24 +00:00
|
|
|
}
|
2013-03-13 15:57:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
arg->handle = qse_sio_open (
|
2019-06-24 14:24:14 +00:00
|
|
|
qse_xli_getmmgr(xli), 0, path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH
|
2013-03-13 15:57:50 +00:00
|
|
|
);
|
|
|
|
|
2019-06-24 14:24:14 +00:00
|
|
|
if (dbuf) qse_xli_freemem (xli, dbuf);
|
2013-03-13 15:57:50 +00:00
|
|
|
if (arg->handle == QSE_NULL)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t ea;
|
2018-01-09 10:45:43 +00:00
|
|
|
ea.ptr = (qse_char_t*)arg->name;
|
2013-03-13 15:57:50 +00:00
|
|
|
ea.len = qse_strlen(ea.ptr);
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-15 12:05:24 +00:00
|
|
|
|
2013-03-13 15:57:50 +00:00
|
|
|
static qse_ssize_t sf_in_close (
|
|
|
|
qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
|
|
|
{
|
2013-05-15 14:20:29 +00:00
|
|
|
if (arg->prev == QSE_NULL)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
|
|
|
switch (xtn->s.in.x->type)
|
|
|
|
{
|
|
|
|
case QSE_XLI_IOSTD_FILE:
|
2013-05-15 12:05:24 +00:00
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
qse_sio_close (arg->handle);
|
2013-03-13 15:57:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_XLI_IOSTD_STR:
|
|
|
|
/* nothing to close */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* nothing to close */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* handle the included source file - @include */
|
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
qse_sio_close (arg->handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static qse_ssize_t sf_in_read (
|
|
|
|
qse_xli_t* xli, qse_xli_io_arg_t* arg,
|
|
|
|
qse_char_t* data, qse_size_t size, xtn_t* xtn)
|
|
|
|
{
|
2013-05-15 14:20:29 +00:00
|
|
|
if (arg->prev == QSE_NULL)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
|
|
|
qse_ssize_t n;
|
|
|
|
|
|
|
|
switch (xtn->s.in.x->type)
|
|
|
|
{
|
|
|
|
case QSE_XLI_IOSTD_FILE:
|
2013-05-15 12:05:24 +00:00
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
n = qse_sio_getstrn (arg->handle, data, size);
|
2013-03-13 15:57:50 +00:00
|
|
|
if (n <= -1)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t ea;
|
2018-01-09 10:45:43 +00:00
|
|
|
ea.ptr = (qse_char_t*)xtn->s.in.x->u.file.path;
|
2013-05-15 14:20:29 +00:00
|
|
|
if (ea.ptr == QSE_NULL) ea.ptr = sio_std_names[QSE_SIO_STDIN].ptr;
|
|
|
|
ea.len = qse_strlen(ea.ptr);
|
2013-03-13 15:57:50 +00:00
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_XLI_IOSTD_STR:
|
|
|
|
n = 0;
|
|
|
|
while (n < size && xtn->s.in.u.str.ptr < xtn->s.in.u.str.end)
|
|
|
|
{
|
|
|
|
data[n++] = *xtn->s.in.u.str.ptr++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* this should never happen */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
|
|
|
n = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* handle the included source file - @include */
|
|
|
|
qse_ssize_t n;
|
|
|
|
|
|
|
|
QSE_ASSERT (arg->name != QSE_NULL);
|
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
|
|
|
|
n = qse_sio_getstrn (arg->handle, data, size);
|
|
|
|
if (n <= -1)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t ea;
|
2018-01-09 10:45:43 +00:00
|
|
|
ea.ptr = (qse_char_t*)arg->name;
|
2013-03-13 15:57:50 +00:00
|
|
|
ea.len = qse_strlen(ea.ptr);
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static qse_ssize_t sf_in (
|
|
|
|
qse_xli_t* xli, qse_xli_io_cmd_t cmd,
|
|
|
|
qse_xli_io_arg_t* arg, qse_char_t* data, qse_size_t size)
|
|
|
|
{
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2013-03-13 15:57:50 +00:00
|
|
|
|
2013-05-15 12:05:24 +00:00
|
|
|
QSE_ASSERT (arg != QSE_NULL);
|
|
|
|
|
2013-03-13 15:57:50 +00:00
|
|
|
switch (cmd)
|
|
|
|
{
|
|
|
|
case QSE_XLI_IO_OPEN:
|
|
|
|
return sf_in_open (xli, arg, xtn);
|
|
|
|
|
|
|
|
case QSE_XLI_IO_CLOSE:
|
|
|
|
return sf_in_close (xli, arg, xtn);
|
|
|
|
|
|
|
|
case QSE_XLI_IO_READ:
|
|
|
|
return sf_in_read (xli, arg, data, size, xtn);
|
|
|
|
|
|
|
|
default:
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-29 17:01:32 +00:00
|
|
|
static qse_ssize_t sf_out_open (qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
|
|
|
{
|
|
|
|
if (arg->prev == QSE_NULL)
|
|
|
|
{
|
|
|
|
qse_xli_iostd_t* psout = xtn->s.out.x;
|
|
|
|
|
|
|
|
QSE_ASSERT (arg == &xli->wio.top);
|
|
|
|
|
|
|
|
switch (psout->type)
|
|
|
|
{
|
|
|
|
/* normal source files */
|
|
|
|
case QSE_XLI_IOSTD_FILE:
|
|
|
|
if (psout->u.file.path == QSE_NULL ||
|
|
|
|
(psout->u.file.path[0] == QSE_T('-') &&
|
|
|
|
psout->u.file.path[1] == QSE_T('\0')))
|
|
|
|
{
|
|
|
|
/* no path name or - -> stdout */
|
2013-10-21 14:53:53 +00:00
|
|
|
arg->handle = open_sio_std (xli, QSE_SIO_STDOUT, QSE_SIO_WRITE | QSE_SIO_CREATE | QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR | QSE_SIO_LINEBREAK);
|
2013-06-29 17:01:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arg->handle = open_sio (xli, psout->u.file.path, QSE_SIO_WRITE | QSE_SIO_CREATE | QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH);
|
|
|
|
}
|
|
|
|
if (arg->handle == QSE_NULL) return -1;
|
|
|
|
if (psout->u.file.cmgr) qse_sio_setcmgr (arg->handle, psout->u.file.cmgr);
|
|
|
|
|
|
|
|
/* update the object name to something more specific */
|
|
|
|
arg->name = psout->u.file.path;
|
|
|
|
if (arg->name == QSE_NULL) arg->name = sio_std_names[QSE_SIO_STDOUT].ptr;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case QSE_XLI_IOSTD_STR:
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn->s.out.u.str.buf = qse_str_open(qse_xli_getmmgr(xli), 0, 512);
|
2013-06-29 17:01:32 +00:00
|
|
|
if (xtn->s.out.u.str.buf == QSE_NULL)
|
|
|
|
{
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* handle the included file - @include */
|
|
|
|
const qse_char_t* path;
|
|
|
|
qse_char_t fbuf[64];
|
|
|
|
qse_char_t* dbuf = QSE_NULL;
|
|
|
|
|
|
|
|
QSE_ASSERT (arg->name != QSE_NULL);
|
|
|
|
|
|
|
|
path = arg->name;
|
|
|
|
if (arg->prev->handle)
|
|
|
|
{
|
|
|
|
const qse_char_t* outer;
|
|
|
|
|
|
|
|
outer = qse_sio_getpath (arg->prev->handle);
|
|
|
|
|
|
|
|
if (outer)
|
|
|
|
{
|
|
|
|
const qse_char_t* base;
|
|
|
|
|
|
|
|
/* i'm being included from another file */
|
2019-08-28 15:14:22 +00:00
|
|
|
base = qse_basename(outer);
|
2013-06-29 17:01:32 +00:00
|
|
|
if (base != outer && arg->name[0] != QSE_T('/'))
|
|
|
|
{
|
|
|
|
qse_size_t tmplen, totlen, dirlen;
|
|
|
|
|
|
|
|
dirlen = base - outer;
|
|
|
|
|
|
|
|
totlen = qse_strlen(arg->name) + dirlen;
|
|
|
|
if (totlen >= QSE_COUNTOF(fbuf))
|
|
|
|
{
|
|
|
|
dbuf = qse_xli_allocmem (
|
|
|
|
xli, QSE_SIZEOF(qse_char_t) * (totlen + 1)
|
|
|
|
);
|
|
|
|
if (dbuf == QSE_NULL) return -1;
|
|
|
|
|
|
|
|
path = dbuf;
|
|
|
|
}
|
|
|
|
else path = fbuf;
|
|
|
|
|
|
|
|
tmplen = qse_strncpy ((qse_char_t*)path, outer, dirlen);
|
|
|
|
qse_strcpy ((qse_char_t*)path + tmplen, arg->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
arg->handle = qse_sio_open (
|
2019-06-24 14:24:14 +00:00
|
|
|
qse_xli_getmmgr(xli), 0, path, QSE_SIO_WRITE | QSE_SIO_CREATE | QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH
|
2013-06-29 17:01:32 +00:00
|
|
|
);
|
|
|
|
|
2019-06-24 14:24:14 +00:00
|
|
|
if (dbuf) qse_xli_freemem (xli, dbuf);
|
2013-06-29 17:01:32 +00:00
|
|
|
if (arg->handle == QSE_NULL)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t ea;
|
2018-01-10 10:01:41 +00:00
|
|
|
/*ea.ptr = (qse_char_t*)arg->name;
|
|
|
|
ea.len = qse_strlen(ea.ptr);*/
|
|
|
|
ea.ptr = (qse_char_t*)path;
|
|
|
|
ea.len = qse_strlen(path);
|
2013-06-29 17:01:32 +00:00
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static qse_ssize_t sf_out_close (
|
|
|
|
qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
|
|
|
{
|
|
|
|
if (arg->prev == QSE_NULL)
|
|
|
|
{
|
|
|
|
switch (xtn->s.out.x->type)
|
|
|
|
{
|
|
|
|
case QSE_XLI_IOSTD_FILE:
|
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
qse_sio_close (arg->handle);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_XLI_IOSTD_STR:
|
|
|
|
/* nothing to close */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* nothing to close */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* handle the included source file - @include */
|
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
qse_sio_close (arg->handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static qse_ssize_t sf_out_write (
|
|
|
|
qse_xli_t* xli, qse_xli_io_arg_t* arg,
|
|
|
|
qse_char_t* data, qse_size_t size, xtn_t* xtn)
|
|
|
|
{
|
|
|
|
if (arg->prev == QSE_NULL)
|
|
|
|
{
|
|
|
|
qse_ssize_t n;
|
|
|
|
|
|
|
|
switch (xtn->s.out.x->type)
|
|
|
|
{
|
|
|
|
case QSE_XLI_IOSTD_FILE:
|
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
n = qse_sio_putstrn (arg->handle, data, size);
|
|
|
|
if (n <= -1)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t ea;
|
2018-01-09 10:45:43 +00:00
|
|
|
ea.ptr = (qse_char_t*)xtn->s.out.x->u.file.path;
|
2013-06-29 17:01:32 +00:00
|
|
|
if (ea.ptr == QSE_NULL) ea.ptr = sio_std_names[QSE_SIO_STDOUT].ptr;
|
|
|
|
ea.len = qse_strlen(ea.ptr);
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_XLI_IOSTD_STR:
|
|
|
|
if (size > QSE_TYPE_MAX(qse_ssize_t)) size = QSE_TYPE_MAX(qse_ssize_t);
|
|
|
|
if (qse_str_ncat (xtn->s.out.u.str.buf, data, size) == (qse_size_t)-1)
|
|
|
|
{
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
n = size;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* this should never happen */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
|
|
|
n = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* handle the included source file - @include */
|
|
|
|
qse_ssize_t n;
|
|
|
|
|
|
|
|
QSE_ASSERT (arg->name != QSE_NULL);
|
|
|
|
QSE_ASSERT (arg->handle != QSE_NULL);
|
|
|
|
|
|
|
|
n = qse_sio_putstrn (arg->handle, data, size);
|
|
|
|
if (n <= -1)
|
|
|
|
{
|
2014-07-08 14:30:42 +00:00
|
|
|
qse_cstr_t ea;
|
2018-01-09 10:45:43 +00:00
|
|
|
ea.ptr = (qse_char_t*)arg->name;
|
2013-06-29 17:01:32 +00:00
|
|
|
ea.len = qse_strlen(ea.ptr);
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static qse_ssize_t sf_out (
|
|
|
|
qse_xli_t* xli, qse_xli_io_cmd_t cmd,
|
|
|
|
qse_xli_io_arg_t* arg, qse_char_t* data, qse_size_t size)
|
|
|
|
{
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2013-06-29 17:01:32 +00:00
|
|
|
|
|
|
|
QSE_ASSERT (arg != QSE_NULL);
|
|
|
|
|
|
|
|
switch (cmd)
|
|
|
|
{
|
|
|
|
case QSE_XLI_IO_OPEN:
|
|
|
|
return sf_out_open (xli, arg, xtn);
|
|
|
|
|
|
|
|
case QSE_XLI_IO_CLOSE:
|
|
|
|
return sf_out_close (xli, arg, xtn);
|
|
|
|
|
|
|
|
case QSE_XLI_IO_WRITE:
|
|
|
|
return sf_out_write (xli, arg, data, size, xtn);
|
|
|
|
|
|
|
|
default:
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-31 13:31:30 +00:00
|
|
|
int qse_xli_readstd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
|
|
|
{
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2013-06-29 17:01:32 +00:00
|
|
|
|
2015-08-31 13:31:30 +00:00
|
|
|
if (in == QSE_NULL || (in->type != QSE_XLI_IOSTD_FILE &&
|
|
|
|
in->type != QSE_XLI_IOSTD_STR))
|
|
|
|
{
|
|
|
|
/* the input is a must. at least 1 file or 1 string
|
|
|
|
* must be specified */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
2013-06-29 17:01:32 +00:00
|
|
|
|
2015-08-31 13:31:30 +00:00
|
|
|
xtn->s.in.x = in;
|
2018-01-09 10:45:43 +00:00
|
|
|
return qse_xli_read(xli, sf_in);
|
2015-08-31 13:31:30 +00:00
|
|
|
}
|
2013-06-29 17:01:32 +00:00
|
|
|
|
|
|
|
|
2015-08-31 13:31:30 +00:00
|
|
|
int qse_xli_readinistd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2013-03-13 15:57:50 +00:00
|
|
|
|
|
|
|
if (in == QSE_NULL || (in->type != QSE_XLI_IOSTD_FILE &&
|
|
|
|
in->type != QSE_XLI_IOSTD_STR))
|
|
|
|
{
|
|
|
|
/* the input is a must. at least 1 file or 1 string
|
|
|
|
* must be specified */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->s.in.x = in;
|
2018-01-09 10:45:43 +00:00
|
|
|
return qse_xli_readini(xli, sf_in);
|
2013-03-13 15:57:50 +00:00
|
|
|
}
|
|
|
|
|
2018-01-09 10:45:43 +00:00
|
|
|
int qse_xli_readjsonstd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
|
|
|
{
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2018-01-09 10:45:43 +00:00
|
|
|
|
|
|
|
if (in == QSE_NULL || (in->type != QSE_XLI_IOSTD_FILE &&
|
|
|
|
in->type != QSE_XLI_IOSTD_STR))
|
|
|
|
{
|
|
|
|
/* the input is a must. at least 1 file or 1 string
|
|
|
|
* must be specified */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->s.in.x = in;
|
|
|
|
return qse_xli_readjson(xli, sf_in);
|
|
|
|
}
|
2015-08-31 13:31:30 +00:00
|
|
|
|
2015-09-02 08:43:43 +00:00
|
|
|
int qse_xli_writestd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iostd_t* out)
|
2013-03-13 15:57:50 +00:00
|
|
|
{
|
|
|
|
int n;
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2013-03-13 15:57:50 +00:00
|
|
|
|
|
|
|
if (out == QSE_NULL || (out->type != QSE_XLI_IOSTD_FILE &&
|
|
|
|
out->type != QSE_XLI_IOSTD_STR))
|
|
|
|
{
|
|
|
|
/* the input is a must. at least 1 file or 1 string
|
|
|
|
* must be specified */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->s.out.x = out;
|
2015-09-02 08:43:43 +00:00
|
|
|
n = qse_xli_write (xli, root_list, sf_out);
|
2013-03-13 15:57:50 +00:00
|
|
|
|
|
|
|
if (out->type == QSE_XLI_IOSTD_STR)
|
|
|
|
{
|
|
|
|
if (n >= 0)
|
|
|
|
{
|
|
|
|
QSE_ASSERT (xtn->s.out.u.str.buf != QSE_NULL);
|
|
|
|
qse_str_yield (xtn->s.out.u.str.buf, &out->u.str, 0);
|
|
|
|
}
|
|
|
|
if (xtn->s.out.u.str.buf) qse_str_close (xtn->s.out.u.str.buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
2015-09-01 06:32:14 +00:00
|
|
|
|
2015-09-02 08:43:43 +00:00
|
|
|
int qse_xli_writeinistd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iostd_t* out)
|
2015-09-01 06:32:14 +00:00
|
|
|
{
|
|
|
|
int n;
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2015-09-01 06:32:14 +00:00
|
|
|
|
|
|
|
if (out == QSE_NULL || (out->type != QSE_XLI_IOSTD_FILE &&
|
|
|
|
out->type != QSE_XLI_IOSTD_STR))
|
|
|
|
{
|
|
|
|
/* the input is a must. at least 1 file or 1 string
|
|
|
|
* must be specified */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->s.out.x = out;
|
2015-09-02 08:43:43 +00:00
|
|
|
n = qse_xli_writeini (xli, root_list, sf_out);
|
2015-09-01 06:32:14 +00:00
|
|
|
|
|
|
|
if (out->type == QSE_XLI_IOSTD_STR)
|
|
|
|
{
|
|
|
|
if (n >= 0)
|
|
|
|
{
|
|
|
|
QSE_ASSERT (xtn->s.out.u.str.buf != QSE_NULL);
|
|
|
|
qse_str_yield (xtn->s.out.u.str.buf, &out->u.str, 0);
|
|
|
|
}
|
|
|
|
if (xtn->s.out.u.str.buf) qse_str_close (xtn->s.out.u.str.buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
2018-01-09 10:45:43 +00:00
|
|
|
|
|
|
|
int qse_xli_writejsonstd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iostd_t* out)
|
|
|
|
{
|
|
|
|
int n;
|
2019-06-24 14:24:14 +00:00
|
|
|
xtn_t* xtn = GET_XTN(xli);
|
2018-01-09 10:45:43 +00:00
|
|
|
|
|
|
|
if (out == QSE_NULL || (out->type != QSE_XLI_IOSTD_FILE &&
|
|
|
|
out->type != QSE_XLI_IOSTD_STR))
|
|
|
|
{
|
|
|
|
/* the input is a must. at least 1 file or 1 string
|
|
|
|
* must be specified */
|
|
|
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtn->s.out.x = out;
|
|
|
|
n = qse_xli_writejson (xli, root_list, sf_out);
|
|
|
|
|
|
|
|
if (out->type == QSE_XLI_IOSTD_STR)
|
|
|
|
{
|
|
|
|
if (n >= 0)
|
|
|
|
{
|
|
|
|
QSE_ASSERT (xtn->s.out.u.str.buf != QSE_NULL);
|
|
|
|
qse_str_yield (xtn->s.out.u.str.buf, &out->u.str, 0);
|
|
|
|
}
|
|
|
|
if (xtn->s.out.u.str.buf) qse_str_close (xtn->s.out.u.str.buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|