reverted previous 2 commits for support json format in xli.
instead, i'm writing a different json format reader
This commit is contained in:
parent
6237b43441
commit
779b335710
@ -58,6 +58,8 @@
|
|||||||
|
|
||||||
#define IO_FLAG_INI_INPUT (1 << 0)
|
#define IO_FLAG_INI_INPUT (1 << 0)
|
||||||
#define IO_FLAG_INI_OUTPUT (1 << 1)
|
#define IO_FLAG_INI_OUTPUT (1 << 1)
|
||||||
|
#define IO_FLAG_JSON_INPUT (1 << 2)
|
||||||
|
#define IO_FLAG_JSON_OUTPUT (1 << 3)
|
||||||
|
|
||||||
static int g_io_flags = 0;
|
static int g_io_flags = 0;
|
||||||
static qse_char_t* g_input_file = QSE_NULL;
|
static qse_char_t* g_input_file = QSE_NULL;
|
||||||
@ -158,6 +160,8 @@ static void print_usage (qse_sio_t* out, int argc, qse_char_t* argv[])
|
|||||||
qse_fprintf (out, QSE_T(" -o file specify an output file\n"));
|
qse_fprintf (out, QSE_T(" -o file specify an output file\n"));
|
||||||
qse_fprintf (out, QSE_T(" -I file specify an ini input file\n"));
|
qse_fprintf (out, QSE_T(" -I file specify an ini input file\n"));
|
||||||
qse_fprintf (out, QSE_T(" -O file specify an ini output file\n"));
|
qse_fprintf (out, QSE_T(" -O file specify an ini output file\n"));
|
||||||
|
qse_fprintf (out, QSE_T(" -j file specify a json input file\n"));
|
||||||
|
qse_fprintf (out, QSE_T(" -J file specify a json output file\n"));
|
||||||
qse_fprintf (out, QSE_T(" -u disallow duplicate keys\n"));
|
qse_fprintf (out, QSE_T(" -u disallow duplicate keys\n"));
|
||||||
qse_fprintf (out, QSE_T(" -a allow a key alias\n"));
|
qse_fprintf (out, QSE_T(" -a allow a key alias\n"));
|
||||||
qse_fprintf (out, QSE_T(" -f keep file inclusion info\n"));
|
qse_fprintf (out, QSE_T(" -f keep file inclusion info\n"));
|
||||||
@ -168,7 +172,6 @@ static void print_usage (qse_sio_t* out, int argc, qse_char_t* argv[])
|
|||||||
qse_fprintf (out, QSE_T(" -l disallow lists\n"));
|
qse_fprintf (out, QSE_T(" -l disallow lists\n"));
|
||||||
qse_fprintf (out, QSE_T(" -K allow key tags\n"));
|
qse_fprintf (out, QSE_T(" -K allow key tags\n"));
|
||||||
qse_fprintf (out, QSE_T(" -S allow string tags\n"));
|
qse_fprintf (out, QSE_T(" -S allow string tags\n"));
|
||||||
qse_fprintf (out, QSE_T(" -j input and output in json format\n"));
|
|
||||||
qse_fprintf (out, QSE_T(" -v perform validation\n"));
|
qse_fprintf (out, QSE_T(" -v perform validation\n"));
|
||||||
qse_fprintf (out, QSE_T(" -m number specify the maximum amount of memory to use in bytes\n"));
|
qse_fprintf (out, QSE_T(" -m number specify the maximum amount of memory to use in bytes\n"));
|
||||||
#if defined(QSE_BUILD_DEBUG)
|
#if defined(QSE_BUILD_DEBUG)
|
||||||
@ -196,15 +199,15 @@ static int handle_args (int argc, qse_char_t* argv[])
|
|||||||
static qse_opt_t opt =
|
static qse_opt_t opt =
|
||||||
{
|
{
|
||||||
#if defined(QSE_BUILD_DEBUG)
|
#if defined(QSE_BUILD_DEBUG)
|
||||||
QSE_T("hi:o:I:O:uaftsdnlKSjvm:X:"),
|
QSE_T("hi:o:I:O:j:J:uaftsdnlKSvm:X:"),
|
||||||
#else
|
#else
|
||||||
QSE_T("hi:o:I:O:uaftsdnlKSjvm:"),
|
QSE_T("hi:o:I:O:j:J:uaftsdnlKSvm:"),
|
||||||
#endif
|
#endif
|
||||||
lng
|
lng
|
||||||
};
|
};
|
||||||
qse_cint_t c;
|
qse_cint_t c;
|
||||||
|
|
||||||
while ((c = qse_getopt (argc, argv, &opt)) != QSE_CHAR_EOF)
|
while ((c = qse_getopt(argc, argv, &opt)) != QSE_CHAR_EOF)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -234,7 +237,7 @@ static int handle_args (int argc, qse_char_t* argv[])
|
|||||||
|
|
||||||
case QSE_T('i'):
|
case QSE_T('i'):
|
||||||
g_input_file = opt.arg;
|
g_input_file = opt.arg;
|
||||||
g_io_flags &= ~IO_FLAG_INI_INPUT;
|
g_io_flags &= ~(IO_FLAG_INI_INPUT | IO_FLAG_JSON_OUTPUT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_T('I'):
|
case QSE_T('I'):
|
||||||
@ -242,9 +245,14 @@ static int handle_args (int argc, qse_char_t* argv[])
|
|||||||
g_io_flags |= IO_FLAG_INI_INPUT;
|
g_io_flags |= IO_FLAG_INI_INPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QSE_T('j'):
|
||||||
|
g_input_file = opt.arg;
|
||||||
|
g_io_flags |= IO_FLAG_JSON_INPUT;
|
||||||
|
break;
|
||||||
|
|
||||||
case QSE_T('o'):
|
case QSE_T('o'):
|
||||||
g_output_file = opt.arg;
|
g_output_file = opt.arg;
|
||||||
g_io_flags &= ~IO_FLAG_INI_OUTPUT;
|
g_io_flags &= ~(IO_FLAG_INI_OUTPUT | IO_FLAG_JSON_OUTPUT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_T('O'):
|
case QSE_T('O'):
|
||||||
@ -252,6 +260,11 @@ static int handle_args (int argc, qse_char_t* argv[])
|
|||||||
g_io_flags |= IO_FLAG_INI_OUTPUT;
|
g_io_flags |= IO_FLAG_INI_OUTPUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QSE_T('J'):
|
||||||
|
g_output_file = opt.arg;
|
||||||
|
g_io_flags |= IO_FLAG_JSON_OUTPUT;
|
||||||
|
break;
|
||||||
|
|
||||||
case QSE_T('u'):
|
case QSE_T('u'):
|
||||||
g_trait |= QSE_XLI_KEYNODUP;
|
g_trait |= QSE_XLI_KEYNODUP;
|
||||||
break;
|
break;
|
||||||
@ -292,10 +305,6 @@ static int handle_args (int argc, qse_char_t* argv[])
|
|||||||
g_trait |= QSE_XLI_STRTAG;
|
g_trait |= QSE_XLI_STRTAG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_T('j'):
|
|
||||||
g_trait |= QSE_XLI_JSON;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QSE_T('v'):
|
case QSE_T('v'):
|
||||||
g_trait |= QSE_XLI_VALIDATE;
|
g_trait |= QSE_XLI_VALIDATE;
|
||||||
break;
|
break;
|
||||||
@ -444,7 +453,9 @@ static int xli_main (int argc, qse_char_t* argv[])
|
|||||||
in.u.file.path = g_input_file;
|
in.u.file.path = g_input_file;
|
||||||
in.u.file.cmgr = g_infile_cmgr;
|
in.u.file.cmgr = g_infile_cmgr;
|
||||||
|
|
||||||
n = (g_io_flags & IO_FLAG_INI_INPUT)? qse_xli_readinistd(xli, &in): qse_xli_readstd(xli, &in);
|
n = (g_io_flags & IO_FLAG_JSON_INPUT)? qse_xli_readjsonstd(xli, &in):
|
||||||
|
(g_io_flags & IO_FLAG_INI_INPUT)? qse_xli_readinistd(xli, &in):
|
||||||
|
qse_xli_readstd(xli, &in);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
const qse_xli_loc_t* errloc;
|
const qse_xli_loc_t* errloc;
|
||||||
@ -553,8 +564,9 @@ static int xli_main (int argc, qse_char_t* argv[])
|
|||||||
out.u.file.path = g_output_file? g_output_file: QSE_T("-");
|
out.u.file.path = g_output_file? g_output_file: QSE_T("-");
|
||||||
out.u.file.cmgr = g_outfile_cmgr;
|
out.u.file.cmgr = g_outfile_cmgr;
|
||||||
|
|
||||||
ret = (g_io_flags & IO_FLAG_INI_OUTPUT)? qse_xli_writeinistd(xli, QSE_NULL, &out): qse_xli_writestd(xli, QSE_NULL, &out);
|
ret = (g_io_flags & IO_FLAG_JSON_OUTPUT)? qse_xli_writejsonstd(xli, QSE_NULL, &out):
|
||||||
|
(g_io_flags & IO_FLAG_INI_OUTPUT)? qse_xli_writeinistd(xli, QSE_NULL, &out):
|
||||||
|
qse_xli_writestd(xli, QSE_NULL, &out);
|
||||||
oops:
|
oops:
|
||||||
if (xli) qse_xli_close (xli);
|
if (xli) qse_xli_close (xli);
|
||||||
if (xma_mmgr.ctx) qse_xma_close (xma_mmgr.ctx);
|
if (xma_mmgr.ctx) qse_xma_close (xma_mmgr.ctx);
|
||||||
|
@ -134,6 +134,12 @@ QSE_EXPORT int qse_xli_readinistd (
|
|||||||
qse_xli_iostd_t* in
|
qse_xli_iostd_t* in
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_xli_readjsonstd (
|
||||||
|
qse_xli_t* xli,
|
||||||
|
qse_xli_iostd_t* in
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
QSE_EXPORT int qse_xli_writestd (
|
QSE_EXPORT int qse_xli_writestd (
|
||||||
qse_xli_t* xli,
|
qse_xli_t* xli,
|
||||||
qse_xli_list_t* root_list,
|
qse_xli_list_t* root_list,
|
||||||
@ -146,6 +152,12 @@ QSE_EXPORT int qse_xli_writeinistd (
|
|||||||
qse_xli_iostd_t* out
|
qse_xli_iostd_t* out
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_xli_writejsonstd (
|
||||||
|
qse_xli_t* xli,
|
||||||
|
qse_xli_list_t* root_list,
|
||||||
|
qse_xli_iostd_t* out
|
||||||
|
);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,10 +65,12 @@ enum qse_xli_errnum_t
|
|||||||
QSE_XLI_EIOUSR, /**< i/o handler error */
|
QSE_XLI_EIOUSR, /**< i/o handler error */
|
||||||
|
|
||||||
QSE_XLI_ESYNTAX, /**< syntax error */
|
QSE_XLI_ESYNTAX, /**< syntax error */
|
||||||
|
QSE_XLI_ECOLON, /**< colon expected in place of '${0}' */
|
||||||
QSE_XLI_ESCOLON, /**< semicolon expected in place of '${0}' */
|
QSE_XLI_ESCOLON, /**< semicolon expected in place of '${0}' */
|
||||||
QSE_XLI_EASSIGN, /**< = expected in place of '${0}' */
|
QSE_XLI_EEQ, /**< = expected in place of '${0}' */
|
||||||
QSE_XLI_ELBREQ, /**< { or = expected in place of '${0}' */
|
QSE_XLI_ELBREQ, /**< { or = expected in place of '${0}' */
|
||||||
QSE_XLI_ERBRCE, /**< } expected in place of '${0}' */
|
QSE_XLI_ERBRACE, /**< } expected in place of '${0}' */
|
||||||
|
QSE_XLI_ERBRACK, /**< ] expected in place of '${0}' */
|
||||||
QSE_XLI_EPAVAL, /**< pair value expected in place of '${0}' */
|
QSE_XLI_EPAVAL, /**< pair value expected in place of '${0}' */
|
||||||
QSE_XLI_ESTRNC, /**< string not closed */
|
QSE_XLI_ESTRNC, /**< string not closed */
|
||||||
QSE_XLI_ETAGNC, /**< tag not closed */
|
QSE_XLI_ETAGNC, /**< tag not closed */
|
||||||
@ -115,18 +117,7 @@ enum qse_xli_opt_t
|
|||||||
*/
|
*/
|
||||||
QSE_XLI_ROOTXTNSIZE,
|
QSE_XLI_ROOTXTNSIZE,
|
||||||
|
|
||||||
/**
|
QSE_XLI_KEYSPLITTER
|
||||||
* It is a character to put between a parent key and a nested key.
|
|
||||||
* By default, it's a period and used like 'a.b.c' that means c under b under a.
|
|
||||||
*/
|
|
||||||
QSE_XLI_KEYSPLITTER,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The first character is in the tag marker speicifies the tag opener
|
|
||||||
* and the second chracter specifies the tag closer. The are used when
|
|
||||||
* key tags and/or string tags are enabled. By default, it is "[]".
|
|
||||||
*/
|
|
||||||
QSE_XLI_TAGMARKER
|
|
||||||
};
|
};
|
||||||
typedef enum qse_xli_opt_t qse_xli_opt_t;
|
typedef enum qse_xli_opt_t qse_xli_opt_t;
|
||||||
|
|
||||||
@ -156,19 +147,14 @@ enum qse_xli_trait_t
|
|||||||
* "tg" is stored into the tag field of qse_xli_str_t. */
|
* "tg" is stored into the tag field of qse_xli_str_t. */
|
||||||
QSE_XLI_STRTAG = (1 << 10),
|
QSE_XLI_STRTAG = (1 << 10),
|
||||||
|
|
||||||
/** support the json format */
|
|
||||||
QSE_XLI_JSON = (1 << 11),
|
|
||||||
|
|
||||||
/** enable pair validation against pair definitions while reading */
|
/** enable pair validation against pair definitions while reading */
|
||||||
QSE_XLI_VALIDATE = (1 << 12)
|
QSE_XLI_VALIDATE = (1 << 11)
|
||||||
};
|
};
|
||||||
typedef enum qse_xli_trait_t qse_xli_trait_t;
|
typedef enum qse_xli_trait_t qse_xli_trait_t;
|
||||||
|
|
||||||
typedef struct qse_xli_val_t qse_xli_val_t;
|
typedef struct qse_xli_val_t qse_xli_val_t;
|
||||||
typedef struct qse_xli_nil_t qse_xli_nil_t;
|
typedef struct qse_xli_nil_t qse_xli_nil_t;
|
||||||
typedef struct qse_xli_str_t qse_xli_str_t;
|
typedef struct qse_xli_str_t qse_xli_str_t;
|
||||||
typedef struct qse_xli_int_t qse_xli_int_t;
|
|
||||||
typedef struct qse_xli_array_t qse_xli_array_t;
|
|
||||||
typedef struct qse_xli_list_t qse_xli_list_t;
|
typedef struct qse_xli_list_t qse_xli_list_t;
|
||||||
|
|
||||||
typedef struct qse_xli_atom_t qse_xli_atom_t;
|
typedef struct qse_xli_atom_t qse_xli_atom_t;
|
||||||
@ -223,26 +209,6 @@ struct qse_xli_str_t
|
|||||||
qse_xli_str_t* next;
|
qse_xli_str_t* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qse_xli_int_t
|
|
||||||
{
|
|
||||||
QSE_XLI_VAL_HDR;
|
|
||||||
const qse_char_t* tag;
|
|
||||||
const qse_char_t* ptr;
|
|
||||||
qse_size_t len;
|
|
||||||
/* TODO: include a numeric value here???
|
|
||||||
qse_intmax_t val;
|
|
||||||
*/
|
|
||||||
/* NEED TO SUPPORT MULTI NUBMER? */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct qse_xli_array_t
|
|
||||||
{
|
|
||||||
QSE_XLI_VAL_HDR;
|
|
||||||
const qse_char_t* tag;
|
|
||||||
qse_xli_val_t* ptr;
|
|
||||||
qse_size_t count;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define QSE_XLI_ATOM_HDR \
|
#define QSE_XLI_ATOM_HDR \
|
||||||
qse_xli_atom_type_t type; \
|
qse_xli_atom_type_t type; \
|
||||||
qse_xli_atom_t* prev; \
|
qse_xli_atom_t* prev; \
|
||||||
@ -261,8 +227,6 @@ struct qse_xli_pair_t
|
|||||||
const qse_char_t* key;
|
const qse_char_t* key;
|
||||||
const qse_char_t* alias;
|
const qse_char_t* alias;
|
||||||
const qse_char_t* tag;
|
const qse_char_t* tag;
|
||||||
unsigned int _key_quoted: 2; /* used internally for output */
|
|
||||||
unsigned int _alias_quoted: 2; /* used internally for output - in fact, an alias is always quoted */
|
|
||||||
qse_xli_val_t* val;
|
qse_xli_val_t* val;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -404,10 +368,9 @@ enum qse_xli_scm_flag_t
|
|||||||
QSE_XLI_SCM_VALNIL = (1 << 1),
|
QSE_XLI_SCM_VALNIL = (1 << 1),
|
||||||
QSE_XLI_SCM_VALSTR = (1 << 2),
|
QSE_XLI_SCM_VALSTR = (1 << 2),
|
||||||
QSE_XLI_SCM_VALLIST = (1 << 3),
|
QSE_XLI_SCM_VALLIST = (1 << 3),
|
||||||
QSE_XLI_SCM_VALARRAY = (1 << 4),
|
|
||||||
|
|
||||||
QSE_XLI_SCM_KEYNODUP = (1 << 5),
|
QSE_XLI_SCM_KEYNODUP = (1 << 4),
|
||||||
QSE_XLI_SCM_KEYALIAS = (1 << 6),
|
QSE_XLI_SCM_KEYALIAS = (1 << 5),
|
||||||
|
|
||||||
/** Indicates that the value is a list with uncertain definitions with
|
/** Indicates that the value is a list with uncertain definitions with
|
||||||
* the following constraints:
|
* the following constraints:
|
||||||
@ -418,7 +381,7 @@ enum qse_xli_scm_flag_t
|
|||||||
* is specified.
|
* is specified.
|
||||||
*
|
*
|
||||||
* Applies only if #QSE_XLI_SCM_VALLIST is set. */
|
* Applies only if #QSE_XLI_SCM_VALLIST is set. */
|
||||||
QSE_XLI_SCM_VALIFFY = (1 << 7)
|
QSE_XLI_SCM_VALIFFY = (1 << 6)
|
||||||
};
|
};
|
||||||
typedef enum qse_xli_scm_flag_t qse_xli_scm_flag_t;
|
typedef enum qse_xli_scm_flag_t qse_xli_scm_flag_t;
|
||||||
|
|
||||||
@ -786,6 +749,11 @@ QSE_EXPORT int qse_xli_readini (
|
|||||||
qse_xli_io_impl_t io
|
qse_xli_io_impl_t io
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_xli_readjson (
|
||||||
|
qse_xli_t* xli,
|
||||||
|
qse_xli_io_impl_t io
|
||||||
|
);
|
||||||
|
|
||||||
QSE_EXPORT int qse_xli_write (
|
QSE_EXPORT int qse_xli_write (
|
||||||
qse_xli_t* xli,
|
qse_xli_t* xli,
|
||||||
qse_xli_list_t* root_list,
|
qse_xli_list_t* root_list,
|
||||||
@ -798,6 +766,12 @@ QSE_EXPORT int qse_xli_writeini (
|
|||||||
qse_xli_io_impl_t io
|
qse_xli_io_impl_t io
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_xli_writejson (
|
||||||
|
qse_xli_t* xli,
|
||||||
|
qse_xli_list_t* root_list,
|
||||||
|
qse_xli_io_impl_t io
|
||||||
|
);
|
||||||
|
|
||||||
QSE_EXPORT void* qse_getxlipairxtn (
|
QSE_EXPORT void* qse_getxlipairxtn (
|
||||||
qse_xli_pair_t* pair
|
qse_xli_pair_t* pair
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,10 @@ AM_CPPFLAGS = \
|
|||||||
-I$(top_srcdir)/include
|
-I$(top_srcdir)/include
|
||||||
|
|
||||||
lib_LTLIBRARIES = libqsexli.la
|
lib_LTLIBRARIES = libqsexli.la
|
||||||
libqsexli_la_SOURCES = xli.h xli.c err.c read.c read-ini.c write.c write-ini.c std.c
|
libqsexli_la_SOURCES = xli.h xli.c err.c \
|
||||||
|
read.c read-ini.c read-json.c \
|
||||||
|
write.c write-ini.c write-json.c \
|
||||||
|
std.c
|
||||||
libqsexli_la_LDFLAGS = -L../cmn -L../si -version-info 1:0:0 -no-undefined
|
libqsexli_la_LDFLAGS = -L../cmn -L../si -version-info 1:0:0 -no-undefined
|
||||||
libqsexli_la_LIBADD = -lqsesi -lqsecmn
|
libqsexli_la_LIBADD = -lqsesi -lqsecmn
|
||||||
|
|
||||||
|
@ -135,8 +135,8 @@ am__uninstall_files_from_dir = { \
|
|||||||
am__installdirs = "$(DESTDIR)$(libdir)"
|
am__installdirs = "$(DESTDIR)$(libdir)"
|
||||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||||
libqsexli_la_DEPENDENCIES =
|
libqsexli_la_DEPENDENCIES =
|
||||||
am_libqsexli_la_OBJECTS = xli.lo err.lo read.lo read-ini.lo write.lo \
|
am_libqsexli_la_OBJECTS = xli.lo err.lo read.lo read-ini.lo \
|
||||||
write-ini.lo std.lo
|
read-json.lo write.lo write-ini.lo write-json.lo std.lo
|
||||||
libqsexli_la_OBJECTS = $(am_libqsexli_la_OBJECTS)
|
libqsexli_la_OBJECTS = $(am_libqsexli_la_OBJECTS)
|
||||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||||
@ -393,7 +393,11 @@ AM_CPPFLAGS = \
|
|||||||
-I$(top_srcdir)/include
|
-I$(top_srcdir)/include
|
||||||
|
|
||||||
lib_LTLIBRARIES = libqsexli.la
|
lib_LTLIBRARIES = libqsexli.la
|
||||||
libqsexli_la_SOURCES = xli.h xli.c err.c read.c read-ini.c write.c write-ini.c std.c
|
libqsexli_la_SOURCES = xli.h xli.c err.c \
|
||||||
|
read.c read-ini.c read-json.c \
|
||||||
|
write.c write-ini.c write-json.c \
|
||||||
|
std.c
|
||||||
|
|
||||||
libqsexli_la_LDFLAGS = -L../cmn -L../si -version-info 1:0:0 -no-undefined
|
libqsexli_la_LDFLAGS = -L../cmn -L../si -version-info 1:0:0 -no-undefined
|
||||||
libqsexli_la_LIBADD = -lqsesi -lqsecmn
|
libqsexli_la_LIBADD = -lqsesi -lqsecmn
|
||||||
all: all-am
|
all: all-am
|
||||||
@ -476,9 +480,11 @@ distclean-compile:
|
|||||||
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read-ini.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read-ini.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read-json.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/std.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/std.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write-ini.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write-ini.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write-json.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xli.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xli.Plo@am__quote@
|
||||||
|
|
||||||
|
@ -27,8 +27,7 @@
|
|||||||
#include "xli.h"
|
#include "xli.h"
|
||||||
#include "../cmn/mem-prv.h"
|
#include "../cmn/mem-prv.h"
|
||||||
|
|
||||||
const qse_char_t* qse_xli_dflerrstr (
|
const qse_char_t* qse_xli_dflerrstr (const qse_xli_t* xli, qse_xli_errnum_t errnum)
|
||||||
const qse_xli_t* xli, qse_xli_errnum_t errnum)
|
|
||||||
{
|
{
|
||||||
static const qse_char_t* errstr[] =
|
static const qse_char_t* errstr[] =
|
||||||
{
|
{
|
||||||
@ -46,10 +45,12 @@ const qse_char_t* qse_xli_dflerrstr (
|
|||||||
QSE_T("error returned by user I/O handler"),
|
QSE_T("error returned by user I/O handler"),
|
||||||
|
|
||||||
QSE_T("syntax error"),
|
QSE_T("syntax error"),
|
||||||
|
QSE_T("colon expected in place of '${0}'"),
|
||||||
QSE_T("semicolon expected in place of '${0}'"),
|
QSE_T("semicolon expected in place of '${0}'"),
|
||||||
QSE_T("assignment symbol expected in place of '${0}'"),
|
QSE_T("equal-sign expected in place of '${0}'"),
|
||||||
QSE_T("left-brace or assignment token expected in place of '${0}'"),
|
QSE_T("left-brace or equal-sign expected in place of '${0}'"),
|
||||||
QSE_T("right-brace expected in place of '${0}'"),
|
QSE_T("right-brace expected in place of '${0}'"),
|
||||||
|
QSE_T("right-bracket expected in place of '${0}'"),
|
||||||
QSE_T("pair value expected in place of '${0}'"),
|
QSE_T("pair value expected in place of '${0}'"),
|
||||||
QSE_T("string not closed"),
|
QSE_T("string not closed"),
|
||||||
QSE_T("string tag not closed"),
|
QSE_T("string tag not closed"),
|
||||||
|
@ -378,7 +378,7 @@ static int read_list (qse_xli_t* xli)
|
|||||||
|
|
||||||
if (!MATCH(xli, QSE_XLI_TOK_EQ))
|
if (!MATCH(xli, QSE_XLI_TOK_EQ))
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_EASSIGN, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_EEQ, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
891
qse/lib/xli/read-json.c
Normal file
891
qse/lib/xli/read-json.c
Normal file
@ -0,0 +1,891 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xli.h"
|
||||||
|
#include <qse/cmn/chr.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
"key1" {
|
||||||
|
# comment
|
||||||
|
[keytag]key11 "alias" = [strtag]"test machine;
|
||||||
|
key1122 {
|
||||||
|
key112233 = "hello";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int get_token (qse_xli_t* xli);
|
||||||
|
static int read_list (qse_xli_t* xli, qse_xli_list_t* lv);
|
||||||
|
static int read_array (qse_xli_t* xli, qse_xli_list_t* lv);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TOK_STATUS_ENABLE_NSTR = (1 << 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GET_CHAR(xli) \
|
||||||
|
do { if (qse_xli_getchar(xli) <= -1) return -1; } while(0)
|
||||||
|
|
||||||
|
#define GET_CHAR_TO(xli,c) \
|
||||||
|
do { \
|
||||||
|
if (qse_xli_getchar(xli) <= -1) return -1; \
|
||||||
|
c = (xli)->rio.last.c; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define ADD_TOKEN_CHAR(xli,tok,c) \
|
||||||
|
do { \
|
||||||
|
if (qse_str_ccat((tok)->name,(c)) == (qse_size_t)-1) \
|
||||||
|
{ \
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define ADD_TOKEN_STR(xli,tok,s,l) \
|
||||||
|
do { \
|
||||||
|
if (qse_str_ncat((tok)->name,(s),(l)) == (qse_size_t)-1) \
|
||||||
|
{ \
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SET_TOKEN_TYPE(xli,tok,code) \
|
||||||
|
do { (tok)->type = (code); } while (0)
|
||||||
|
|
||||||
|
#define MATCH(xli,tok_type) ((xli)->tok.type == (tok_type))
|
||||||
|
|
||||||
|
typedef struct kwent_t kwent_t;
|
||||||
|
|
||||||
|
struct kwent_t
|
||||||
|
{
|
||||||
|
qse_cstr_t name;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* note that the keyword must start with @. */
|
||||||
|
static kwent_t kwtab[] =
|
||||||
|
{
|
||||||
|
/* keep it sorted by the first field for binary search */
|
||||||
|
{ { QSE_T("@include"), 8 }, QSE_XLI_TOK_XINCLUDE }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int skip_spaces (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
qse_cint_t c = xli->rio.last.c;
|
||||||
|
while (QSE_ISSPACE(c)) GET_CHAR_TO (xli, c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||||
|
{
|
||||||
|
qse_cint_t c = xli->rio.last.c;
|
||||||
|
|
||||||
|
if (c == QSE_T('#'))
|
||||||
|
{
|
||||||
|
/* skip up to \n */
|
||||||
|
|
||||||
|
qse_str_clear (tok->name);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
if (c == QSE_T('\n') || c == QSE_CHAR_EOF) break;
|
||||||
|
|
||||||
|
if (xli->opt.trait & QSE_XLI_KEEPTEXT) ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
}
|
||||||
|
while (1);
|
||||||
|
|
||||||
|
if ((xli->opt.trait & QSE_XLI_KEEPTEXT) &&
|
||||||
|
qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(tok->name)) == QSE_NULL) return -1;
|
||||||
|
|
||||||
|
GET_CHAR (xli); /* eat the new line letter */
|
||||||
|
return 1; /* comment by # */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
||||||
|
{
|
||||||
|
/* perform binary search */
|
||||||
|
|
||||||
|
/* declaring left, right, mid to be the int type is ok
|
||||||
|
* because we know kwtab is small enough. */
|
||||||
|
int left = 0, right = QSE_COUNTOF(kwtab) - 1, mid;
|
||||||
|
|
||||||
|
while (left <= right)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
kwent_t* kwp;
|
||||||
|
|
||||||
|
/*mid = (left + right) / 2;*/
|
||||||
|
mid = left + (right - left) / 2;
|
||||||
|
kwp = &kwtab[mid];
|
||||||
|
|
||||||
|
n = qse_strxncmp (kwp->name.ptr, kwp->name.len, name->ptr, name->len);
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
/* if left, right, mid were of qse_size_t,
|
||||||
|
* you would need the following line.
|
||||||
|
if (mid == 0) break;
|
||||||
|
*/
|
||||||
|
right = mid - 1;
|
||||||
|
}
|
||||||
|
else if (n < 0) left = mid + 1;
|
||||||
|
else return kwp->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSE_XLI_TOK_IDENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_symbols (qse_xli_t* xli, qse_cint_t c, qse_xli_tok_t* tok)
|
||||||
|
{
|
||||||
|
struct ops_t
|
||||||
|
{
|
||||||
|
const qse_char_t* str;
|
||||||
|
qse_size_t len;
|
||||||
|
int tid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ops_t ops[] =
|
||||||
|
{
|
||||||
|
{ QSE_T(","), 1, QSE_XLI_TOK_COMMA },
|
||||||
|
{ QSE_T(":"), 1, QSE_XLI_TOK_COLON },
|
||||||
|
{ QSE_T(";"), 1, QSE_XLI_TOK_SEMICOLON },
|
||||||
|
{ QSE_T("{"), 1, QSE_XLI_TOK_LBRACE },
|
||||||
|
{ QSE_T("}"), 1, QSE_XLI_TOK_RBRACE },
|
||||||
|
{ QSE_T("["), 1, QSE_XLI_TOK_LBRACK },
|
||||||
|
{ QSE_T("]"), 1, QSE_XLI_TOK_RBRACK },
|
||||||
|
{ QSE_NULL, 0, 0, }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ops_t* p;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
/* note that the loop below is not generaic enough.
|
||||||
|
* you must keep the operators strings in a particular order */
|
||||||
|
|
||||||
|
for (p = ops; p->str != QSE_NULL; )
|
||||||
|
{
|
||||||
|
if (p->str[idx] == QSE_T('\0'))
|
||||||
|
{
|
||||||
|
ADD_TOKEN_STR (xli, tok, p->str, p->len);
|
||||||
|
SET_TOKEN_TYPE (xli, tok, p->tid);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == p->str[idx])
|
||||||
|
{
|
||||||
|
idx++;
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int end_include (qse_xli_t* xli, int noeof)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
qse_xli_io_arg_t* cur;
|
||||||
|
|
||||||
|
if (xli->rio.inp == &xli->rio.top) return 0; /* no include */
|
||||||
|
|
||||||
|
|
||||||
|
/* if it is an included file, close it and
|
||||||
|
* retry to read a character from an outer file */
|
||||||
|
|
||||||
|
x = xli->rio.impl (
|
||||||
|
xli, QSE_XLI_IO_CLOSE,
|
||||||
|
xli->rio.inp, QSE_NULL, 0);
|
||||||
|
|
||||||
|
/* if closing has failed, still destroy the
|
||||||
|
* sio structure first as normal and return
|
||||||
|
* the failure below. this way, the caller
|
||||||
|
* does not call QSE_XLI_SIO_CLOSE on
|
||||||
|
* xli->rio.inp again. */
|
||||||
|
|
||||||
|
cur = xli->rio.inp;
|
||||||
|
xli->rio.inp = xli->rio.inp->prev;
|
||||||
|
|
||||||
|
QSE_ASSERT (cur->name != QSE_NULL);
|
||||||
|
QSE_MMGR_FREE (xli->mmgr, cur);
|
||||||
|
/* xli->parse.depth.incl--; */
|
||||||
|
|
||||||
|
if ((xli->opt.trait & QSE_XLI_KEEPFILE) && !noeof &&
|
||||||
|
qse_xli_inserteof (xli, xli->parlink->list, QSE_NULL) == QSE_NULL) return -1;
|
||||||
|
|
||||||
|
if (x != 0)
|
||||||
|
{
|
||||||
|
/* the failure mentioned above is returned here */
|
||||||
|
if (xli->errnum == QSE_XLI_ENOERR)
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_EIOUSR, QSE_NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xli->rio.last = xli->rio.inp->last;
|
||||||
|
return 1; /* ended the included file successfully */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int begin_include (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
qse_link_t* link;
|
||||||
|
qse_xli_io_arg_t* arg = QSE_NULL;
|
||||||
|
|
||||||
|
link = (qse_link_t*) qse_xli_callocmem (xli,
|
||||||
|
QSE_SIZEOF(*link) + QSE_SIZEOF(qse_char_t) * (QSE_STR_LEN(xli->tok.name) + 1));
|
||||||
|
if (link == QSE_NULL) goto oops;
|
||||||
|
|
||||||
|
qse_strncpy ((qse_char_t*)(link + 1), QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name));
|
||||||
|
link->link = xli->rio_names;
|
||||||
|
xli->rio_names = link;
|
||||||
|
|
||||||
|
arg = (qse_xli_io_arg_t*) qse_xli_callocmem (xli, QSE_SIZEOF(*arg));
|
||||||
|
if (arg == QSE_NULL) goto oops;
|
||||||
|
|
||||||
|
arg->name = (const qse_char_t*)(link + 1);
|
||||||
|
arg->line = 1;
|
||||||
|
arg->colm = 1;
|
||||||
|
|
||||||
|
/* let the argument's prev point field to the current */
|
||||||
|
arg->prev = xli->rio.inp;
|
||||||
|
|
||||||
|
if (qse_xli_openrstream(xli, arg) <= -1) goto oops;
|
||||||
|
|
||||||
|
/* i update the current pointer after opening is successful */
|
||||||
|
xli->rio.inp = arg;
|
||||||
|
/* xli->parse.depth.incl++; */
|
||||||
|
|
||||||
|
/* read in the first character in the included file.
|
||||||
|
* so the next call to get_token() sees the character read
|
||||||
|
* from this file. */
|
||||||
|
if (qse_xli_getchar (xli) <= -1 || get_token (xli) <= -1)
|
||||||
|
{
|
||||||
|
end_include (xli, 1);
|
||||||
|
/* i don't jump to oops since i've called
|
||||||
|
* end_include() where xli->rio.inp/arg is freed. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((xli->opt.trait & QSE_XLI_KEEPFILE) &&
|
||||||
|
qse_xli_insertfile (xli, xli->parlink->list, QSE_NULL, arg->name) == QSE_NULL)
|
||||||
|
{
|
||||||
|
end_include (xli, 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
/* i don't need to free 'link' since it's linked to
|
||||||
|
* xli->rio_names that's freed at the beginning of qse_xli_read()
|
||||||
|
* or by qse_xli_fini() */
|
||||||
|
if (arg) QSE_MMGR_FREE (xli->mmgr, arg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||||
|
{
|
||||||
|
qse_cint_t c;
|
||||||
|
int n;
|
||||||
|
int skip_semicolon_after_include = 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (skip_spaces (xli) <= -1) return -1;
|
||||||
|
if ((n = skip_comment (xli, tok)) <= -1) return -1;
|
||||||
|
}
|
||||||
|
while (n >= 1);
|
||||||
|
|
||||||
|
qse_str_clear (tok->name);
|
||||||
|
tok->loc.file = xli->rio.last.file;
|
||||||
|
tok->loc.line = xli->rio.last.line;
|
||||||
|
tok->loc.colm = xli->rio.last.colm;
|
||||||
|
|
||||||
|
c = xli->rio.last.c;
|
||||||
|
|
||||||
|
if (c == QSE_CHAR_EOF)
|
||||||
|
{
|
||||||
|
n = end_include (xli, 0);
|
||||||
|
if (n <= -1) return -1;
|
||||||
|
if (n >= 1)
|
||||||
|
{
|
||||||
|
/*xli->rio.last = xli->rio.inp->last;*/
|
||||||
|
/* mark that i'm retrying after end of an included file */
|
||||||
|
skip_semicolon_after_include = 1;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_TOKEN_STR (xli, tok, QSE_T("<EOF>"), 5);
|
||||||
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_EOF);
|
||||||
|
}
|
||||||
|
else if (c == QSE_T('@'))
|
||||||
|
{
|
||||||
|
/* keyword/directive - start with @ */
|
||||||
|
|
||||||
|
int type;
|
||||||
|
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
|
if (!QSE_ISALPHA (c))
|
||||||
|
{
|
||||||
|
/* this directive is empty, not followed by a valid word */
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EXKWEM, QSE_NULL, &tok->loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expect an identifier starting with an alphabet. the identifier
|
||||||
|
* forming a keyword/directory is composed of alphabets. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
}
|
||||||
|
while (QSE_ISALPHA (c));
|
||||||
|
|
||||||
|
type = classify_ident (xli, QSE_STR_XSTR(tok->name));
|
||||||
|
if (type == QSE_XLI_TOK_IDENT)
|
||||||
|
{
|
||||||
|
/* this keyword/directive is not recognized */
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EXKWNR, QSE_STR_XSTR(tok->name), &tok->loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SET_TOKEN_TYPE (xli, tok, type);
|
||||||
|
}
|
||||||
|
else if (c == QSE_T('_') || QSE_ISALPHA (c) ||
|
||||||
|
(!(xli->tok_status & TOK_STATUS_ENABLE_NSTR) &&
|
||||||
|
(xli->opt.trait & QSE_XLI_LEADDIGIT) &&
|
||||||
|
QSE_ISDIGIT(c)))
|
||||||
|
{
|
||||||
|
int lead_digit = QSE_ISDIGIT(c);
|
||||||
|
int all_digits = 1;
|
||||||
|
|
||||||
|
/* a normal identifier can be composed of wider varieties of
|
||||||
|
* characters than a keyword/directive */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
|
if (c == QSE_T('_') || c == QSE_T('-') || c == QSE_T('*') ||
|
||||||
|
c == QSE_T('/') || QSE_ISALPHA (c))
|
||||||
|
{
|
||||||
|
all_digits = 0;
|
||||||
|
}
|
||||||
|
else if (QSE_ISDIGIT(c))
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lead_digit && all_digits)
|
||||||
|
{
|
||||||
|
/* if an identifier begins with a digit, it must contain a non-digits character */
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EIDENT, QSE_STR_XSTR(tok->name), &tok->loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_IDENT);
|
||||||
|
}
|
||||||
|
else if ((xli->tok_status & TOK_STATUS_ENABLE_NSTR) && QSE_ISDIGIT(c))
|
||||||
|
{
|
||||||
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_NSTR);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
}
|
||||||
|
while (QSE_ISDIGIT(c));
|
||||||
|
}
|
||||||
|
else if (c == QSE_T('\''))
|
||||||
|
{
|
||||||
|
/* single-quoted string - no escaping */
|
||||||
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_SQSTR);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
|
if (c == QSE_CHAR_EOF)
|
||||||
|
{
|
||||||
|
/* the string is not closed */
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ESTRNC, QSE_NULL, &tok->loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == QSE_T('\''))
|
||||||
|
{
|
||||||
|
/* terminating quote */
|
||||||
|
GET_CHAR (xli);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == QSE_T('\"'))
|
||||||
|
{
|
||||||
|
/* double-quoted string - support escaping */
|
||||||
|
int escaped = 0;
|
||||||
|
|
||||||
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_DQSTR);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
|
if (c == QSE_CHAR_EOF)
|
||||||
|
{
|
||||||
|
/* the string is not closed */
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ESTRNC, QSE_NULL, &tok->loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!escaped)
|
||||||
|
{
|
||||||
|
if (c == QSE_T('\\'))
|
||||||
|
{
|
||||||
|
escaped = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == QSE_T('\"'))
|
||||||
|
{
|
||||||
|
/* terminating quote */
|
||||||
|
GET_CHAR (xli);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
|
escaped = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = get_symbols (xli, c, tok);
|
||||||
|
if (n <= -1) return -1; /* hard failure */
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
/* not handled yet */
|
||||||
|
if (c == QSE_T('\0'))
|
||||||
|
{
|
||||||
|
qse_cstr_t ea;
|
||||||
|
ea.ptr = QSE_T("<NUL>");
|
||||||
|
ea.len = 5;
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ELXCHR, &ea, &tok->loc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_char_t cc = (qse_char_t)c;
|
||||||
|
qse_cstr_t ea;
|
||||||
|
ea.ptr = &cc;
|
||||||
|
ea.len = 1;
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ELXCHR, &ea, &tok->loc);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip_semicolon_after_include && tok->type == QSE_XLI_TOK_SEMICOLON)
|
||||||
|
{
|
||||||
|
/* this handles the optional semicolon after the
|
||||||
|
* included file named as in @include "file-name"; */
|
||||||
|
skip_semicolon_after_include = 0;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip_semicolon_after_include)
|
||||||
|
{
|
||||||
|
/* semiclon has not been skipped yet */
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ESCOLON, QSE_STR_XSTR(tok->name), &tok->loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("TOKEN: %ls\n",QSE_STR_PTR(tok->name));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_token (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
return get_token_into (xli, &xli->tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_token_for_key_eligibility (qse_xli_t* xli, qse_xli_list_t* parlist)
|
||||||
|
{
|
||||||
|
if (xli->opt.trait & QSE_XLI_KEYNODUP)
|
||||||
|
{
|
||||||
|
qse_xli_atom_t* atom;
|
||||||
|
|
||||||
|
/* find any key conflicts in the current scope */
|
||||||
|
/* TODO: optimization. no sequential search */
|
||||||
|
atom = parlist->tail;
|
||||||
|
while (atom)
|
||||||
|
{
|
||||||
|
if (atom->type == QSE_XLI_PAIR &&
|
||||||
|
qse_strcmp(((qse_xli_pair_t*)atom)->key, QSE_STR_PTR(xli->tok.name)) == 0)
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EEXIST, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
atom = atom->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_xli_val_t* __read_value (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_XINCLUDE))
|
||||||
|
{
|
||||||
|
if (get_token(xli) <= -1) return QSE_NULL;
|
||||||
|
|
||||||
|
if (!MATCH(xli,QSE_XLI_TOK_SQSTR) && !MATCH(xli,QSE_XLI_TOK_DQSTR))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EINCLSTR, QSE_NULL, &xli->tok.loc);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin_include(xli) <= -1) return QSE_NULL;
|
||||||
|
}
|
||||||
|
else if (/*MATCH(xli, QSE_XLI_TOK_IDENT) || */MATCH(xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||||
|
{
|
||||||
|
return (qse_xli_val_t*)qse_xli_makestrval(xli, QSE_STR_XSTR(xli->tok.name), QSE_NULL);
|
||||||
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_LBRACE))
|
||||||
|
{
|
||||||
|
qse_xli_list_t* lv;
|
||||||
|
|
||||||
|
lv = qse_xli_makelistval (xli);
|
||||||
|
if (!lv) return QSE_NULL;
|
||||||
|
|
||||||
|
if (get_token(xli) <= -1 || read_list(xli, lv) <= -1)
|
||||||
|
{
|
||||||
|
qse_xli_freeval (xli, (qse_xli_val_t*)lv);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (qse_xli_val_t*)lv;
|
||||||
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_LBRACK))
|
||||||
|
{
|
||||||
|
qse_xli_list_t* lv;
|
||||||
|
|
||||||
|
lv = qse_xli_makelistval (xli);
|
||||||
|
if (!lv) return QSE_NULL;
|
||||||
|
|
||||||
|
if (get_token(xli) <= -1 || read_array(xli, lv) <= -1)
|
||||||
|
if (!lv)
|
||||||
|
{
|
||||||
|
qse_xli_freeval (xli, (qse_xli_val_t*)lv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (qse_xli_val_t*)lv;
|
||||||
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
||||||
|
{
|
||||||
|
if (get_token(xli) <= -1) return QSE_NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct rpair_t
|
||||||
|
{
|
||||||
|
qse_char_t* key;
|
||||||
|
qse_xli_val_t* val;
|
||||||
|
};
|
||||||
|
typedef struct rpair_t rpair_t;
|
||||||
|
|
||||||
|
static int read_pair (qse_xli_t* xli, rpair_t* pair)
|
||||||
|
{
|
||||||
|
qse_char_t* key = QSE_NULL;
|
||||||
|
qse_xli_val_t* val = QSE_NULL;
|
||||||
|
|
||||||
|
if (check_token_for_key_eligibility(xli, xli->parlink->list) <= -1) goto oops;
|
||||||
|
|
||||||
|
key = qse_strdup(QSE_STR_PTR(xli->tok.name), xli->mmgr);
|
||||||
|
if (key == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_token(xli) <= -1) goto oops;
|
||||||
|
|
||||||
|
if (!MATCH(xli, QSE_XLI_TOK_COLON))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ECOLON, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_token(xli) <= -1) goto oops;
|
||||||
|
|
||||||
|
val = __read_value(xli);
|
||||||
|
if (!val) goto oops;
|
||||||
|
|
||||||
|
pair->key = key;
|
||||||
|
pair->val = val;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (val) qse_xli_freeval (xli, val);
|
||||||
|
if (key) QSE_MMGR_FREE (xli->mmgr, key);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __read_array (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
qse_xli_val_t* val;
|
||||||
|
qse_size_t index = 0;
|
||||||
|
qse_char_t key[64];
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
val = __read_value(xli);
|
||||||
|
if (!val) return -1;
|
||||||
|
|
||||||
|
qse_strxfmt (key, QSE_COUNTOF(key), QSE_T("%zu"), index);
|
||||||
|
if (!qse_xli_insertpair (xli, xli->parlink->list, QSE_NULL, key, QSE_NULL, QSE_NULL, val)) return -1;
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_COMMA))
|
||||||
|
{
|
||||||
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_RBRACK)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_array (qse_xli_t* xli, qse_xli_list_t* lv)
|
||||||
|
{
|
||||||
|
qse_xli_list_link_t* ll;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ll = qse_xli_makelistlink (xli, lv);
|
||||||
|
if (!ll) return -1;
|
||||||
|
|
||||||
|
n = __read_array(xli);
|
||||||
|
|
||||||
|
qse_xli_freelistlink (xli, ll);
|
||||||
|
|
||||||
|
if (n <= -1) return -1;
|
||||||
|
|
||||||
|
if (!MATCH(xli, QSE_XLI_TOK_RBRACK))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ERBRACK, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __read_list (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_XINCLUDE))
|
||||||
|
{
|
||||||
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
|
||||||
|
if (!MATCH(xli,QSE_XLI_TOK_SQSTR) && !MATCH(xli,QSE_XLI_TOK_DQSTR))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EINCLSTR, QSE_NULL, &xli->tok.loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin_include (xli) <= -1) return -1;
|
||||||
|
}
|
||||||
|
else if (/*MATCH(xli, QSE_XLI_TOK_IDENT) ||*/ MATCH(xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||||
|
{
|
||||||
|
rpair_t rpair;
|
||||||
|
if (read_pair(xli, &rpair) <= -1) return -1;
|
||||||
|
|
||||||
|
if (!qse_xli_insertpair (xli, xli->parlink->list, QSE_NULL, rpair.key, QSE_NULL, QSE_NULL, rpair.val))
|
||||||
|
{
|
||||||
|
QSE_MMGR_FREE (xli->mmgr, rpair.key);
|
||||||
|
qse_xli_freeval (xli, rpair.val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear the duplicated key. the key is also duplicated in qse_xli_insertpair(). don't need it */
|
||||||
|
QSE_MMGR_FREE (xli->mmgr, rpair.key);
|
||||||
|
|
||||||
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_COMMA))
|
||||||
|
{
|
||||||
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
||||||
|
{
|
||||||
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_list (qse_xli_t* xli, qse_xli_list_t* lv)
|
||||||
|
{
|
||||||
|
qse_xli_list_link_t* ll;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ll = qse_xli_makelistlink (xli, lv);
|
||||||
|
if (!ll) return -1;
|
||||||
|
|
||||||
|
n = __read_list(xli);
|
||||||
|
|
||||||
|
qse_xli_freelistlink (xli, ll);
|
||||||
|
|
||||||
|
if (n <= -1) return -1;
|
||||||
|
|
||||||
|
if (!MATCH(xli, QSE_XLI_TOK_RBRACE))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ERBRACE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_root_list (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
qse_xli_list_link_t* link;
|
||||||
|
|
||||||
|
link = qse_xli_makelistlink (xli, &xli->root->list);
|
||||||
|
if (!link) return -1;
|
||||||
|
|
||||||
|
if (qse_xli_getchar(xli) <= -1 || get_token(xli) <= -1 || __read_list(xli) <= -1)
|
||||||
|
{
|
||||||
|
qse_xli_freelistlink (xli, link);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_ASSERT (link == xli->parlink);
|
||||||
|
qse_xli_freelistlink (xli, link);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qse_xli_readjson (qse_xli_t* xli, qse_xli_io_impl_t io)
|
||||||
|
{
|
||||||
|
if (!io)
|
||||||
|
{
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MEMSET (&xli->rio, 0, QSE_SIZEOF(xli->rio));
|
||||||
|
xli->rio.impl = io;
|
||||||
|
xli->rio.top.line = 1;
|
||||||
|
xli->rio.top.colm = 1;
|
||||||
|
xli->rio.inp = &xli->rio.top;
|
||||||
|
|
||||||
|
xli->tok_status = 0;
|
||||||
|
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_ENOERR, QSE_NULL);
|
||||||
|
qse_xli_clearrionames (xli);
|
||||||
|
|
||||||
|
QSE_ASSERT (QSE_STR_LEN(xli->dotted_curkey) == 0);
|
||||||
|
|
||||||
|
if (qse_xli_openrstream (xli, xli->rio.inp) <= -1) return -1;
|
||||||
|
/* the input stream is open now */
|
||||||
|
|
||||||
|
if (read_root_list (xli) <= -1) goto oops;
|
||||||
|
|
||||||
|
QSE_ASSERT (xli->parlink == QSE_NULL);
|
||||||
|
|
||||||
|
if (!MATCH (xli, QSE_XLI_TOK_EOF))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_ASSERT (xli->rio.inp == &xli->rio.top);
|
||||||
|
qse_xli_closeactiverstream (xli);
|
||||||
|
qse_str_clear (xli->tok.name);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
/* an error occurred and control has reached here
|
||||||
|
* probably, some included files might not have been
|
||||||
|
* closed. close them */
|
||||||
|
while (xli->rio.inp != &xli->rio.top)
|
||||||
|
{
|
||||||
|
qse_xli_io_arg_t* prev;
|
||||||
|
|
||||||
|
/* nothing much to do about a close error */
|
||||||
|
qse_xli_closeactiverstream (xli);
|
||||||
|
|
||||||
|
prev = xli->rio.inp->prev;
|
||||||
|
QSE_ASSERT (xli->rio.inp->name != QSE_NULL);
|
||||||
|
QSE_MMGR_FREE (xli->mmgr, xli->rio.inp);
|
||||||
|
xli->rio.inp = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_xli_closeactiverstream (xli);
|
||||||
|
qse_str_clear (xli->tok.name);
|
||||||
|
return -1;
|
||||||
|
}
|
@ -27,20 +27,6 @@
|
|||||||
#include "xli.h"
|
#include "xli.h"
|
||||||
#include <qse/cmn/chr.h>
|
#include <qse/cmn/chr.h>
|
||||||
|
|
||||||
/*
|
|
||||||
"key1" {
|
|
||||||
# comment
|
|
||||||
[keytag]key11 "alias" = [strtag]"test machine;
|
|
||||||
key1122 {
|
|
||||||
key112233 = "hello";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static qse_char_t tag_opener[] = { QSE_T('['), QSE_T('(') };
|
|
||||||
static qse_char_t tag_closer[] = { QSE_T(']'), QSE_T(')') };
|
|
||||||
|
|
||||||
static int get_token (qse_xli_t* xli);
|
static int get_token (qse_xli_t* xli);
|
||||||
static int read_list (qse_xli_t* xli, qse_xli_list_t* list, const qse_xli_scm_t* override);
|
static int read_list (qse_xli_t* xli, qse_xli_list_t* list, const qse_xli_scm_t* override);
|
||||||
|
|
||||||
@ -307,37 +293,32 @@ static int get_symbols (qse_xli_t* xli, qse_cint_t c, qse_xli_tok_t* tok)
|
|||||||
{
|
{
|
||||||
const qse_char_t* str;
|
const qse_char_t* str;
|
||||||
qse_size_t len;
|
qse_size_t len;
|
||||||
int tid[2]; /* normal id, alternative id */
|
int tid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ops_t ops[] =
|
static struct ops_t ops[] =
|
||||||
{
|
{
|
||||||
{ QSE_T("="), 1, { QSE_XLI_TOK_EQ, QSE_XLI_TOK_COLON } },
|
{ QSE_T("="), 1, QSE_XLI_TOK_EQ },
|
||||||
{ QSE_T(":"), 1, { QSE_XLI_TOK_COLON, QSE_XLI_TOK_EQ } },
|
{ QSE_T(","), 1, QSE_XLI_TOK_COMMA },
|
||||||
{ QSE_T(","), 1, { QSE_XLI_TOK_COMMA, QSE_XLI_TOK_COMMA } },
|
{ QSE_T(";"), 1, QSE_XLI_TOK_SEMICOLON },
|
||||||
{ QSE_T(";"), 1, { QSE_XLI_TOK_SEMICOLON, QSE_XLI_TOK_SEMICOLON } },
|
{ QSE_T("{"), 1, QSE_XLI_TOK_LBRACE },
|
||||||
{ QSE_T("{"), 1, { QSE_XLI_TOK_LBRACE, QSE_XLI_TOK_LBRACE } },
|
{ QSE_T("}"), 1, QSE_XLI_TOK_RBRACE },
|
||||||
{ QSE_T("}"), 1, { QSE_XLI_TOK_RBRACE, QSE_XLI_TOK_RBRACE } },
|
{ QSE_NULL, 0, 0, }
|
||||||
{ QSE_T("["), 1, { QSE_XLI_TOK_LBRACK, QSE_XLI_TOK_LPAREN } },
|
|
||||||
{ QSE_T("]"), 1, { QSE_XLI_TOK_RBRACK, QSE_XLI_TOK_RPAREN } },
|
|
||||||
{ QSE_T("("), 1, { QSE_XLI_TOK_LPAREN, QSE_XLI_TOK_LBRACK } },
|
|
||||||
{ QSE_T(")"), 1, { QSE_XLI_TOK_RPAREN, QSE_XLI_TOK_RBRACK } },
|
|
||||||
{ QSE_NULL, 0, { 0, 0 } }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ops_t* p;
|
struct ops_t* p;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
int tid_mode = (xli->opt.trait & QSE_XLI_JSON)? 1: 0;
|
|
||||||
|
|
||||||
/* note that the loop below is not generaic enough.
|
/* note that the loop below is not generaic enough.
|
||||||
* you must keep the operators strings in a particular order */
|
* you must keep the operators strings in a particular order */
|
||||||
|
|
||||||
|
|
||||||
for (p = ops; p->str != QSE_NULL; )
|
for (p = ops; p->str != QSE_NULL; )
|
||||||
{
|
{
|
||||||
if (p->str[idx] == QSE_T('\0'))
|
if (p->str[idx] == QSE_T('\0'))
|
||||||
{
|
{
|
||||||
ADD_TOKEN_STR (xli, tok, p->str, p->len);
|
ADD_TOKEN_STR (xli, tok, p->str, p->len);
|
||||||
SET_TOKEN_TYPE (xli, tok, p->tid[tid_mode]);
|
SET_TOKEN_TYPE (xli, tok, p->tid);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +439,7 @@ oops:
|
|||||||
static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||||
{
|
{
|
||||||
qse_cint_t c;
|
qse_cint_t c;
|
||||||
int n, tag_mode = (xli->opt.trait & QSE_XLI_JSON)? 1: 0;
|
int n;
|
||||||
int skip_semicolon_after_include = 0;
|
int skip_semicolon_after_include = 0;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
@ -530,8 +511,6 @@ retry:
|
|||||||
(xli->opt.trait & QSE_XLI_LEADDIGIT) &&
|
(xli->opt.trait & QSE_XLI_LEADDIGIT) &&
|
||||||
QSE_ISDIGIT(c)))
|
QSE_ISDIGIT(c)))
|
||||||
{
|
{
|
||||||
/* if you change the rules here, you need to update
|
|
||||||
* need_quoting() in write.c */
|
|
||||||
int lead_digit = QSE_ISDIGIT(c);
|
int lead_digit = QSE_ISDIGIT(c);
|
||||||
int all_digits = 1;
|
int all_digits = 1;
|
||||||
|
|
||||||
@ -543,8 +522,8 @@ retry:
|
|||||||
GET_CHAR_TO (xli, c);
|
GET_CHAR_TO (xli, c);
|
||||||
|
|
||||||
if (c == QSE_T('_') || c == QSE_T('-') ||
|
if (c == QSE_T('_') || c == QSE_T('-') ||
|
||||||
(!(xli->opt.trait & QSE_XLI_JSON) && c == QSE_T(':')) ||
|
c == QSE_T(':') || c == QSE_T('*') ||
|
||||||
c == QSE_T('*') || c == QSE_T('/') || QSE_ISALPHA (c))
|
c == QSE_T('/') || QSE_ISALPHA (c))
|
||||||
{
|
{
|
||||||
all_digits = 0;
|
all_digits = 0;
|
||||||
}
|
}
|
||||||
@ -557,7 +536,7 @@ retry:
|
|||||||
|
|
||||||
if (lead_digit && all_digits)
|
if (lead_digit && all_digits)
|
||||||
{
|
{
|
||||||
/* if an identifier begins with a digit, it must contain a non-digit character */
|
/* if an identifier begins with a digit, it must contain a non-digits character */
|
||||||
qse_xli_seterror (xli, QSE_XLI_EIDENT, QSE_STR_XSTR(tok->name), &tok->loc);
|
qse_xli_seterror (xli, QSE_XLI_EIDENT, QSE_STR_XSTR(tok->name), &tok->loc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -642,15 +621,13 @@ retry:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((xli->opt.trait & (QSE_XLI_KEYTAG | QSE_XLI_STRTAG)) && c == tag_opener[tag_mode]) /* [ */
|
else if ((xli->opt.trait & (QSE_XLI_KEYTAG | QSE_XLI_STRTAG)) && c == QSE_T('['))
|
||||||
{
|
{
|
||||||
/* a string tag is a bracketed word placed in front of a string value.
|
/* a string tag is a bracketed word placed in front of a string value.
|
||||||
* A = [tg] "abc";
|
* A = [tg] "abc";
|
||||||
* "tg" is stored into the tag field of qse_xli_str_t.
|
* "tg" is stored into the tag field of qse_xli_str_t.
|
||||||
*
|
|
||||||
* however, the tag opener and the closer are not hard-coded. you may
|
|
||||||
* use a different opener and closer depending on your requirement.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_TAG);
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_TAG);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -664,7 +641,7 @@ retry:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == tag_closer[tag_mode]) /* ] */
|
if (c == QSE_T(']'))
|
||||||
{
|
{
|
||||||
/* terminating quote */
|
/* terminating quote */
|
||||||
GET_CHAR (xli);
|
GET_CHAR (xli);
|
||||||
@ -747,7 +724,6 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
|
|
||||||
const qse_xli_scm_t* scm = QSE_NULL;
|
const qse_xli_scm_t* scm = QSE_NULL;
|
||||||
int key_nodup = 0, key_alias = 0, val_iffy = 0;
|
int key_nodup = 0, key_alias = 0, val_iffy = 0;
|
||||||
/*int key_quoted = 0, alias_quoted = 0;*/
|
|
||||||
|
|
||||||
key.ptr = QSE_NULL;
|
key.ptr = QSE_NULL;
|
||||||
name = QSE_NULL;
|
name = QSE_NULL;
|
||||||
@ -759,11 +735,9 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
if (xli->opt.trait & QSE_XLI_KEYNODUP) key_nodup = 1;
|
if (xli->opt.trait & QSE_XLI_KEYNODUP) key_nodup = 1;
|
||||||
if (xli->opt.trait & QSE_XLI_KEYALIAS) key_alias = 1;
|
if (xli->opt.trait & QSE_XLI_KEYALIAS) key_alias = 1;
|
||||||
|
|
||||||
/*if (MATCH(xli, QSE_XLI_TOK_SQSTR)) key_quoted = 1;
|
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_DQSTR)) key_quoted = 2;*/
|
|
||||||
kloc = xli->tok.loc;
|
kloc = xli->tok.loc;
|
||||||
key.len = QSE_STR_LEN(xli->tok.name);
|
key.len = QSE_STR_LEN(xli->tok.name);
|
||||||
key.ptr = qse_strdup(QSE_STR_PTR(xli->tok.name), xli->mmgr);
|
key.ptr = qse_strdup (QSE_STR_PTR(xli->tok.name), xli->mmgr);
|
||||||
if (key.ptr == QSE_NULL)
|
if (key.ptr == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||||
@ -771,8 +745,8 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
}
|
}
|
||||||
|
|
||||||
dotted_curkey_len = QSE_STR_LEN (xli->dotted_curkey);
|
dotted_curkey_len = QSE_STR_LEN (xli->dotted_curkey);
|
||||||
if ((dotted_curkey_len > 0 && qse_str_cat(xli->dotted_curkey, QSE_T(".")) == (qse_size_t)-1) ||
|
if ((dotted_curkey_len > 0 && qse_str_cat (xli->dotted_curkey, QSE_T(".")) == (qse_size_t)-1) ||
|
||||||
qse_str_cat(xli->dotted_curkey, key.ptr) == (qse_size_t)-1)
|
qse_str_cat (xli->dotted_curkey, key.ptr) == (qse_size_t)-1)
|
||||||
{
|
{
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||||
goto oops;
|
goto oops;
|
||||||
@ -810,7 +784,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
while (atom)
|
while (atom)
|
||||||
{
|
{
|
||||||
if (atom->type == QSE_XLI_PAIR &&
|
if (atom->type == QSE_XLI_PAIR &&
|
||||||
qse_strcmp(((qse_xli_pair_t*)atom)->key, QSE_STR_PTR(xli->tok.name)) == 0)
|
qse_strcmp (((qse_xli_pair_t*)atom)->key, QSE_STR_PTR(xli->tok.name)) == 0)
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_EEXIST, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_EEXIST, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
@ -820,15 +794,15 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* once the key name is read, enable the numeric string for a key alias and a value */
|
/* once the key name is read, enable the numeric string for a value */
|
||||||
xli->tok_status |= TOK_STATUS_ENABLE_NSTR;
|
xli->tok_status |= TOK_STATUS_ENABLE_NSTR;
|
||||||
|
|
||||||
if (get_token(xli) <= -1) goto oops;
|
if (get_token (xli) <= -1) goto oops;
|
||||||
|
|
||||||
if (key_alias)
|
if (key_alias)
|
||||||
{
|
{
|
||||||
/* the alias part must be unique for the same key(s) */
|
/* the alias part must be unique for the same key(s) */
|
||||||
if (MATCH(xli, QSE_XLI_TOK_IDENT) || MATCH(xli, QSE_XLI_TOK_SQSTR) || MATCH(xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_NSTR))
|
if (MATCH(xli, QSE_XLI_TOK_IDENT) || MATCH(xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_SQSTR) || MATCH(xli, QSE_XLI_TOK_NSTR))
|
||||||
{
|
{
|
||||||
qse_xli_atom_t* atom;
|
qse_xli_atom_t* atom;
|
||||||
|
|
||||||
@ -853,9 +827,6 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (MATCH(xli, QSE_XLI_TOK_SQSTR)) alias_quoted = 1;
|
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_DQSTR)) alias_quoted = 2;*/
|
|
||||||
|
|
||||||
if (get_token (xli) <= -1) goto oops;
|
if (get_token (xli) <= -1) goto oops;
|
||||||
}
|
}
|
||||||
else if (key_alias == 2)
|
else if (key_alias == 2)
|
||||||
@ -871,9 +842,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
{
|
{
|
||||||
if (get_token (xli) <= -1) goto oops;
|
if (get_token (xli) <= -1) goto oops;
|
||||||
|
|
||||||
if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH(xli, QSE_XLI_TOK_LBRACE)) goto handle_list;
|
if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH(xli, QSE_XLI_TOK_TAG))
|
||||||
|
|
||||||
if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, QSE_XLI_TOK_TAG))
|
|
||||||
{
|
{
|
||||||
strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
|
strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
|
||||||
if (strtag == QSE_NULL)
|
if (strtag == QSE_NULL)
|
||||||
@ -901,11 +870,6 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
pair = qse_xli_insertpairwithstr (xli, parlist, QSE_NULL, key.ptr, name, keytag, QSE_STR_XSTR(xli->tok.name), strtag);
|
pair = qse_xli_insertpairwithstr (xli, parlist, QSE_NULL, key.ptr, name, keytag, QSE_STR_XSTR(xli->tok.name), strtag);
|
||||||
if (pair == QSE_NULL) goto oops;
|
if (pair == QSE_NULL) goto oops;
|
||||||
|
|
||||||
#if 0
|
|
||||||
pair->_key_quoted = key_quoted; /* store this for easier output support */
|
|
||||||
pair->_alias_quoted = alias_quoted;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
segcount++;
|
segcount++;
|
||||||
curstrseg = (qse_xli_str_t*)pair->val;
|
curstrseg = (qse_xli_str_t*)pair->val;
|
||||||
|
|
||||||
@ -923,7 +887,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
strtag = QSE_NULL;
|
strtag = QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH (xli, QSE_XLI_TOK_TAG))
|
if ((xli->opt.trait & QSE_XLI_STRTAG) && MATCH(xli, QSE_XLI_TOK_TAG))
|
||||||
{
|
{
|
||||||
strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
|
strtag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
|
||||||
if (strtag == QSE_NULL)
|
if (strtag == QSE_NULL)
|
||||||
@ -935,7 +899,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
if (get_token (xli) <= -1) goto oops;
|
if (get_token (xli) <= -1) goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MATCH (xli, QSE_XLI_TOK_SQSTR) && !MATCH (xli, QSE_XLI_TOK_DQSTR) && !MATCH (xli, QSE_XLI_TOK_NSTR) && !MATCH (xli, QSE_XLI_TOK_IDENT))
|
if (!MATCH(xli, QSE_XLI_TOK_SQSTR) && !MATCH(xli, QSE_XLI_TOK_DQSTR) && !MATCH(xli, QSE_XLI_TOK_NSTR) && !MATCH(xli, QSE_XLI_TOK_IDENT))
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
@ -948,11 +912,11 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
segcount++;
|
segcount++;
|
||||||
if (get_token (xli) <= -1) goto oops; /* skip the value */
|
if (get_token (xli) <= -1) goto oops; /* skip the value */
|
||||||
}
|
}
|
||||||
while (MATCH (xli, QSE_XLI_TOK_COMMA));
|
while (MATCH(xli, QSE_XLI_TOK_COMMA));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* semicolon is mandatory for a string */
|
/* semicolon is mandatory for a string */
|
||||||
if (!MATCH (xli, QSE_XLI_TOK_SEMICOLON))
|
if (!MATCH(xli, QSE_XLI_TOK_SEMICOLON))
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_ESCOLON, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_ESCOLON, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
@ -975,17 +939,12 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: check against schema */
|
/* TODO: check against schema */
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (xli->opt.trait & QSE_XLI_JSON)
|
else if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH(xli, QSE_XLI_TOK_LBRACE))
|
||||||
{
|
{
|
||||||
/* the assignment operator is mandator */
|
|
||||||
qse_xli_seterror (xli, QSE_XLI_EASSIGN, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
else if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH (xli, QSE_XLI_TOK_LBRACE))
|
|
||||||
{
|
|
||||||
handle_list:
|
|
||||||
if (scm && !(scm->flags & QSE_XLI_SCM_VALLIST))
|
if (scm && !(scm->flags & QSE_XLI_SCM_VALLIST))
|
||||||
{
|
{
|
||||||
/* check the value type */
|
/* check the value type */
|
||||||
@ -996,25 +955,25 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR;
|
xli->tok_status &= ~TOK_STATUS_ENABLE_NSTR;
|
||||||
|
|
||||||
/* insert a pair with an empty list */
|
/* insert a pair with an empty list */
|
||||||
pair = qse_xli_insertpairwithemptylist (xli, parlist, QSE_NULL, key.ptr, name, keytag);
|
pair = qse_xli_insertpairwithemptylist(xli, parlist, QSE_NULL, key.ptr, name, keytag);
|
||||||
if (pair == QSE_NULL) goto oops;
|
if (pair == QSE_NULL) goto oops;
|
||||||
|
|
||||||
/* skip validations of child pairs if the schema for the
|
/* skip validations of child pairs if the schema for the
|
||||||
* current pair is set with QSE_XLI_SCM_VALIFFY.
|
* current pair is set with QSE_XLI_SCM_VALIFFY.
|
||||||
* the schema for the child pairs, if specified, must not
|
* the schema for the child pairs, if specified, must not
|
||||||
* take effect. */
|
* take effect. */
|
||||||
if (read_list (xli, (qse_xli_list_t*)pair->val, (val_iffy? &scm_val_iffy: QSE_NULL)) <= -1) goto oops;
|
if (read_list(xli, (qse_xli_list_t*)pair->val, (val_iffy? &scm_val_iffy: QSE_NULL)) <= -1) goto oops;
|
||||||
|
|
||||||
if (!MATCH (xli, QSE_XLI_TOK_RBRACE))
|
if (!MATCH(xli, QSE_XLI_TOK_RBRACE))
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_ERBRCE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_ERBRACE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_token (xli) <= -1) goto oops;
|
if (get_token(xli) <= -1) goto oops;
|
||||||
|
|
||||||
/* semicolon is optional for a list */
|
/* semicolon is optional for a list */
|
||||||
if (MATCH (xli, QSE_XLI_TOK_SEMICOLON))
|
if (MATCH(xli, QSE_XLI_TOK_SEMICOLON))
|
||||||
{
|
{
|
||||||
/* skip the semicolon */
|
/* skip the semicolon */
|
||||||
if (get_token (xli) <= -1) goto oops;
|
if (get_token (xli) <= -1) goto oops;
|
||||||
@ -1022,7 +981,7 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
|
|
||||||
/* TODO: check against schema */
|
/* TODO: check against schema */
|
||||||
}
|
}
|
||||||
else if (MATCH (xli, QSE_XLI_TOK_SEMICOLON))
|
else if (MATCH(xli, QSE_XLI_TOK_SEMICOLON))
|
||||||
{
|
{
|
||||||
if (xli->opt.trait & QSE_XLI_NONIL)
|
if (xli->opt.trait & QSE_XLI_NONIL)
|
||||||
{
|
{
|
||||||
@ -1087,18 +1046,16 @@ qse_xli_list_link_t* qse_xli_makelistlink (qse_xli_t* xli, qse_xli_list_t* parli
|
|||||||
|
|
||||||
void qse_xli_freelistlink (qse_xli_t* xli, qse_xli_list_link_t* link)
|
void qse_xli_freelistlink (qse_xli_t* xli, qse_xli_list_link_t* link)
|
||||||
{
|
{
|
||||||
|
QSE_ASSERT (xli->parlink == link);
|
||||||
xli->parlink = link->next;
|
xli->parlink = link->next;
|
||||||
qse_xli_freemem (xli, link);
|
qse_xli_freemem (xli, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override)
|
||||||
static int __read_array (qse_xli_t* xli, int opt_outer_brace)
|
|
||||||
{
|
{
|
||||||
qse_size_t pair_count = 0;
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (MATCH (xli, QSE_XLI_TOK_XINCLUDE))
|
if (MATCH(xli, QSE_XLI_TOK_XINCLUDE))
|
||||||
{
|
{
|
||||||
if (get_token(xli) <= -1) return -1;
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
|
||||||
@ -1110,85 +1067,12 @@ static int __read_array (qse_xli_t* xli, int opt_outer_brace)
|
|||||||
|
|
||||||
if (begin_include (xli) <= -1) return -1;
|
if (begin_include (xli) <= -1) return -1;
|
||||||
}
|
}
|
||||||
else if (opt_outer_brace == 1 && pair_count == 0 && MATCH(xli, QSE_XLI_TOK_LBRACK))
|
|
||||||
{
|
|
||||||
opt_outer_brace++;
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_IDENT) || MATCH(xli, QSE_XLI_TOK_SQSTR) || MATCH(xli, QSE_XLI_TOK_DQSTR))
|
|
||||||
{
|
|
||||||
//if (read_pair(xli, QSE_NULL, override) <= -1) return -1;
|
|
||||||
pair_count++;
|
|
||||||
}
|
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_LBRACE))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_LBRACK))
|
|
||||||
{
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
|
|
||||||
if (__read_array(xli, 0) <= -1) return -1;
|
|
||||||
|
|
||||||
if (!MATCH(xli, QSE_XLI_TOK_RBRACK))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
|
||||||
{
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_outer_brace >= 2)
|
|
||||||
{
|
|
||||||
if (!MATCH(xli, QSE_XLI_TOK_RBRACE))
|
|
||||||
{
|
|
||||||
qse_xli_seterror (xli, QSE_XLI_ERBRCE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override, int opt_outer_brace)
|
|
||||||
{
|
|
||||||
qse_size_t pair_count = 0;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (MATCH (xli, QSE_XLI_TOK_XINCLUDE))
|
|
||||||
{
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
|
|
||||||
if (!MATCH(xli,QSE_XLI_TOK_SQSTR) && !MATCH(xli,QSE_XLI_TOK_DQSTR))
|
|
||||||
{
|
|
||||||
qse_xli_seterror (xli, QSE_XLI_EINCLSTR, QSE_NULL, &xli->tok.loc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (begin_include (xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
else if (opt_outer_brace == 1 && pair_count == 0 && MATCH(xli, QSE_XLI_TOK_LBRACE))
|
|
||||||
{
|
|
||||||
opt_outer_brace++;
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
else if ((xli->opt.trait & QSE_XLI_KEYTAG) && MATCH(xli, QSE_XLI_TOK_TAG))
|
else if ((xli->opt.trait & QSE_XLI_KEYTAG) && MATCH(xli, QSE_XLI_TOK_TAG))
|
||||||
{
|
{
|
||||||
qse_char_t* keytag;
|
qse_char_t* keytag;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
keytag = qse_strxdup(QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
|
keytag = qse_strxdup (QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name), xli->mmgr);
|
||||||
if (keytag == QSE_NULL)
|
if (keytag == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||||
@ -1201,7 +1085,7 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override, int opt_o
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MATCH(xli,QSE_XLI_TOK_IDENT) && !MATCH(xli,QSE_XLI_TOK_SQSTR) && !MATCH(xli,QSE_XLI_TOK_DQSTR))
|
if (!MATCH(xli, QSE_XLI_TOK_IDENT) && !MATCH(xli, QSE_XLI_TOK_DQSTR) && !MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||||
{
|
{
|
||||||
QSE_MMGR_FREE (xli->mmgr, keytag);
|
QSE_MMGR_FREE (xli->mmgr, keytag);
|
||||||
qse_xli_seterror (xli, QSE_XLI_ENOKEY, QSE_NULL, &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_ENOKEY, QSE_NULL, &xli->tok.loc);
|
||||||
@ -1211,12 +1095,10 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override, int opt_o
|
|||||||
x = read_pair(xli, keytag, override);
|
x = read_pair(xli, keytag, override);
|
||||||
QSE_MMGR_FREE (xli->mmgr, keytag);
|
QSE_MMGR_FREE (xli->mmgr, keytag);
|
||||||
if (x <= -1) return -1;
|
if (x <= -1) return -1;
|
||||||
pair_count++;
|
|
||||||
}
|
}
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_IDENT) || MATCH(xli, QSE_XLI_TOK_SQSTR) || MATCH(xli, QSE_XLI_TOK_DQSTR))
|
else if (MATCH(xli, QSE_XLI_TOK_IDENT) || MATCH(xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||||
{
|
{
|
||||||
if (read_pair(xli, QSE_NULL, override) <= -1) return -1;
|
if (read_pair(xli, QSE_NULL, override) <= -1) return -1;
|
||||||
pair_count++;
|
|
||||||
}
|
}
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
||||||
{
|
{
|
||||||
@ -1228,16 +1110,6 @@ static int __read_list (qse_xli_t* xli, const qse_xli_scm_t* override, int opt_o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_outer_brace >= 2)
|
|
||||||
{
|
|
||||||
if (!MATCH(xli, QSE_XLI_TOK_RBRACE))
|
|
||||||
{
|
|
||||||
qse_xli_seterror (xli, QSE_XLI_ERBRCE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1248,17 +1120,19 @@ static int read_list (qse_xli_t* xli, qse_xli_list_t* parlist, const qse_xli_scm
|
|||||||
link = qse_xli_makelistlink(xli, parlist);
|
link = qse_xli_makelistlink(xli, parlist);
|
||||||
if (link == QSE_NULL) return -1;
|
if (link == QSE_NULL) return -1;
|
||||||
|
|
||||||
|
QSE_ASSERT (link == xli->parlink);
|
||||||
|
|
||||||
/* get_token() here is to read the token after the left brace.
|
/* get_token() here is to read the token after the left brace.
|
||||||
* it must be called after the xli->parlink has been updated
|
* it must be called after the xli->parlink has been updated
|
||||||
* in case there are comments at the beginning of the list */
|
* in case there are comments at the beginning of the list */
|
||||||
if (get_token(xli) <= -1 || __read_list(xli, override, 0) <= -1)
|
if (get_token(xli) <= -1 || __read_list(xli, override) <= -1)
|
||||||
{
|
{
|
||||||
qse_xli_freelistlink (xli, link);
|
qse_xli_freelistlink (xli, link);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_ASSERT (link == xli->parlink);
|
QSE_ASSERT (link == xli->parlink);
|
||||||
qse_xli_freelistlink(xli, link);
|
qse_xli_freelistlink (xli, link);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1267,18 +1141,19 @@ static int read_root_list (qse_xli_t* xli)
|
|||||||
{
|
{
|
||||||
qse_xli_list_link_t* link;
|
qse_xli_list_link_t* link;
|
||||||
|
|
||||||
link = qse_xli_makelistlink(xli, &xli->root->list);
|
link = qse_xli_makelistlink (xli, &xli->root->list);
|
||||||
if (!link) return -1;
|
if (!link) return -1;
|
||||||
|
|
||||||
/* TODO: pass opt_outer_brace 1 to __read_list only if a certian option is enabled */
|
QSE_ASSERT (link == xli->parlink);
|
||||||
if (qse_xli_getchar(xli) <= -1 || get_token(xli) <= -1 || __read_list(xli, QSE_NULL, 1) <= -1)
|
|
||||||
|
if (qse_xli_getchar(xli) <= -1 || get_token(xli) <= -1 || __read_list(xli, QSE_NULL) <= -1)
|
||||||
{
|
{
|
||||||
qse_xli_freelistlink (xli, link);
|
qse_xli_freelistlink (xli, link);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_ASSERT (link == xli->parlink);
|
QSE_ASSERT (link == xli->parlink);
|
||||||
qse_xli_freelistlink(xli, link);
|
qse_xli_freelistlink (xli, link);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1322,7 +1197,7 @@ int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io)
|
|||||||
|
|
||||||
QSE_ASSERT (xli->parlink == QSE_NULL);
|
QSE_ASSERT (xli->parlink == QSE_NULL);
|
||||||
|
|
||||||
if (!MATCH (xli, QSE_XLI_TOK_EOF))
|
if (!MATCH(xli, QSE_XLI_TOK_EOF))
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
|
@ -123,7 +123,7 @@ static qse_sio_t* open_sio (qse_xli_t* xli, const qse_char_t* file, int flags)
|
|||||||
if (sio == QSE_NULL)
|
if (sio == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_cstr_t errarg;
|
qse_cstr_t errarg;
|
||||||
errarg.ptr = file;
|
errarg.ptr = (qse_char_t*)file;
|
||||||
errarg.len = qse_strlen(file);
|
errarg.len = qse_strlen(file);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &errarg);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &errarg);
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ static qse_ssize_t sf_in_open (qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn
|
|||||||
if (arg->handle == QSE_NULL)
|
if (arg->handle == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_cstr_t ea;
|
qse_cstr_t ea;
|
||||||
ea.ptr = arg->name;
|
ea.ptr = (qse_char_t*)arg->name;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
return -1;
|
return -1;
|
||||||
@ -299,7 +299,7 @@ static qse_ssize_t sf_in_read (
|
|||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
qse_cstr_t ea;
|
qse_cstr_t ea;
|
||||||
ea.ptr = xtn->s.in.x->u.file.path;
|
ea.ptr = (qse_char_t*)xtn->s.in.x->u.file.path;
|
||||||
if (ea.ptr == QSE_NULL) ea.ptr = sio_std_names[QSE_SIO_STDIN].ptr;
|
if (ea.ptr == QSE_NULL) ea.ptr = sio_std_names[QSE_SIO_STDIN].ptr;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
@ -335,7 +335,7 @@ static qse_ssize_t sf_in_read (
|
|||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
qse_cstr_t ea;
|
qse_cstr_t ea;
|
||||||
ea.ptr = arg->name;
|
ea.ptr = (qse_char_t*)arg->name;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
}
|
}
|
||||||
@ -468,7 +468,7 @@ static qse_ssize_t sf_out_open (qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xt
|
|||||||
if (arg->handle == QSE_NULL)
|
if (arg->handle == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_cstr_t ea;
|
qse_cstr_t ea;
|
||||||
ea.ptr = arg->name;
|
ea.ptr = (qse_char_t*)arg->name;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
return -1;
|
return -1;
|
||||||
@ -526,7 +526,7 @@ static qse_ssize_t sf_out_write (
|
|||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
qse_cstr_t ea;
|
qse_cstr_t ea;
|
||||||
ea.ptr = xtn->s.out.x->u.file.path;
|
ea.ptr = (qse_char_t*)xtn->s.out.x->u.file.path;
|
||||||
if (ea.ptr == QSE_NULL) ea.ptr = sio_std_names[QSE_SIO_STDOUT].ptr;
|
if (ea.ptr == QSE_NULL) ea.ptr = sio_std_names[QSE_SIO_STDOUT].ptr;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
@ -564,7 +564,7 @@ static qse_ssize_t sf_out_write (
|
|||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
qse_cstr_t ea;
|
qse_cstr_t ea;
|
||||||
ea.ptr = arg->name;
|
ea.ptr = (qse_char_t*)arg->name;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
}
|
}
|
||||||
@ -611,7 +611,7 @@ int qse_xli_readstd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xtn->s.in.x = in;
|
xtn->s.in.x = in;
|
||||||
return qse_xli_read (xli, sf_in);
|
return qse_xli_read(xli, sf_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -629,9 +629,25 @@ int qse_xli_readinistd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xtn->s.in.x = in;
|
xtn->s.in.x = in;
|
||||||
return qse_xli_readini (xli, sf_in);
|
return qse_xli_readini(xli, sf_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qse_xli_readjsonstd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
||||||
|
{
|
||||||
|
xtn_t* xtn = (xtn_t*) QSE_XTN (xli);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
int qse_xli_writestd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iostd_t* out)
|
int qse_xli_writestd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iostd_t* out)
|
||||||
{
|
{
|
||||||
@ -692,3 +708,33 @@ int qse_xli_writeinistd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iost
|
|||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qse_xli_writejsonstd (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_iostd_t* out)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
xtn_t* xtn = (xtn_t*) QSE_XTN (xli);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -119,7 +119,16 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case QSE_XLI_LIST:
|
case QSE_XLI_LIST:
|
||||||
if (write_list (xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1) return -1;
|
if (depth < 1)
|
||||||
|
{
|
||||||
|
if (write_list(xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1 ||
|
||||||
|
write_to_current_stream (xli, QSE_T("\n"), 1) <= -1) return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the ini format doesn't support deep nesting */
|
||||||
|
if (write_to_current_stream (xli, QSE_T("={}\n"), 4) <= -1) return -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -129,9 +138,9 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
{
|
{
|
||||||
const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr;
|
const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr;
|
||||||
|
|
||||||
if (write_to_current_stream (xli, QSE_T(";"), 1) <= -1 ||
|
if (write_to_current_stream(xli, QSE_T(";"), 1) <= -1 ||
|
||||||
write_to_current_stream (xli, str, qse_strlen(str)) <= -1 ||
|
write_to_current_stream(xli, str, qse_strlen(str)) <= -1 ||
|
||||||
write_to_current_stream (xli, QSE_T("\n"), 1) <= -1) return -1;
|
write_to_current_stream(xli, QSE_T("\n"), 1) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
357
qse/lib/xli/write-json.c
Normal file
357
qse/lib/xli/write-json.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xli.h"
|
||||||
|
#include <qse/cmn/chr.h>
|
||||||
|
|
||||||
|
typedef struct arg_data_t arg_data_t;
|
||||||
|
struct arg_data_t
|
||||||
|
{
|
||||||
|
int org_depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int write_to_current_stream(qse_xli_t* xli, const qse_char_t* ptr, qse_size_t len, int escape)
|
||||||
|
{
|
||||||
|
qse_xli_io_arg_t* arg;
|
||||||
|
qse_size_t i;
|
||||||
|
|
||||||
|
arg = xli->wio.inp;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (escape && (ptr[i] == QSE_T('\\') || ptr[i] == QSE_T('\"')))
|
||||||
|
{
|
||||||
|
if (arg->b.len + 2 > QSE_COUNTOF(arg->b.buf) && qse_xli_flushwstream (xli, arg) <= -1) return -1;
|
||||||
|
arg->b.buf[arg->b.len++] = QSE_T('\\');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (arg->b.len + 1 > QSE_COUNTOF(arg->b.buf) && qse_xli_flushwstream (xli, arg) <= -1) return -1;
|
||||||
|
}
|
||||||
|
arg->b.buf[arg->b.len++] = ptr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_indentation (qse_xli_t* xli, int depth)
|
||||||
|
{
|
||||||
|
static const qse_char_t tabs[16] =
|
||||||
|
{
|
||||||
|
QSE_T('\t'), QSE_T('\t'), QSE_T('\t'), QSE_T('\t'),
|
||||||
|
QSE_T('\t'), QSE_T('\t'), QSE_T('\t'), QSE_T('\t'),
|
||||||
|
QSE_T('\t'), QSE_T('\t'), QSE_T('\t'), QSE_T('\t'),
|
||||||
|
QSE_T('\t'), QSE_T('\t'), QSE_T('\t'), QSE_T('\t')
|
||||||
|
};
|
||||||
|
|
||||||
|
if (depth <= QSE_COUNTOF(tabs))
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, tabs, depth, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (write_to_current_stream(xli, tabs, QSE_COUNTOF(tabs), 0) <= -1) return -1;
|
||||||
|
for (i = QSE_COUNTOF(tabs); i < depth; i++)
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int key_needs_quoting (qse_xli_t* xli, const qse_char_t* str, int nstr)
|
||||||
|
{
|
||||||
|
/* this determines if a key or an alias requires quoting for output.
|
||||||
|
* NSTR is not taken into account because it's only allowed as a value */
|
||||||
|
|
||||||
|
/* refer to the tokenization rule in get_token_into() in read.c */
|
||||||
|
qse_char_t c;
|
||||||
|
|
||||||
|
c = *str++;
|
||||||
|
if (c == QSE_T('\0')) return 1; /* an empty string requires a quoting */
|
||||||
|
|
||||||
|
if (c == QSE_T('_') || QSE_ISALPHA(c) || (!nstr && (xli->opt.trait & QSE_XLI_LEADDIGIT) && QSE_ISDIGIT(c)))
|
||||||
|
{
|
||||||
|
int lead_digit = QSE_ISDIGIT(c);
|
||||||
|
int all_digits = 1;
|
||||||
|
|
||||||
|
/* a normal identifier can be composed of wider varieties of
|
||||||
|
* characters than a keyword/directive */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
c = *str++;
|
||||||
|
if (c == QSE_T('\0')) break;
|
||||||
|
|
||||||
|
if (c == QSE_T('_') || c == QSE_T('-') ||
|
||||||
|
(!(xli->opt.trait & QSE_XLI_JSON) && c == QSE_T(':')) ||
|
||||||
|
c == QSE_T('*') || c == QSE_T('/') || QSE_ISALPHA(c))
|
||||||
|
{
|
||||||
|
all_digits = 0;
|
||||||
|
}
|
||||||
|
else if (QSE_ISDIGIT(c))
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* a disallowed character for an identifier */
|
||||||
|
return 1; /* quote it */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lead_digit && all_digits)
|
||||||
|
{
|
||||||
|
/* if an identifier begins with a digit, it must contain a non-digit character */
|
||||||
|
/* in fact, it is not a valid identifer. so quote it */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this must be a normal identifer */
|
||||||
|
return 0; /* no quoting needed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nstr && QSE_ISDIGIT(c))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = *str++;
|
||||||
|
if (c == QSE_T('\0')) return 0; /* it's a numeric string */
|
||||||
|
}
|
||||||
|
while (QSE_ISDIGIT(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* quote all the rest */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
||||||
|
{
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
qse_char_t* qptr;
|
||||||
|
qse_size_t qlen;
|
||||||
|
} quotes[] =
|
||||||
|
{
|
||||||
|
{ QSE_T(""), 0 },
|
||||||
|
{ QSE_T("\'"), 1 },
|
||||||
|
{ QSE_T("\""), 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static qse_char_t tag_opener[] = { QSE_T('['), QSE_T('(') };
|
||||||
|
static qse_char_t tag_closer[] = { QSE_T(']'), QSE_T(')') };
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
qse_char_t* ptr;
|
||||||
|
qse_size_t len;
|
||||||
|
} assign_symbol[] =
|
||||||
|
{
|
||||||
|
{ QSE_T(" = "), 3 },
|
||||||
|
{ QSE_T(": "), 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
qse_char_t* ptr;
|
||||||
|
qse_size_t len;
|
||||||
|
} list_assign_symbol[] =
|
||||||
|
{
|
||||||
|
{ QSE_T(" "), 1 },
|
||||||
|
{ QSE_T(": "), 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
qse_xli_atom_t* curatom;
|
||||||
|
int tag_mode = (xli->opt.trait & QSE_XLI_JSON)? 1: 0;
|
||||||
|
|
||||||
|
for (curatom = list->head; curatom; curatom = curatom->next)
|
||||||
|
{
|
||||||
|
switch (curatom->type)
|
||||||
|
{
|
||||||
|
case QSE_XLI_PAIR:
|
||||||
|
{
|
||||||
|
int qtype;
|
||||||
|
qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom;
|
||||||
|
|
||||||
|
if (write_indentation(xli, depth) <= -1) return -1;
|
||||||
|
|
||||||
|
if (pair->tag)
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, &tag_opener[tag_mode], 1, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, pair->tag, qse_strlen(pair->tag), 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, &tag_closer[tag_mode], 1, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_ASSERT(pair->_key_quoted >= 0 && pair->_key_quoted < QSE_COUNTOF(quotes));
|
||||||
|
qtype = pair->_key_quoted;
|
||||||
|
if (qtype <= 0 && key_needs_quoting(xli, pair->key, 0)) qtype = 2; /* force double quoting */
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, pair->key, qse_strlen(pair->key), (qtype >= 2)) <= -1 ||
|
||||||
|
write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1) return -1;
|
||||||
|
|
||||||
|
if (pair->alias)
|
||||||
|
{
|
||||||
|
QSE_ASSERT(pair->_alias_quoted >= 0 && pair->_alias_quoted < QSE_COUNTOF(quotes));
|
||||||
|
qtype = pair->_alias_quoted;
|
||||||
|
if (qtype <= 0 && key_needs_quoting(xli, pair->alias, 1)) qtype = 2;
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, QSE_T(" "), 1, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, pair->alias, qse_strlen(pair->alias), (qtype >= 2)) <= -1 ||
|
||||||
|
write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pair->val->type)
|
||||||
|
{
|
||||||
|
case QSE_XLI_NIL:
|
||||||
|
if (write_to_current_stream(xli, QSE_T(";\n"), 2, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_STR:
|
||||||
|
{
|
||||||
|
qse_xli_str_t* str = (qse_xli_str_t*)pair->val;
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, assign_symbol[tag_mode].ptr, assign_symbol[tag_mode].len, 0) <= -1) return -1;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (str->tag)
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, &tag_opener[tag_mode], 1, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, str->tag, qse_strlen(str->tag), 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, &tag_closer[tag_mode], 1, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, str->ptr, str->len, 1) <= -1 ||
|
||||||
|
write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1;
|
||||||
|
if (!str->next) break;
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, QSE_T(", "), 2, 0) <= -1) return -1;
|
||||||
|
str = str->next;
|
||||||
|
}
|
||||||
|
if (write_to_current_stream(xli, QSE_T(";\n"), 2, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QSE_XLI_LIST:
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, list_assign_symbol[tag_mode].ptr, list_assign_symbol[tag_mode].len, 0) <= -1) return -1;
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, QSE_T("{\n"), 2, 0) <= -1 ||
|
||||||
|
write_list (xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1 ||
|
||||||
|
write_indentation (xli, depth) <= -1 ||
|
||||||
|
write_to_current_stream(xli, QSE_T("}\n"), 2, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QSE_XLI_TEXT:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr;
|
||||||
|
|
||||||
|
for (i = 0; i < depth; i++)
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, QSE_T("#"), 1, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, str, qse_strlen(str), 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QSE_XLI_FILE:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const qse_char_t* path = ((qse_xli_file_t*)curatom)->path;
|
||||||
|
|
||||||
|
for (i = 0; i < depth; i++)
|
||||||
|
{
|
||||||
|
if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_to_current_stream(xli, QSE_T("@include \""), 10, 0) <= -1 ||
|
||||||
|
write_to_current_stream(xli, path, qse_strlen(path), 1) <= -1 ||
|
||||||
|
write_to_current_stream(xli, QSE_T("\";\n"), 3, 0) <= -1) return -1;
|
||||||
|
|
||||||
|
if (qse_xli_openwstream (xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1;
|
||||||
|
depth = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QSE_XLI_EOF:
|
||||||
|
if (qse_xli_closeactivewstream (xli, &depth) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int qse_xli_writejson (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_io_impl_t io)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (io == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MEMSET (&xli->wio, 0, QSE_SIZEOF(xli->wio));
|
||||||
|
xli->wio.impl = io;
|
||||||
|
xli->wio.inp = &xli->wio.top;
|
||||||
|
|
||||||
|
qse_xli_seterrnum (xli, QSE_XLI_ENOERR, QSE_NULL);
|
||||||
|
qse_xli_clearwionames (xli);
|
||||||
|
|
||||||
|
/* open the top level stream */
|
||||||
|
if (qse_xli_openwstream (xli, QSE_NULL, 0) <= -1) return -1;
|
||||||
|
|
||||||
|
/* begin writing the root list */
|
||||||
|
n = write_list (xli, (root_list? root_list: &xli->root->list), 0);
|
||||||
|
|
||||||
|
/* close all open streams. there should be only the
|
||||||
|
* top-level stream here if there occurred no errors */
|
||||||
|
while (xli->wio.inp) qse_xli_closeactivewstream (xli, QSE_NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ int qse_xli_closeactivewstream (qse_xli_t* xli, int* org_depth)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_to_current_stream(qse_xli_t* xli, const qse_char_t* ptr, qse_size_t len, int escape)
|
static int write_to_current_stream (qse_xli_t* xli, const qse_char_t* ptr, qse_size_t len, int escape)
|
||||||
{
|
{
|
||||||
qse_xli_io_arg_t* arg;
|
qse_xli_io_arg_t* arg;
|
||||||
qse_size_t i;
|
qse_size_t i;
|
||||||
@ -175,21 +175,20 @@ static int write_indentation (qse_xli_t* xli, int depth)
|
|||||||
|
|
||||||
if (depth <= QSE_COUNTOF(tabs))
|
if (depth <= QSE_COUNTOF(tabs))
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, tabs, depth, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, tabs, depth, 0) <= -1) return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (write_to_current_stream(xli, tabs, QSE_COUNTOF(tabs), 0) <= -1) return -1;
|
if (write_to_current_stream (xli, tabs, QSE_COUNTOF(tabs), 0) <= -1) return -1;
|
||||||
for (i = QSE_COUNTOF(tabs); i < depth; i++)
|
for (i = QSE_COUNTOF(tabs); i < depth; i++)
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int key_needs_quoting (qse_xli_t* xli, const qse_char_t* str, int nstr)
|
static int key_needs_quoting (qse_xli_t* xli, const qse_char_t* str, int nstr)
|
||||||
{
|
{
|
||||||
/* this determines if a key or an alias requires quoting for output.
|
/* this determines if a key or an alias requires quoting for output.
|
||||||
@ -213,8 +212,7 @@ static int key_needs_quoting (qse_xli_t* xli, const qse_char_t* str, int nstr)
|
|||||||
c = *str++;
|
c = *str++;
|
||||||
if (c == QSE_T('\0')) break;
|
if (c == QSE_T('\0')) break;
|
||||||
|
|
||||||
if (c == QSE_T('_') || c == QSE_T('-') ||
|
if (c == QSE_T('_') || c == QSE_T('-') || c == QSE_T(':') ||
|
||||||
(!(xli->opt.trait & QSE_XLI_JSON) && c == QSE_T(':')) ||
|
|
||||||
c == QSE_T('*') || c == QSE_T('/') || QSE_ISALPHA(c))
|
c == QSE_T('*') || c == QSE_T('/') || QSE_ISALPHA(c))
|
||||||
{
|
{
|
||||||
all_digits = 0;
|
all_digits = 0;
|
||||||
@ -258,122 +256,78 @@ static int key_needs_quoting (qse_xli_t* xli, const qse_char_t* str, int nstr)
|
|||||||
|
|
||||||
static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
||||||
{
|
{
|
||||||
static struct
|
|
||||||
{
|
|
||||||
qse_char_t* qptr;
|
|
||||||
qse_size_t qlen;
|
|
||||||
} quotes[] =
|
|
||||||
{
|
|
||||||
{ QSE_T(""), 0 },
|
|
||||||
{ QSE_T("\'"), 1 },
|
|
||||||
{ QSE_T("\""), 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static qse_char_t tag_opener[] = { QSE_T('['), QSE_T('(') };
|
|
||||||
static qse_char_t tag_closer[] = { QSE_T(']'), QSE_T(')') };
|
|
||||||
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
qse_char_t* ptr;
|
|
||||||
qse_size_t len;
|
|
||||||
} assign_symbol[] =
|
|
||||||
{
|
|
||||||
{ QSE_T(" = "), 3 },
|
|
||||||
{ QSE_T(": "), 2 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
qse_char_t* ptr;
|
|
||||||
qse_size_t len;
|
|
||||||
} list_assign_symbol[] =
|
|
||||||
{
|
|
||||||
{ QSE_T(" "), 1 },
|
|
||||||
{ QSE_T(": "), 2 }
|
|
||||||
};
|
|
||||||
|
|
||||||
qse_xli_atom_t* curatom;
|
qse_xli_atom_t* curatom;
|
||||||
int tag_mode = (xli->opt.trait & QSE_XLI_JSON)? 1: 0;
|
|
||||||
|
|
||||||
for (curatom = list->head; curatom; curatom = curatom->next)
|
for (curatom = list->head; curatom; curatom = curatom->next)
|
||||||
{
|
{
|
||||||
|
int quote_key = 0;
|
||||||
|
|
||||||
switch (curatom->type)
|
switch (curatom->type)
|
||||||
{
|
{
|
||||||
case QSE_XLI_PAIR:
|
case QSE_XLI_PAIR:
|
||||||
{
|
{
|
||||||
int qtype;
|
|
||||||
qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom;
|
qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom;
|
||||||
|
|
||||||
if (write_indentation(xli, depth) <= -1) return -1;
|
if (write_indentation (xli, depth) <= -1) return -1;
|
||||||
|
|
||||||
if (pair->tag)
|
if (pair->tag)
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, &tag_opener[tag_mode], 1, 0) <= -1 ||
|
if (write_to_current_stream (xli, QSE_T("["), 1, 0) <= -1 ||
|
||||||
write_to_current_stream(xli, pair->tag, qse_strlen(pair->tag), 0) <= -1 ||
|
write_to_current_stream (xli, pair->tag, qse_strlen(pair->tag), 0) <= -1 ||
|
||||||
write_to_current_stream(xli, &tag_closer[tag_mode], 1, 0) <= -1) return -1;
|
write_to_current_stream (xli, QSE_T("]"), 1, 0) <= -1) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_ASSERT(pair->_key_quoted >= 0 && pair->_key_quoted < QSE_COUNTOF(quotes));
|
if (key_needs_quoting(xli, pair->key, 0)) quote_key = 1;
|
||||||
qtype = pair->_key_quoted;
|
|
||||||
if (qtype <= 0 && key_needs_quoting(xli, pair->key, 0)) qtype = 2; /* force double quoting */
|
|
||||||
|
|
||||||
if (write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1 ||
|
if ((quote_key && write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1) ||
|
||||||
write_to_current_stream(xli, pair->key, qse_strlen(pair->key), (qtype >= 2)) <= -1 ||
|
write_to_current_stream (xli, pair->key, qse_strlen(pair->key), 0) <= -1 ||
|
||||||
write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1) return -1;
|
(quote_key && write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1)) return -1;
|
||||||
|
|
||||||
if (pair->alias)
|
if (pair->alias)
|
||||||
{
|
{
|
||||||
QSE_ASSERT(pair->_alias_quoted >= 0 && pair->_alias_quoted < QSE_COUNTOF(quotes));
|
if (write_to_current_stream (xli, QSE_T(" \""), 2, 0) <= -1 ||
|
||||||
qtype = pair->_alias_quoted;
|
write_to_current_stream (xli, pair->alias, qse_strlen(pair->alias), 1) <= -1 ||
|
||||||
if (qtype <= 0 && key_needs_quoting(xli, pair->alias, 1)) qtype = 2;
|
write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1) return -1;
|
||||||
|
|
||||||
if (write_to_current_stream(xli, QSE_T(" "), 1, 0) <= -1 ||
|
|
||||||
write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1 ||
|
|
||||||
write_to_current_stream(xli, pair->alias, qse_strlen(pair->alias), (qtype >= 2)) <= -1 ||
|
|
||||||
write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1) return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pair->val->type)
|
switch (pair->val->type)
|
||||||
{
|
{
|
||||||
case QSE_XLI_NIL:
|
case QSE_XLI_NIL:
|
||||||
if (write_to_current_stream(xli, QSE_T(";\n"), 2, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T(";\n"), 2, 0) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_XLI_STR:
|
case QSE_XLI_STR:
|
||||||
{
|
{
|
||||||
qse_xli_str_t* str = (qse_xli_str_t*)pair->val;
|
qse_xli_str_t* str = (qse_xli_str_t*)pair->val;
|
||||||
|
|
||||||
if (write_to_current_stream(xli, assign_symbol[tag_mode].ptr, assign_symbol[tag_mode].len, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T(" = "), 3, 0) <= -1) return -1;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (str->tag)
|
if (str->tag)
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, QSE_T("["), 1, 0) <= -1 ||
|
if (write_to_current_stream (xli, QSE_T("["), 1, 0) <= -1 ||
|
||||||
write_to_current_stream(xli, str->tag, qse_strlen(str->tag), 0) <= -1 ||
|
write_to_current_stream (xli, str->tag, qse_strlen(str->tag), 0) <= -1 ||
|
||||||
write_to_current_stream(xli, QSE_T("]"), 1, 0) <= -1) return -1;
|
write_to_current_stream (xli, QSE_T("]"), 1, 0) <= -1) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1 ||
|
if (write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1 ||
|
||||||
write_to_current_stream(xli, str->ptr, str->len, 1) <= -1 ||
|
write_to_current_stream (xli, str->ptr, str->len, 1) <= -1 ||
|
||||||
write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1;
|
write_to_current_stream (xli, QSE_T("\""), 1, 0) <= -1) return -1;
|
||||||
if (!str->next) break;
|
if (!str->next) break;
|
||||||
|
|
||||||
if (write_to_current_stream(xli, QSE_T(", "), 2, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T(", "), 2, 0) <= -1) return -1;
|
||||||
str = str->next;
|
str = str->next;
|
||||||
}
|
}
|
||||||
if (write_to_current_stream(xli, QSE_T(";\n"), 2, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T(";\n"), 2, 0) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case QSE_XLI_LIST:
|
case QSE_XLI_LIST:
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, list_assign_symbol[tag_mode].ptr, list_assign_symbol[tag_mode].len, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T(" {\n"), 3, 0) <= -1 ||
|
||||||
|
|
||||||
if (write_to_current_stream(xli, QSE_T("{\n"), 2, 0) <= -1 ||
|
|
||||||
write_list (xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1 ||
|
write_list (xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1 ||
|
||||||
write_indentation (xli, depth) <= -1 ||
|
write_indentation (xli, depth) <= -1 ||
|
||||||
write_to_current_stream(xli, QSE_T("}\n"), 2, 0) <= -1) return -1;
|
write_to_current_stream (xli, QSE_T("}\n"), 2, 0) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,12 +341,12 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
|
|
||||||
for (i = 0; i < depth; i++)
|
for (i = 0; i < depth; i++)
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_to_current_stream(xli, QSE_T("#"), 1, 0) <= -1 ||
|
if (write_to_current_stream (xli, QSE_T("#"), 1, 0) <= -1 ||
|
||||||
write_to_current_stream(xli, str, qse_strlen(str), 0) <= -1 ||
|
write_to_current_stream (xli, str, qse_strlen(str), 0) <= -1 ||
|
||||||
write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1;
|
write_to_current_stream (xli, QSE_T("\n"), 1, 0) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,12 +357,12 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
|
|
||||||
for (i = 0; i < depth; i++)
|
for (i = 0; i < depth; i++)
|
||||||
{
|
{
|
||||||
if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T("\t"), 1, 0) <= -1) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_to_current_stream(xli, QSE_T("@include \""), 10, 0) <= -1 ||
|
if (write_to_current_stream (xli, QSE_T("@include \""), 10, 0) <= -1 ||
|
||||||
write_to_current_stream(xli, path, qse_strlen(path), 1) <= -1 ||
|
write_to_current_stream (xli, path, qse_strlen(path), 1) <= -1 ||
|
||||||
write_to_current_stream(xli, QSE_T("\";\n"), 3, 0) <= -1) return -1;
|
write_to_current_stream (xli, QSE_T("\";\n"), 3, 0) <= -1) return -1;
|
||||||
|
|
||||||
if (qse_xli_openwstream (xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1;
|
if (qse_xli_openwstream (xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1;
|
||||||
depth = 0;
|
depth = 0;
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
#include <qse/cmn/chr.h>
|
#include <qse/cmn/chr.h>
|
||||||
|
|
||||||
static qse_xli_root_list_t* make_root (qse_xli_t* xli);
|
static qse_xli_root_list_t* make_root (qse_xli_t* xli);
|
||||||
static void free_val (qse_xli_root_list_t* xli, qse_xli_val_t* val);
|
static void free_val (qse_xli_root_list_t* root, qse_xli_val_t* val);
|
||||||
static void free_list (qse_xli_root_list_t* xli, qse_xli_list_t* list);
|
static void free_list (qse_xli_root_list_t* root, qse_xli_list_t* list);
|
||||||
static void free_atom (qse_xli_root_list_t* xli, qse_xli_atom_t* atom);
|
static void free_atom (qse_xli_root_list_t* root, qse_xli_atom_t* atom);
|
||||||
|
|
||||||
qse_xli_t* qse_xli_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_size_t rootxtnsize, qse_xli_errnum_t* errnum)
|
qse_xli_t* qse_xli_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_size_t rootxtnsize, qse_xli_errnum_t* errnum)
|
||||||
{
|
{
|
||||||
@ -289,18 +289,18 @@ qse_xli_pair_t* qse_xli_insertpair (
|
|||||||
qse_cstr_t a, * ap = QSE_NULL;
|
qse_cstr_t a, * ap = QSE_NULL;
|
||||||
qse_cstr_t t, * tp = QSE_NULL;
|
qse_cstr_t t, * tp = QSE_NULL;
|
||||||
|
|
||||||
k.ptr = key;
|
k.ptr = (qse_char_t*)key;
|
||||||
k.len = qse_strlen (key);
|
k.len = qse_strlen(key);
|
||||||
|
|
||||||
if (alias)
|
if (alias)
|
||||||
{
|
{
|
||||||
a.ptr = alias;
|
a.ptr = (qse_char_t*)alias;
|
||||||
a.len = qse_strlen (alias);
|
a.len = qse_strlen (alias);
|
||||||
ap = &a;
|
ap = &a;
|
||||||
}
|
}
|
||||||
if (keytag)
|
if (keytag)
|
||||||
{
|
{
|
||||||
t.ptr = keytag;
|
t.ptr = (qse_char_t*)keytag;
|
||||||
t.len = qse_strlen (keytag);
|
t.len = qse_strlen (keytag);
|
||||||
tp = &t;
|
tp = &t;
|
||||||
}
|
}
|
||||||
@ -339,29 +339,10 @@ void qse_xli_deletepair (qse_xli_t* xli, qse_xli_pair_t* pair)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------ */
|
/* ------------------------------------------------------ */
|
||||||
qse_xli_pair_t* qse_xli_insertpairwithemptylist (
|
|
||||||
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer,
|
|
||||||
const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag)
|
|
||||||
{
|
|
||||||
qse_xli_list_t* val;
|
|
||||||
qse_xli_pair_t* tmp;
|
|
||||||
|
|
||||||
val = qse_xli_callocmem (xli, QSE_SIZEOF(*val));
|
qse_xli_str_t* qse_xli_makestrval (qse_xli_t* xli, const qse_cstr_t* value, const qse_char_t* strtag)
|
||||||
if (!val) return QSE_NULL;
|
|
||||||
|
|
||||||
val->type = QSE_XLI_LIST;
|
|
||||||
tmp = qse_xli_insertpair (xli, parent, peer, key, alias, keytag, (qse_xli_val_t*)val);
|
|
||||||
if (!tmp) qse_xli_freemem (xli, val);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
qse_xli_pair_t* qse_xli_insertpairwithstr (
|
|
||||||
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer,
|
|
||||||
const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag,
|
|
||||||
const qse_cstr_t* value, const qse_char_t* strtag)
|
|
||||||
{
|
{
|
||||||
qse_xli_str_t* val;
|
qse_xli_str_t* val;
|
||||||
qse_xli_pair_t* tmp;
|
|
||||||
qse_size_t reqlen;
|
qse_size_t reqlen;
|
||||||
|
|
||||||
reqlen = QSE_SIZEOF(*val) + ((value->len + 1) * QSE_SIZEOF(*value->ptr));
|
reqlen = QSE_SIZEOF(*val) + ((value->len + 1) * QSE_SIZEOF(*value->ptr));
|
||||||
@ -382,6 +363,51 @@ qse_xli_pair_t* qse_xli_insertpairwithstr (
|
|||||||
qse_strcpy ((qse_char_t*)val->tag, strtag);
|
qse_strcpy ((qse_char_t*)val->tag, strtag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_xli_list_t* qse_xli_makelistval (qse_xli_t* xli)
|
||||||
|
{
|
||||||
|
qse_xli_list_t* val;
|
||||||
|
|
||||||
|
val = qse_xli_callocmem (xli, QSE_SIZEOF(*val));
|
||||||
|
if (!val) return QSE_NULL;
|
||||||
|
|
||||||
|
val->type = QSE_XLI_LIST;
|
||||||
|
val->head = QSE_NULL;
|
||||||
|
val->tail = QSE_NULL;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------ */
|
||||||
|
|
||||||
|
qse_xli_pair_t* qse_xli_insertpairwithemptylist (
|
||||||
|
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer,
|
||||||
|
const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag)
|
||||||
|
{
|
||||||
|
qse_xli_list_t* val;
|
||||||
|
qse_xli_pair_t* tmp;
|
||||||
|
|
||||||
|
val = qse_xli_makelistval(xli);
|
||||||
|
if (!val) return QSE_NULL;
|
||||||
|
|
||||||
|
tmp = qse_xli_insertpair (xli, parent, peer, key, alias, keytag, (qse_xli_val_t*)val);
|
||||||
|
if (!tmp) qse_xli_freemem (xli, val);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_xli_pair_t* qse_xli_insertpairwithstr (
|
||||||
|
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer,
|
||||||
|
const qse_char_t* key, const qse_char_t* alias, const qse_char_t* keytag,
|
||||||
|
const qse_cstr_t* value, const qse_char_t* strtag)
|
||||||
|
{
|
||||||
|
qse_xli_str_t* val;
|
||||||
|
qse_xli_pair_t* tmp;
|
||||||
|
|
||||||
|
val = qse_xli_makestrval (xli, value, strtag);
|
||||||
|
if (!val) return QSE_NULL;
|
||||||
|
|
||||||
tmp = qse_xli_insertpair (xli, parent, peer, key, alias, keytag, (qse_xli_val_t*)val);
|
tmp = qse_xli_insertpair (xli, parent, peer, key, alias, keytag, (qse_xli_val_t*)val);
|
||||||
if (!tmp) qse_xli_freemem (xli, val);
|
if (!tmp) qse_xli_freemem (xli, val);
|
||||||
return tmp;
|
return tmp;
|
||||||
@ -496,10 +522,9 @@ static qse_xli_root_list_t* make_root (qse_xli_t* xli)
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_val (qse_xli_root_list_t* root, qse_xli_val_t* val)
|
|
||||||
|
static void unsafe_free_val (qse_xli_root_list_t* root, qse_xli_val_t* val)
|
||||||
{
|
{
|
||||||
if ((qse_xli_nil_t*)val != &root->xnil)
|
|
||||||
{
|
|
||||||
if (val->type == QSE_XLI_LIST)
|
if (val->type == QSE_XLI_LIST)
|
||||||
{
|
{
|
||||||
free_list (root, (qse_xli_list_t*)val);
|
free_list (root, (qse_xli_list_t*)val);
|
||||||
@ -518,6 +543,18 @@ static void free_val (qse_xli_root_list_t* root, qse_xli_val_t* val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QSE_MMGR_FREE (root->mmgr, val);
|
QSE_MMGR_FREE (root->mmgr, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qse_xli_freeval (qse_xli_t* xli, qse_xli_val_t* val)
|
||||||
|
{
|
||||||
|
unsafe_free_val (xli->root, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_val (qse_xli_root_list_t* root, qse_xli_val_t* val)
|
||||||
|
{
|
||||||
|
if ((qse_xli_nil_t*)val != &root->xnil)
|
||||||
|
{
|
||||||
|
unsafe_free_val (root, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +616,7 @@ qse_xli_list_t* qse_xli_yieldroot (qse_xli_t* xli)
|
|||||||
{
|
{
|
||||||
qse_xli_root_list_t* tmp, * tmp2;
|
qse_xli_root_list_t* tmp, * tmp2;
|
||||||
|
|
||||||
tmp = make_root (xli);
|
tmp = make_root(xli);
|
||||||
if (!tmp) return QSE_NULL;
|
if (!tmp) return QSE_NULL;
|
||||||
|
|
||||||
tmp2 = xli->root;
|
tmp2 = xli->root;
|
||||||
@ -732,7 +769,7 @@ const qse_char_t* get_next_fqpn_segment (qse_xli_t* xli, const qse_char_t* fqpn,
|
|||||||
* so if your alias contains these characters (in a quoted string),
|
* so if your alias contains these characters (in a quoted string),
|
||||||
* you can't reference it using a dotted key name. */
|
* you can't reference it using a dotted key name. */
|
||||||
seg->idxtype = FQPN_SEG_IDX_ALIAS;
|
seg->idxtype = FQPN_SEG_IDX_ALIAS;
|
||||||
seg->idx.alias.ptr = ptr;
|
seg->idx.alias.ptr = (qse_char_t*)ptr;
|
||||||
while (*ptr != QSE_T('}') && *ptr != QSE_T('\0')) ptr++;
|
while (*ptr != QSE_T('}') && *ptr != QSE_T('\0')) ptr++;
|
||||||
seg->idx.alias.len = ptr - seg->idx.alias.ptr;
|
seg->idx.alias.len = ptr - seg->idx.alias.ptr;
|
||||||
|
|
||||||
@ -1010,7 +1047,7 @@ int qse_xli_definepair (qse_xli_t* xli, const qse_char_t* fqpn, const qse_xli_sc
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qse_rbt_upsert (xli->schema, fqpn, qse_strlen(fqpn), scm, QSE_SIZEOF(*scm)) == QSE_NULL)
|
if (qse_rbt_upsert (xli->schema, (void*)fqpn, qse_strlen(fqpn), (void*)scm, QSE_SIZEOF(*scm)) == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1171,8 +1208,6 @@ noent:
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void* qse_getxlipairxtn (qse_xli_pair_t* pair)
|
void* qse_getxlipairxtn (qse_xli_pair_t* pair)
|
||||||
|
@ -36,8 +36,8 @@ enum qse_xli_tok_type_t
|
|||||||
{
|
{
|
||||||
QSE_XLI_TOK_EOF,
|
QSE_XLI_TOK_EOF,
|
||||||
QSE_XLI_TOK_XINCLUDE,
|
QSE_XLI_TOK_XINCLUDE,
|
||||||
QSE_XLI_TOK_SEMICOLON,
|
|
||||||
QSE_XLI_TOK_COLON,
|
QSE_XLI_TOK_COLON,
|
||||||
|
QSE_XLI_TOK_SEMICOLON,
|
||||||
QSE_XLI_TOK_LBRACE,
|
QSE_XLI_TOK_LBRACE,
|
||||||
QSE_XLI_TOK_RBRACE,
|
QSE_XLI_TOK_RBRACE,
|
||||||
QSE_XLI_TOK_LBRACK,
|
QSE_XLI_TOK_LBRACK,
|
||||||
@ -103,7 +103,7 @@ struct qse_xli_t
|
|||||||
qse_xli_ecb_t* ecb;
|
qse_xli_ecb_t* ecb;
|
||||||
|
|
||||||
qse_xli_root_list_t* root;
|
qse_xli_root_list_t* root;
|
||||||
qse_xli_list_link_t* parlink; /* link that points to the list being read currently */
|
qse_xli_list_link_t* parlink; /* internal use only - link that points to the list being read currently */
|
||||||
|
|
||||||
qse_str_t* dotted_curkey;
|
qse_str_t* dotted_curkey;
|
||||||
qse_rbt_t* schema;
|
qse_rbt_t* schema;
|
||||||
@ -143,7 +143,6 @@ const qse_char_t* qse_xli_dflerrstr (
|
|||||||
void qse_xli_clearrionames (qse_xli_t* xli);
|
void qse_xli_clearrionames (qse_xli_t* xli);
|
||||||
void qse_xli_clearwionames (qse_xli_t* xli);
|
void qse_xli_clearwionames (qse_xli_t* xli);
|
||||||
|
|
||||||
|
|
||||||
int qse_xli_getchar (qse_xli_t* xli);
|
int qse_xli_getchar (qse_xli_t* xli);
|
||||||
int qse_xli_openrstream (qse_xli_t* xli, qse_xli_io_arg_t* arg);
|
int qse_xli_openrstream (qse_xli_t* xli, qse_xli_io_arg_t* arg);
|
||||||
int qse_xli_closeactiverstream (qse_xli_t* xli);
|
int qse_xli_closeactiverstream (qse_xli_t* xli);
|
||||||
@ -155,6 +154,12 @@ int qse_xli_flushwstream (qse_xli_t* xli, qse_xli_io_arg_t* arg);
|
|||||||
qse_xli_list_link_t* qse_xli_makelistlink (qse_xli_t* xli, qse_xli_list_t* parlist);
|
qse_xli_list_link_t* qse_xli_makelistlink (qse_xli_t* xli, qse_xli_list_t* parlist);
|
||||||
void qse_xli_freelistlink (qse_xli_t* xli, qse_xli_list_link_t* link);
|
void qse_xli_freelistlink (qse_xli_t* xli, qse_xli_list_link_t* link);
|
||||||
|
|
||||||
|
|
||||||
|
qse_xli_str_t* qse_xli_makestrval (qse_xli_t* xli, const qse_cstr_t* value, const qse_char_t* strtag);
|
||||||
|
qse_xli_list_t* qse_xli_makelistval (qse_xli_t* xli);
|
||||||
|
qse_xli_pair_t* qse_xli_makepairval (qse_xli_t* xli);
|
||||||
|
void qse_xli_freeval (qse_xli_t* xli, qse_xli_val_t* val);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user