added quite some xli code to read the json formatted data
This commit is contained in:
parent
779b335710
commit
4636a46acb
@ -164,6 +164,7 @@ static void print_usage (qse_sio_t* out, int argc, qse_char_t* argv[])
|
|||||||
qse_fprintf (out, QSE_T(" -J file specify a json output 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(" -b allow true and false as boolean values\n"));
|
||||||
qse_fprintf (out, QSE_T(" -f keep file inclusion info\n"));
|
qse_fprintf (out, QSE_T(" -f keep file inclusion info\n"));
|
||||||
qse_fprintf (out, QSE_T(" -t keep comment text\n"));
|
qse_fprintf (out, QSE_T(" -t keep comment text\n"));
|
||||||
qse_fprintf (out, QSE_T(" -s allow multi-segmented strings\n"));
|
qse_fprintf (out, QSE_T(" -s allow multi-segmented strings\n"));
|
||||||
@ -199,9 +200,9 @@ 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:j:J:uaftsdnlKSvm:X:"),
|
QSE_T("hi:o:I:O:j:J:uabftsdnlKSvm:X:"),
|
||||||
#else
|
#else
|
||||||
QSE_T("hi:o:I:O:j:J:uaftsdnlKSvm:"),
|
QSE_T("hi:o:I:O:j:J:uabftsdnlKSvm:"),
|
||||||
#endif
|
#endif
|
||||||
lng
|
lng
|
||||||
};
|
};
|
||||||
@ -273,6 +274,10 @@ static int handle_args (int argc, qse_char_t* argv[])
|
|||||||
g_trait |= QSE_XLI_KEYALIAS;
|
g_trait |= QSE_XLI_KEYALIAS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QSE_T('b'):
|
||||||
|
g_trait |= QSE_XLI_BOOLEAN;
|
||||||
|
break;
|
||||||
|
|
||||||
case QSE_T('f'):
|
case QSE_T('f'):
|
||||||
g_trait |= QSE_XLI_KEEPFILE;
|
g_trait |= QSE_XLI_KEEPFILE;
|
||||||
break;
|
break;
|
||||||
@ -547,7 +552,15 @@ static int xli_main (int argc, qse_char_t* argv[])
|
|||||||
}
|
}
|
||||||
else if (pair->val->type == QSE_XLI_NIL)
|
else if (pair->val->type == QSE_XLI_NIL)
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("#NIL\n"));
|
qse_printf (QSE_T("nil\n"));
|
||||||
|
}
|
||||||
|
else if (pair->val->type == QSE_XLI_TRUE)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("true\n"));
|
||||||
|
}
|
||||||
|
else if (pair->val->type == QSE_XLI_FALSE)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("false\n"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -567,6 +580,11 @@ static int xli_main (int argc, qse_char_t* argv[])
|
|||||||
ret = (g_io_flags & IO_FLAG_JSON_OUTPUT)? qse_xli_writejsonstd(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):
|
(g_io_flags & IO_FLAG_INI_OUTPUT)? qse_xli_writeinistd(xli, QSE_NULL, &out):
|
||||||
qse_xli_writestd(xli, QSE_NULL, &out);
|
qse_xli_writestd(xli, QSE_NULL, &out);
|
||||||
|
if (ret <= -1)
|
||||||
|
{
|
||||||
|
qse_fprintf (QSE_STDERR, QSE_T("WARNING: cannot write - %s\n"), qse_xli_geterrmsg(xli));
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -71,7 +71,8 @@ enum qse_xli_errnum_t
|
|||||||
QSE_XLI_ELBREQ, /**< { or = expected in place of '${0}' */
|
QSE_XLI_ELBREQ, /**< { or = expected in place of '${0}' */
|
||||||
QSE_XLI_ERBRACE, /**< } expected in place of '${0}' */
|
QSE_XLI_ERBRACE, /**< } expected in place of '${0}' */
|
||||||
QSE_XLI_ERBRACK, /**< ] 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_ECOMMA, /**< , expected in place of '${0}' */
|
||||||
|
QSE_XLI_EVALUE, /**< 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 */
|
||||||
QSE_XLI_EINCLSTR ,/**< '@include' not followed by a string */
|
QSE_XLI_EINCLSTR ,/**< '@include' not followed by a string */
|
||||||
@ -147,13 +148,20 @@ 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),
|
||||||
|
|
||||||
|
/** enable the keyword 'true' and 'false' in the xli format.
|
||||||
|
* the json format always supports these keywords regardless of this option.
|
||||||
|
* the ini format doesn't support these regardless of this option. */
|
||||||
|
QSE_XLI_BOOLEAN = (1 << 11),
|
||||||
|
|
||||||
/** enable pair validation against pair definitions while reading */
|
/** enable pair validation against pair definitions while reading */
|
||||||
QSE_XLI_VALIDATE = (1 << 11)
|
QSE_XLI_VALIDATE = (1 << 12)
|
||||||
};
|
};
|
||||||
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_true_t qse_xli_true_t;
|
||||||
|
typedef struct qse_xli_false_t qse_xli_false_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_list_t qse_xli_list_t;
|
typedef struct qse_xli_list_t qse_xli_list_t;
|
||||||
|
|
||||||
@ -166,11 +174,20 @@ typedef struct qse_xli_eof_t qse_xli_eof_t;
|
|||||||
enum qse_xli_val_type_t
|
enum qse_xli_val_type_t
|
||||||
{
|
{
|
||||||
QSE_XLI_NIL,
|
QSE_XLI_NIL,
|
||||||
|
QSE_XLI_TRUE,
|
||||||
|
QSE_XLI_FALSE,
|
||||||
QSE_XLI_STR,
|
QSE_XLI_STR,
|
||||||
QSE_XLI_LIST,
|
QSE_XLI_LIST,
|
||||||
};
|
};
|
||||||
typedef enum qse_xli_val_type_t qse_xli_val_type_t;
|
typedef enum qse_xli_val_type_t qse_xli_val_type_t;
|
||||||
|
|
||||||
|
enum qse_xli_str_flag_t
|
||||||
|
{
|
||||||
|
QSE_XLI_STR_NSTR = (1 << 0),
|
||||||
|
QSE_XLI_STR_RADIX = (1 << 1),
|
||||||
|
QSE_XLI_STR_FLOAT = (1 << 2)
|
||||||
|
};
|
||||||
|
|
||||||
enum qse_xli_atom_type_t
|
enum qse_xli_atom_type_t
|
||||||
{
|
{
|
||||||
QSE_XLI_PAIR,
|
QSE_XLI_PAIR,
|
||||||
@ -193,6 +210,16 @@ struct qse_xli_nil_t
|
|||||||
QSE_XLI_VAL_HDR;
|
QSE_XLI_VAL_HDR;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct qse_xli_true_t
|
||||||
|
{
|
||||||
|
QSE_XLI_VAL_HDR;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qse_xli_false_t
|
||||||
|
{
|
||||||
|
QSE_XLI_VAL_HDR;
|
||||||
|
};
|
||||||
|
|
||||||
struct qse_xli_list_t
|
struct qse_xli_list_t
|
||||||
{
|
{
|
||||||
QSE_XLI_VAL_HDR;
|
QSE_XLI_VAL_HDR;
|
||||||
@ -203,6 +230,7 @@ struct qse_xli_list_t
|
|||||||
struct qse_xli_str_t
|
struct qse_xli_str_t
|
||||||
{
|
{
|
||||||
QSE_XLI_VAL_HDR;
|
QSE_XLI_VAL_HDR;
|
||||||
|
int flags;
|
||||||
const qse_char_t* tag;
|
const qse_char_t* tag;
|
||||||
const qse_char_t* ptr;
|
const qse_char_t* ptr;
|
||||||
qse_size_t len;
|
qse_size_t len;
|
||||||
|
@ -51,7 +51,8 @@ const qse_char_t* qse_xli_dflerrstr (const qse_xli_t* xli, qse_xli_errnum_t errn
|
|||||||
QSE_T("left-brace or equal-sign 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("right-bracket expected in place of '${0}'"),
|
||||||
QSE_T("pair value expected in place of '${0}'"),
|
QSE_T("comma expected in place of '${0}'"),
|
||||||
|
QSE_T("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"),
|
||||||
QSE_T("'@include' not followed by a string"),
|
QSE_T("'@include' not followed by a string"),
|
||||||
|
@ -84,14 +84,17 @@ typedef struct kwent_t kwent_t;
|
|||||||
struct kwent_t
|
struct kwent_t
|
||||||
{
|
{
|
||||||
qse_cstr_t name;
|
qse_cstr_t name;
|
||||||
int type;
|
qse_xli_tok_type_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* note that the keyword must start with @. */
|
/* note that the keyword must start with @. */
|
||||||
static kwent_t kwtab[] =
|
static kwent_t kwtab[] =
|
||||||
{
|
{
|
||||||
/* keep it sorted by the first field for binary search */
|
/* keep it sorted by the first field for binary search */
|
||||||
{ { QSE_T("@include"), 8 }, QSE_XLI_TOK_XINCLUDE }
|
{ { QSE_T("@include"), 8 }, QSE_XLI_TOK_XINCLUDE },
|
||||||
|
{ { QSE_T("false"), 5 }, QSE_XLI_TOK_FALSE },
|
||||||
|
{ { QSE_T("nil"), 3 }, QSE_XLI_TOK_NIL },
|
||||||
|
{ { QSE_T("true"), 4 }, QSE_XLI_TOK_TRUE }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int skip_spaces (qse_xli_t* xli)
|
static int skip_spaces (qse_xli_t* xli)
|
||||||
@ -130,7 +133,7 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
static qse_xli_tok_type_t classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
||||||
{
|
{
|
||||||
/* perform binary search */
|
/* perform binary search */
|
||||||
|
|
||||||
@ -316,7 +319,6 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
|||||||
{
|
{
|
||||||
qse_cint_t c;
|
qse_cint_t c;
|
||||||
int n;
|
int n;
|
||||||
int skip_semicolon_after_include = 0;
|
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
do
|
do
|
||||||
@ -341,7 +343,6 @@ retry:
|
|||||||
{
|
{
|
||||||
/*xli->rio.last = xli->rio.inp->last;*/
|
/*xli->rio.last = xli->rio.inp->last;*/
|
||||||
/* mark that i'm retrying after end of an included file */
|
/* mark that i'm retrying after end of an included file */
|
||||||
skip_semicolon_after_include = 1;
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +353,7 @@ retry:
|
|||||||
{
|
{
|
||||||
/* keyword/directive - start with @ */
|
/* keyword/directive - start with @ */
|
||||||
|
|
||||||
int type;
|
qse_xli_tok_type_t type;
|
||||||
|
|
||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
GET_CHAR_TO (xli, c);
|
GET_CHAR_TO (xli, c);
|
||||||
@ -382,43 +383,22 @@ retry:
|
|||||||
}
|
}
|
||||||
SET_TOKEN_TYPE (xli, tok, type);
|
SET_TOKEN_TYPE (xli, tok, type);
|
||||||
}
|
}
|
||||||
else if (c == QSE_T('_') || QSE_ISALPHA (c) ||
|
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);
|
qse_xli_tok_type_t type;
|
||||||
int all_digits = 1;
|
|
||||||
|
|
||||||
/* a normal identifier can be composed of wider varieties of
|
do
|
||||||
* characters than a keyword/directive */
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
ADD_TOKEN_CHAR (xli, tok, c);
|
ADD_TOKEN_CHAR (xli, tok, c);
|
||||||
GET_CHAR_TO (xli, 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;
|
|
||||||
}
|
}
|
||||||
|
while (c == QSE_T('_') || QSE_ISALNUM (c));
|
||||||
|
|
||||||
|
type = classify_ident(xli, QSE_STR_XSTR(tok->name));
|
||||||
|
SET_TOKEN_TYPE (xli, tok, type);
|
||||||
|
}
|
||||||
|
/* TODO: negative number, floating-point number, etc */
|
||||||
else if (QSE_ISDIGIT(c))
|
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);
|
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_NSTR);
|
||||||
do
|
do
|
||||||
@ -520,24 +500,8 @@ retry:
|
|||||||
}
|
}
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,9 +551,19 @@ static qse_xli_val_t* __read_value (qse_xli_t* xli)
|
|||||||
|
|
||||||
if (begin_include(xli) <= -1) 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))
|
else 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))
|
||||||
{
|
{
|
||||||
return (qse_xli_val_t*)qse_xli_makestrval(xli, QSE_STR_XSTR(xli->tok.name), QSE_NULL);
|
qse_xli_str_t* sv;
|
||||||
|
|
||||||
|
sv = qse_xli_makestrval(xli, QSE_STR_XSTR(xli->tok.name), QSE_NULL);
|
||||||
|
if (!sv) return QSE_NULL;
|
||||||
|
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_NSTR))
|
||||||
|
{
|
||||||
|
sv->flags |= QSE_XLI_STR_NSTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (qse_xli_val_t*)sv;
|
||||||
}
|
}
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_LBRACE))
|
else if (MATCH(xli, QSE_XLI_TOK_LBRACE))
|
||||||
{
|
{
|
||||||
@ -614,13 +588,25 @@ static qse_xli_val_t* __read_value (qse_xli_t* xli)
|
|||||||
if (!lv) return QSE_NULL;
|
if (!lv) return QSE_NULL;
|
||||||
|
|
||||||
if (get_token(xli) <= -1 || read_array(xli, lv) <= -1)
|
if (get_token(xli) <= -1 || read_array(xli, lv) <= -1)
|
||||||
if (!lv)
|
|
||||||
{
|
{
|
||||||
qse_xli_freeval (xli, (qse_xli_val_t*)lv);
|
qse_xli_freeval (xli, (qse_xli_val_t*)lv);
|
||||||
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (qse_xli_val_t*)lv;
|
return (qse_xli_val_t*)lv;
|
||||||
}
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_NIL))
|
||||||
|
{
|
||||||
|
return (qse_xli_val_t*)&xli->root->xnil;
|
||||||
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_TRUE))
|
||||||
|
{
|
||||||
|
return (qse_xli_val_t*)&xli->root->xtrue;
|
||||||
|
}
|
||||||
|
else if (MATCH(xli, QSE_XLI_TOK_FALSE))
|
||||||
|
{
|
||||||
|
return (qse_xli_val_t*)&xli->root->xfalse;
|
||||||
|
}
|
||||||
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
else if (MATCH(xli, QSE_XLI_TOK_TEXT))
|
||||||
{
|
{
|
||||||
if (get_token(xli) <= -1) return QSE_NULL;
|
if (get_token(xli) <= -1) return QSE_NULL;
|
||||||
@ -631,10 +617,10 @@ static qse_xli_val_t* __read_value (qse_xli_t* xli)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_EVALUE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct rpair_t
|
struct rpair_t
|
||||||
{
|
{
|
||||||
qse_char_t* key;
|
qse_char_t* key;
|
||||||
@ -697,17 +683,17 @@ static int __read_array (qse_xli_t* xli)
|
|||||||
|
|
||||||
if (get_token(xli) <= -1) return -1;
|
if (get_token(xli) <= -1) return -1;
|
||||||
|
|
||||||
if (MATCH(xli, QSE_XLI_TOK_COMMA))
|
if (MATCH(xli, QSE_XLI_TOK_RBRACK)) break;
|
||||||
|
if (!MATCH(xli, QSE_XLI_TOK_COMMA))
|
||||||
{
|
{
|
||||||
if (get_token(xli) <= -1) return -1;
|
qse_xli_seterror (xli, QSE_XLI_ECOMMA, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
continue;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MATCH(xli, QSE_XLI_TOK_RBRACK)) break;
|
if (get_token(xli) <= -1) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_array (qse_xli_t* xli, qse_xli_list_t* lv)
|
static int read_array (qse_xli_t* xli, qse_xli_list_t* lv)
|
||||||
@ -858,8 +844,17 @@ int qse_xli_readjson (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))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (MATCH(xli, QSE_XLI_TOK_LBRACE) || MATCH(xli, QSE_XLI_TOK_LBRACK) ||
|
||||||
|
MATCH(xli, QSE_XLI_TOK_DQSTR) || MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ECOMMA, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ typedef struct kwent_t kwent_t;
|
|||||||
struct kwent_t
|
struct kwent_t
|
||||||
{
|
{
|
||||||
qse_cstr_t name;
|
qse_cstr_t name;
|
||||||
int type;
|
qse_xli_tok_type_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* note that the keyword must start with @. */
|
/* note that the keyword must start with @. */
|
||||||
@ -114,6 +114,13 @@ static kwent_t kwtab[] =
|
|||||||
{ { QSE_T("@include"), 8 }, QSE_XLI_TOK_XINCLUDE }
|
{ { QSE_T("@include"), 8 }, QSE_XLI_TOK_XINCLUDE }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static kwent_t boolkwtab[] =
|
||||||
|
{
|
||||||
|
/* keep it sorted by the first field for binary search */
|
||||||
|
{ { QSE_T("false"), 5 }, QSE_XLI_TOK_FALSE },
|
||||||
|
{ { QSE_T("true"), 4 }, QSE_XLI_TOK_TRUE }
|
||||||
|
};
|
||||||
|
|
||||||
int qse_xli_getchar (qse_xli_t* xli)
|
int qse_xli_getchar (qse_xli_t* xli)
|
||||||
{
|
{
|
||||||
qse_ssize_t n;
|
qse_ssize_t n;
|
||||||
@ -254,14 +261,21 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
static qse_xli_tok_type_t classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
||||||
{
|
{
|
||||||
/* perform binary search */
|
/* perform binary search */
|
||||||
|
|
||||||
/* declaring left, right, mid to be the int type is ok
|
/* declaring left, right, mid to be the int type is ok
|
||||||
* because we know kwtab is small enough. */
|
* because we know kwtab is small enough. */
|
||||||
int left = 0, right = QSE_COUNTOF(kwtab) - 1, mid;
|
int left, right, mid;
|
||||||
|
int bool_checked = 0;
|
||||||
|
kwent_t* kwtabp;
|
||||||
|
|
||||||
|
left = 0;
|
||||||
|
right = QSE_COUNTOF(kwtab) - 1;
|
||||||
|
kwtabp = kwtab;
|
||||||
|
|
||||||
|
retry:
|
||||||
while (left <= right)
|
while (left <= right)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
@ -269,7 +283,7 @@ static int classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
|||||||
|
|
||||||
/*mid = (left + right) / 2;*/
|
/*mid = (left + right) / 2;*/
|
||||||
mid = left + (right - left) / 2;
|
mid = left + (right - left) / 2;
|
||||||
kwp = &kwtab[mid];
|
kwp = &kwtabp[mid];
|
||||||
|
|
||||||
n = qse_strxncmp (kwp->name.ptr, kwp->name.len, name->ptr, name->len);
|
n = qse_strxncmp (kwp->name.ptr, kwp->name.len, name->ptr, name->len);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
@ -284,6 +298,15 @@ static int classify_ident (qse_xli_t* xli, const qse_cstr_t* name)
|
|||||||
else return kwp->type;
|
else return kwp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bool_checked && (xli->opt.trait & QSE_XLI_BOOLEAN))
|
||||||
|
{
|
||||||
|
bool_checked = 1;
|
||||||
|
kwtabp = boolkwtab;
|
||||||
|
left = 0;
|
||||||
|
right = QSE_COUNTOF(boolkwtab) - 1;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
return QSE_XLI_TOK_IDENT;
|
return QSE_XLI_TOK_IDENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,6 +536,7 @@ retry:
|
|||||||
{
|
{
|
||||||
int lead_digit = QSE_ISDIGIT(c);
|
int lead_digit = QSE_ISDIGIT(c);
|
||||||
int all_digits = 1;
|
int all_digits = 1;
|
||||||
|
qse_xli_tok_type_t type;
|
||||||
|
|
||||||
/* a normal identifier can be composed of wider varieties of
|
/* a normal identifier can be composed of wider varieties of
|
||||||
* characters than a keyword/directive */
|
* characters than a keyword/directive */
|
||||||
@ -541,7 +565,8 @@ retry:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_IDENT);
|
type = classify_ident (xli, QSE_STR_XSTR(tok->name));
|
||||||
|
SET_TOKEN_TYPE (xli, tok, type);
|
||||||
}
|
}
|
||||||
else if ((xli->tok_status & TOK_STATUS_ENABLE_NSTR) && QSE_ISDIGIT(c))
|
else if ((xli->tok_status & TOK_STATUS_ENABLE_NSTR) && QSE_ISDIGIT(c))
|
||||||
{
|
{
|
||||||
@ -854,7 +879,26 @@ 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_TRUE) || MATCH(xli, QSE_XLI_TOK_FALSE))
|
||||||
|
{
|
||||||
|
qse_xli_val_t* v;
|
||||||
|
|
||||||
|
v = MATCH(xli, QSE_XLI_TOK_TRUE)? (qse_xli_val_t*)&xli->root->xtrue:
|
||||||
|
(qse_xli_val_t*)&xli->root->xfalse;
|
||||||
|
pair = qse_xli_insertpair(xli, parlist, QSE_NULL, key.ptr, name, keytag, v);
|
||||||
|
if (pair == QSE_NULL) goto oops;
|
||||||
|
|
||||||
|
if (get_token (xli) <= -1) goto oops; /* skip the value */
|
||||||
|
|
||||||
|
if (!MATCH(xli, QSE_XLI_TOK_SEMICOLON))
|
||||||
|
{
|
||||||
|
qse_xli_seterror (xli, QSE_XLI_ESCOLON, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_token (xli) <= -1) goto oops; /* skip the value */
|
||||||
|
}
|
||||||
|
else 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_str_t* curstrseg;
|
qse_xli_str_t* curstrseg;
|
||||||
qse_size_t segcount = 0;
|
qse_size_t segcount = 0;
|
||||||
@ -870,6 +914,11 @@ 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 (MATCH(xli, QSE_XLI_TOK_NSTR))
|
||||||
|
{
|
||||||
|
((qse_xli_str_t*)pair->val)->flags |= QSE_XLI_STR_NSTR;
|
||||||
|
}
|
||||||
|
|
||||||
segcount++;
|
segcount++;
|
||||||
curstrseg = (qse_xli_str_t*)pair->val;
|
curstrseg = (qse_xli_str_t*)pair->val;
|
||||||
|
|
||||||
@ -935,13 +984,10 @@ static int read_pair (qse_xli_t* xli, const qse_char_t* keytag, const qse_xli_sc
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qse_xli_seterror (xli, QSE_XLI_EPAVAL, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
qse_xli_seterror (xli, QSE_XLI_EVALUE, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: check against schema */
|
/* TODO: check against schema */
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH(xli, QSE_XLI_TOK_LBRACE))
|
else if (!(xli->opt.trait & QSE_XLI_NOLIST) && MATCH(xli, QSE_XLI_TOK_LBRACE))
|
||||||
{
|
{
|
||||||
|
@ -468,8 +468,10 @@ 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 = (qse_char_t*)arg->name;
|
/*ea.ptr = (qse_char_t*)arg->name;
|
||||||
ea.len = qse_strlen(ea.ptr);
|
ea.len = qse_strlen(ea.ptr);*/
|
||||||
|
ea.ptr = (qse_char_t*)path;
|
||||||
|
ea.len = qse_strlen(path);
|
||||||
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
qse_xli_seterrnum (xli, QSE_XLI_EIOFIL, &ea);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,14 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
if (write_to_current_stream (xli, QSE_T("\n"), 1) <= -1) return -1;
|
if (write_to_current_stream (xli, QSE_T("\n"), 1) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_TRUE:
|
||||||
|
if (write_to_current_stream (xli, QSE_T("true\n"), 5) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_FALSE:
|
||||||
|
if (write_to_current_stream (xli, QSE_T("false\n"), 6) <= -1) return -1;
|
||||||
|
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;
|
||||||
|
@ -232,7 +232,15 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
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("nil;\n"), 5, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_TRUE:
|
||||||
|
if (write_to_current_stream(xli, QSE_T("true;\n"), 6, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_FALSE:
|
||||||
|
if (write_to_current_stream(xli, QSE_T("false;\n"), 7, 0) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_XLI_STR:
|
case QSE_XLI_STR:
|
||||||
|
@ -296,6 +296,14 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
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_TRUE:
|
||||||
|
if (write_to_current_stream (xli, QSE_T(" = true;\n"), 9, 0) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_FALSE:
|
||||||
|
if (write_to_current_stream (xli, QSE_T(" = false;\n"), 10, 0) <= -1) return -1;
|
||||||
|
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;
|
||||||
@ -310,9 +318,11 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth)
|
|||||||
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 ((!(str->flags & QSE_XLI_STR_NSTR) &&
|
||||||
|
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;
|
(!(str->flags & QSE_XLI_STR_NSTR) &&
|
||||||
|
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;
|
||||||
|
@ -320,7 +320,7 @@ void qse_xli_deletepair (qse_xli_t* xli, qse_xli_pair_t* pair)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (list->head == pair);
|
QSE_ASSERT (list->head == (qse_xli_atom_t*)pair);
|
||||||
list->head = pair->next;
|
list->head = pair->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ void qse_xli_deletepair (qse_xli_t* xli, qse_xli_pair_t* pair)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (list->tail == pair);
|
QSE_ASSERT (list->tail == (qse_xli_atom_t*)pair);
|
||||||
list->tail = pair->prev;
|
list->tail = pair->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,6 +352,7 @@ qse_xli_str_t* qse_xli_makestrval (qse_xli_t* xli, const qse_cstr_t* value, cons
|
|||||||
if (!val) return QSE_NULL;
|
if (!val) return QSE_NULL;
|
||||||
|
|
||||||
val->type = QSE_XLI_STR;
|
val->type = QSE_XLI_STR;
|
||||||
|
val->flags = 0;
|
||||||
|
|
||||||
qse_strncpy ((qse_char_t*)(val + 1), value->ptr, value->len);
|
qse_strncpy ((qse_char_t*)(val + 1), value->ptr, value->len);
|
||||||
val->ptr = (const qse_char_t*)(val + 1);
|
val->ptr = (const qse_char_t*)(val + 1);
|
||||||
@ -380,6 +381,81 @@ qse_xli_list_t* qse_xli_makelistval (qse_xli_t* xli)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_val (qse_xli_root_list_t* root, qse_xli_val_t* val)
|
||||||
|
{
|
||||||
|
switch (val->type)
|
||||||
|
{
|
||||||
|
case QSE_XLI_NIL:
|
||||||
|
QSE_ASSERT (val == (qse_xli_val_t*)&root->xnil);
|
||||||
|
return;
|
||||||
|
case QSE_XLI_TRUE:
|
||||||
|
QSE_ASSERT (val == (qse_xli_val_t*)&root->xtrue);
|
||||||
|
return;
|
||||||
|
case QSE_XLI_FALSE:
|
||||||
|
QSE_ASSERT (val == (qse_xli_val_t*)&root->xfalse);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case QSE_XLI_LIST:
|
||||||
|
free_list (root, (qse_xli_list_t*)val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QSE_XLI_STR:
|
||||||
|
{
|
||||||
|
qse_xli_str_t* cur, * next;
|
||||||
|
|
||||||
|
cur = ((qse_xli_str_t*)val)->next;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
next = cur->next;
|
||||||
|
QSE_MMGR_FREE (root->mmgr, cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MMGR_FREE (root->mmgr, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void free_atom (qse_xli_root_list_t* root, qse_xli_atom_t* atom)
|
||||||
|
{
|
||||||
|
/* Among all atom type, QSE_XLI_PAIR has a value to dispose of specially.
|
||||||
|
* A tag and an alise are inlined to the atom itself. see insert_atom()
|
||||||
|
* above for details.
|
||||||
|
*
|
||||||
|
* for QSE_XLI_TEXT, QSE_XLI_FILE, QSE_XLI_EOF, data are inlined to
|
||||||
|
* the atom itself as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (atom->type == QSE_XLI_PAIR) free_val (root, ((qse_xli_pair_t*)atom)->val);
|
||||||
|
QSE_MMGR_FREE (root->mmgr, atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_list (qse_xli_root_list_t* root, qse_xli_list_t* list)
|
||||||
|
{
|
||||||
|
qse_xli_atom_t* p, * n;
|
||||||
|
|
||||||
|
p = list->head;
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
n = p->next;
|
||||||
|
free_atom (root, p);
|
||||||
|
p = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->head = QSE_NULL;
|
||||||
|
list->tail = QSE_NULL;
|
||||||
|
|
||||||
|
/* this doesn't destroy the list itself.
|
||||||
|
* the caller must destory the list if necessary. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void qse_xli_freeval (qse_xli_t* xli, qse_xli_val_t* val)
|
||||||
|
{
|
||||||
|
free_val (xli->root, val);
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------ */
|
/* ------------------------------------------------------ */
|
||||||
|
|
||||||
qse_xli_pair_t* qse_xli_insertpairwithemptylist (
|
qse_xli_pair_t* qse_xli_insertpairwithemptylist (
|
||||||
@ -517,80 +593,13 @@ static qse_xli_root_list_t* make_root (qse_xli_t* xli)
|
|||||||
QSE_MEMSET (tmp, 0, QSE_SIZEOF(*tmp) + xli->opt.root_xtnsize);
|
QSE_MEMSET (tmp, 0, QSE_SIZEOF(*tmp) + xli->opt.root_xtnsize);
|
||||||
tmp->list.type = QSE_XLI_LIST;
|
tmp->list.type = QSE_XLI_LIST;
|
||||||
tmp->xnil.type = QSE_XLI_NIL;
|
tmp->xnil.type = QSE_XLI_NIL;
|
||||||
|
tmp->xtrue.type = QSE_XLI_TRUE;
|
||||||
|
tmp->xfalse.type = QSE_XLI_FALSE;
|
||||||
tmp->mmgr = xli->mmgr;
|
tmp->mmgr = xli->mmgr;
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void unsafe_free_val (qse_xli_root_list_t* root, qse_xli_val_t* val)
|
|
||||||
{
|
|
||||||
if (val->type == QSE_XLI_LIST)
|
|
||||||
{
|
|
||||||
free_list (root, (qse_xli_list_t*)val);
|
|
||||||
}
|
|
||||||
else if (val->type == QSE_XLI_STR)
|
|
||||||
{
|
|
||||||
qse_xli_str_t* cur, * next;
|
|
||||||
|
|
||||||
cur = ((qse_xli_str_t*)val)->next;
|
|
||||||
while (cur)
|
|
||||||
{
|
|
||||||
next = cur->next;
|
|
||||||
QSE_MMGR_FREE (root->mmgr, cur);
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_atom (qse_xli_root_list_t* root, qse_xli_atom_t* atom)
|
|
||||||
{
|
|
||||||
/* Among all atom type, QSE_XLI_PAIR has a value to dispose of specially.
|
|
||||||
* A tag and an alise are inlined to the atom itself. see insert_atom()
|
|
||||||
* above for details.
|
|
||||||
*
|
|
||||||
* for QSE_XLI_TEXT, QSE_XLI_FILE, QSE_XLI_EOF, data are inlined to
|
|
||||||
* the atom itself as well.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (atom->type == QSE_XLI_PAIR) free_val (root, ((qse_xli_pair_t*)atom)->val);
|
|
||||||
QSE_MMGR_FREE (root->mmgr, atom);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_list (qse_xli_root_list_t* root, qse_xli_list_t* list)
|
|
||||||
{
|
|
||||||
qse_xli_atom_t* p, * n;
|
|
||||||
|
|
||||||
p = list->head;
|
|
||||||
while (p)
|
|
||||||
{
|
|
||||||
n = p->next;
|
|
||||||
free_atom (root, p);
|
|
||||||
p = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
list->head = QSE_NULL;
|
|
||||||
list->tail = QSE_NULL;
|
|
||||||
|
|
||||||
/* this doesn't destroy the list itself.
|
|
||||||
* the caller must destory the list if necessary. */
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_xli_clear (qse_xli_t* xli)
|
void qse_xli_clear (qse_xli_t* xli)
|
||||||
{
|
{
|
||||||
free_list (xli->root, &xli->root->list);
|
free_list (xli->root, &xli->root->list);
|
||||||
@ -726,7 +735,8 @@ const qse_char_t* get_next_fqpn_segment (qse_xli_t* xli, const qse_char_t* fqpn,
|
|||||||
{
|
{
|
||||||
const qse_char_t* ptr;
|
const qse_char_t* ptr;
|
||||||
|
|
||||||
seg->key.ptr = ptr = fqpn;
|
ptr = fqpn;
|
||||||
|
seg->key.ptr = (qse_char_t*)ptr;
|
||||||
while (*ptr != QSE_T('\0') && *ptr != xli->opt.key_splitter && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++;
|
while (*ptr != QSE_T('\0') && *ptr != xli->opt.key_splitter && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++;
|
||||||
if (ptr == seg->key.ptr) goto inval; /* no key part */
|
if (ptr == seg->key.ptr) goto inval; /* no key part */
|
||||||
seg->key.len = ptr - seg->key.ptr;
|
seg->key.len = ptr - seg->key.ptr;
|
||||||
|
@ -36,6 +36,9 @@ 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_TRUE,
|
||||||
|
QSE_XLI_TOK_FALSE,
|
||||||
|
QSE_XLI_TOK_NIL,
|
||||||
QSE_XLI_TOK_COLON,
|
QSE_XLI_TOK_COLON,
|
||||||
QSE_XLI_TOK_SEMICOLON,
|
QSE_XLI_TOK_SEMICOLON,
|
||||||
QSE_XLI_TOK_LBRACE,
|
QSE_XLI_TOK_LBRACE,
|
||||||
@ -80,6 +83,8 @@ struct qse_xli_root_list_t
|
|||||||
{
|
{
|
||||||
qse_xli_list_t list;
|
qse_xli_list_t list;
|
||||||
qse_xli_nil_t xnil;
|
qse_xli_nil_t xnil;
|
||||||
|
qse_xli_true_t xtrue;
|
||||||
|
qse_xli_false_t xfalse;
|
||||||
qse_mmgr_t* mmgr;
|
qse_mmgr_t* mmgr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -157,7 +162,6 @@ 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_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_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);
|
void qse_xli_freeval (qse_xli_t* xli, qse_xli_val_t* val);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
Loading…
Reference in New Issue
Block a user