finished implementing the initial ini-format reader.
added qse_xli_readinistd()
This commit is contained in:
parent
7cda6152f3
commit
9532597507
@ -413,7 +413,7 @@ static int xli_main (int argc, qse_char_t* argv[])
|
||||
in.u.file.path = g_input_file;
|
||||
in.u.file.cmgr = g_infile_cmgr;
|
||||
|
||||
if (qse_xli_readstd (xli, &in) <= -1)
|
||||
if (qse_xli_readinistd (xli, &in) <= -1)
|
||||
{
|
||||
const qse_xli_loc_t* errloc;
|
||||
|
||||
|
@ -129,6 +129,11 @@ QSE_EXPORT int qse_xli_readstd (
|
||||
qse_xli_iostd_t* in
|
||||
);
|
||||
|
||||
QSE_EXPORT int qse_xli_readinistd (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_iostd_t* in
|
||||
);
|
||||
|
||||
QSE_EXPORT int qse_xli_writestd (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_iostd_t* out
|
||||
|
@ -71,7 +71,7 @@ enum qse_xli_errnum_t
|
||||
QSE_XLI_ERBRCE, /**< } expected in place of '${0}' */
|
||||
QSE_XLI_EPAVAL, /**< pair value expected in place of '${0}' */
|
||||
QSE_XLI_ESTRNC, /**< string not closed */
|
||||
QSE_XLI_ETAGNC, /**< string tag not closed */
|
||||
QSE_XLI_ETAGNC, /**< tag not closed */
|
||||
QSE_XLI_EINCLSTR ,/**< '@include' not followed by a string */
|
||||
QSE_XLI_ELXCHR, /**< invalid character '${0} */
|
||||
QSE_XLI_ETAGCHR, /**< invalid tag character '${0} */
|
||||
@ -543,9 +543,9 @@ QSE_EXPORT void qse_xli_seterrnum (
|
||||
* message for a given error number.
|
||||
*/
|
||||
QSE_EXPORT void qse_xli_seterrmsg (
|
||||
qse_xli_t* xli, /**< stream editor */
|
||||
qse_xli_errnum_t errnum, /**< error number */
|
||||
const qse_char_t* errmsg, /**< error message */
|
||||
qse_xli_t* xli, /**< stream editor */
|
||||
qse_xli_errnum_t errnum, /**< error number */
|
||||
const qse_char_t* errmsg, /**< error message */
|
||||
const qse_xli_loc_t* errloc /**< error location */
|
||||
);
|
||||
|
||||
@ -630,27 +630,27 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstrs (
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_text_t* qse_xli_inserttext (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
qse_xli_atom_t* peer,
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
qse_xli_atom_t* peer,
|
||||
const qse_char_t* str
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_file_t* qse_xli_insertfile (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
qse_xli_atom_t* peer,
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
qse_xli_atom_t* peer,
|
||||
const qse_char_t* path
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_eof_t* qse_xli_inserteof (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
qse_xli_atom_t* peer
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
qse_xli_atom_t* peer
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_pair_t* qse_xli_findpair (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_t* xli,
|
||||
const qse_xli_list_t* list,
|
||||
const qse_char_t* fqpn
|
||||
);
|
||||
@ -681,10 +681,10 @@ QSE_EXPORT qse_xli_str_t* qse_xli_addsegtostr (
|
||||
* segment is delimited by double '\0's. The string tags are not included.
|
||||
*/
|
||||
QSE_EXPORT qse_char_t* qse_xli_dupflatstr (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_str_t* str,
|
||||
qse_size_t* len,
|
||||
qse_size_t* nsegs
|
||||
qse_xli_t* xli,
|
||||
qse_xli_str_t* str,
|
||||
qse_size_t* len,
|
||||
qse_size_t* nsegs
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_list_t* qse_xli_getroot (
|
||||
|
@ -67,7 +67,7 @@ const qse_char_t* qse_xli_dflerrstr (
|
||||
QSE_T("illegal value for '${0}'"),
|
||||
QSE_T("no value for '${0}'"),
|
||||
QSE_T("uncomplying number of string segments for '${0}'"),
|
||||
QSE_T("section tag expected in place of '${0}'"),
|
||||
QSE_T("section tag expected in place of '${0}'")
|
||||
};
|
||||
|
||||
return (errnum >= 0 && errnum < QSE_COUNTOF(errstr))?
|
||||
|
@ -81,11 +81,20 @@ enum
|
||||
do { (tok)->type = (code); } while (0)
|
||||
|
||||
#define MATCH(xli,tok_type) ((xli)->tok.type == (tok_type))
|
||||
#define MATCH(xli,tok_type) ((xli)->tok.type == (tok_type))
|
||||
|
||||
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);
|
||||
if (xli->tok_status & TOK_STATUS_SAME_LINE)
|
||||
{
|
||||
while (QSE_ISSPACE(c) && c != QSE_T('\n')) GET_CHAR_TO (xli, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (QSE_ISSPACE(c)) GET_CHAR_TO (xli, c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -96,7 +105,6 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||
if (c == QSE_T(';'))
|
||||
{
|
||||
/* skip up to \n */
|
||||
/* TODO: support a different line terminator */
|
||||
qse_str_clear (tok->name);
|
||||
|
||||
do
|
||||
@ -149,14 +157,21 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||
|
||||
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_SQSTR);
|
||||
|
||||
while (1)
|
||||
do
|
||||
{
|
||||
GET_CHAR_TO (xli, c);
|
||||
if (c == QSE_CHAR_EOF || c == QSE_T(';')) break;
|
||||
if (c == QSE_T('\n'))
|
||||
{
|
||||
GET_CHAR (xli);
|
||||
break;
|
||||
}
|
||||
|
||||
ADD_TOKEN_CHAR (xli, tok, c);
|
||||
if (!QSE_ISSPACE(c)) xlen = QSE_STR_LEN(tok->name);
|
||||
|
||||
GET_CHAR_TO (xli, c);
|
||||
}
|
||||
while (1);
|
||||
|
||||
/* trim away trailing spaces */
|
||||
qse_str_setlen (tok->name, xlen);
|
||||
@ -172,7 +187,7 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||
{
|
||||
GET_CHAR_TO (xli, c);
|
||||
|
||||
if (c == QSE_CHAR_EOF)
|
||||
if (c == QSE_CHAR_EOF || c == QSE_T('\n'))
|
||||
{
|
||||
/* the string tag is not closed */
|
||||
qse_xli_seterror (xli, QSE_XLI_ETAGNC, QSE_NULL, &xli->tok.loc);
|
||||
@ -238,16 +253,24 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||
{
|
||||
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_EQ);
|
||||
ADD_TOKEN_CHAR (xli, tok, c);
|
||||
GET_CHAR (xli);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((xli->tok_status & TOK_STATUS_SAME_LINE) && c == QSE_T('\n'))
|
||||
{
|
||||
SET_TOKEN_TYPE (xli, tok, QSE_XLI_TOK_NL);
|
||||
ADD_TOKEN_STR (xli, tok, QSE_T("<NL>"), 4);
|
||||
GET_CHAR (xli);
|
||||
}
|
||||
/* not handled yet */
|
||||
if (c == QSE_T('\0'))
|
||||
else 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);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -256,8 +279,8 @@ static int get_token_into (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||
ea.ptr = &cc;
|
||||
ea.len = 1;
|
||||
qse_xli_seterror (xli, QSE_XLI_ELXCHR, &ea, &tok->loc);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -270,6 +293,9 @@ static int get_token (qse_xli_t* xli)
|
||||
|
||||
static int read_list (qse_xli_t* xli)
|
||||
{
|
||||
qse_xli_pair_t* pair;
|
||||
qse_cstr_t key;
|
||||
qse_xli_list_t* curlist;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -277,42 +303,107 @@ static int read_list (qse_xli_t* xli)
|
||||
|
||||
if (MATCH(xli, QSE_XLI_TOK_TAG))
|
||||
{
|
||||
if (get_token(xli) <= -1) return -1;
|
||||
/* insert a pair with an empty list */
|
||||
pair = qse_xli_insertpairwithemptylist (xli, &xli->root->list, QSE_NULL, QSE_STR_PTR(xli->tok.name), QSE_NULL, QSE_NULL);
|
||||
if (pair == QSE_NULL) return -1;
|
||||
curlist = (qse_xli_list_t*)pair->val;
|
||||
|
||||
if (MATCH(xli, QSE_XLI_TOK_EOF)) break;
|
||||
if (MATCH(xli, QSE_XLI_TOK_TAG)) continue;
|
||||
|
||||
if (!MATCH(xli, QSE_XLI_TOK_IDENT))
|
||||
while (1)
|
||||
{
|
||||
qse_xli_seterror (xli, QSE_XLI_EKEY, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||
return -1;
|
||||
}
|
||||
if (get_token(xli) <= -1) return -1;
|
||||
|
||||
/* key is the token... */
|
||||
xli->tok_status |= TOK_STATUS_SAME_LINE;
|
||||
if (get_token (xli) <= -1) return -1;
|
||||
if (MATCH(xli, QSE_XLI_TOK_EOF)) break;
|
||||
if (MATCH(xli, QSE_XLI_TOK_TAG))
|
||||
{
|
||||
/* switch to a new tag */
|
||||
pair = qse_xli_insertpairwithemptylist (xli, &xli->root->list, QSE_NULL, QSE_STR_PTR(xli->tok.name), QSE_NULL, QSE_NULL);
|
||||
if (pair == QSE_NULL) return -1;
|
||||
curlist = (qse_xli_list_t*)pair->val;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MATCH(xli, QSE_XLI_TOK_EQ))
|
||||
{
|
||||
qse_xli_seterror (xli, QSE_XLI_EEQ, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||
return -1;
|
||||
}
|
||||
if (!MATCH(xli, QSE_XLI_TOK_IDENT))
|
||||
{
|
||||
qse_xli_seterror (xli, QSE_XLI_EKEY, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
xli->tok_status |= TOK_STATUS_UPTO_EOL;
|
||||
if (get_token (xli) <= -1) return -1;
|
||||
if (xli->opt.trait & QSE_XLI_KEYNODUP)
|
||||
{
|
||||
qse_xli_atom_t* atom;
|
||||
|
||||
xli->tok_status &= ~(TOK_STATUS_SAME_LINE | TOK_STATUS_UPTO_EOL);
|
||||
/* find any key conflicts in the current scope */
|
||||
/* TODO: optimization. no sequential search */
|
||||
atom = curlist->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;
|
||||
}
|
||||
|
||||
if (MATCH(xli, QSE_XLI_TOK_EOF))
|
||||
{
|
||||
/* empty value */
|
||||
break;
|
||||
}
|
||||
atom = atom->prev;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||
{
|
||||
qse_xli_seterror (xli, QSE_XLI_EVAL, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||
return -1;
|
||||
key.len = QSE_STR_LEN(xli->tok.name);
|
||||
key.ptr = qse_strdup (QSE_STR_PTR(xli->tok.name), xli->mmgr);
|
||||
if (key.ptr == QSE_NULL)
|
||||
{
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
xli->tok_status |= TOK_STATUS_SAME_LINE;
|
||||
if (get_token (xli) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (xli->mmgr, key.ptr);
|
||||
return -1;
|
||||
}
|
||||
if (!MATCH(xli, QSE_XLI_TOK_EQ))
|
||||
{
|
||||
QSE_MMGR_FREE (xli->mmgr, key.ptr);
|
||||
qse_xli_seterror (xli, QSE_XLI_EEQ, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read the value */
|
||||
xli->tok_status |= TOK_STATUS_UPTO_EOL;
|
||||
if (get_token (xli) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (xli->mmgr, key.ptr);
|
||||
return -1;
|
||||
}
|
||||
xli->tok_status &= ~(TOK_STATUS_SAME_LINE | TOK_STATUS_UPTO_EOL);
|
||||
|
||||
if (MATCH(xli, QSE_XLI_TOK_EOF))
|
||||
{
|
||||
/* empty value */
|
||||
qse_cstr_t empty;
|
||||
|
||||
empty.ptr = QSE_T("");
|
||||
empty.len = 0;
|
||||
|
||||
pair = qse_xli_insertpairwithstr (xli, curlist, QSE_NULL, key.ptr, QSE_NULL, QSE_NULL, &empty, QSE_NULL);
|
||||
QSE_MMGR_FREE (xli->mmgr, key.ptr);
|
||||
if (pair == QSE_NULL) return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MATCH(xli, QSE_XLI_TOK_SQSTR))
|
||||
{
|
||||
/* add a new pair with the initial string segment */
|
||||
pair = qse_xli_insertpairwithstr (xli, curlist, QSE_NULL, key.ptr, QSE_NULL, QSE_NULL, QSE_STR_XSTR(xli->tok.name), QSE_NULL);
|
||||
QSE_MMGR_FREE (xli->mmgr, key.ptr);
|
||||
if (pair == QSE_NULL) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_xli_seterror (xli, QSE_XLI_EVAL, QSE_STR_XSTR(xli->tok.name), &xli->tok.loc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -234,7 +234,7 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok)
|
||||
if (c == QSE_T('#'))
|
||||
{
|
||||
/* skip up to \n */
|
||||
/* TODO: support a different line terminator */
|
||||
|
||||
qse_str_clear (tok->name);
|
||||
|
||||
do
|
||||
@ -635,7 +635,7 @@ retry:
|
||||
{
|
||||
GET_CHAR_TO (xli, c);
|
||||
|
||||
if (c == QSE_CHAR_EOF)
|
||||
if (c == QSE_CHAR_EOF || c == QSE_T('\n'))
|
||||
{
|
||||
/* the string tag is not closed */
|
||||
qse_xli_seterror (xli, QSE_XLI_ETAGNC, QSE_NULL, &xli->tok.loc);
|
||||
|
@ -597,12 +597,6 @@ static qse_ssize_t sf_out (
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int qse_xli_readstd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
||||
{
|
||||
xtn_t* xtn = (xtn_t*) QSE_XTN (xli);
|
||||
@ -620,6 +614,25 @@ int qse_xli_readstd (qse_xli_t* xli, qse_xli_iostd_t* in)
|
||||
return qse_xli_read (xli, sf_in);
|
||||
}
|
||||
|
||||
|
||||
int qse_xli_readinistd (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_readini (xli, sf_in);
|
||||
}
|
||||
|
||||
|
||||
int qse_xli_writestd (qse_xli_t* xli, qse_xli_iostd_t* out)
|
||||
{
|
||||
int n;
|
||||
|
@ -46,7 +46,8 @@ enum qse_xli_tok_type_t
|
||||
QSE_XLI_TOK_NSTR,
|
||||
QSE_XLI_TOK_IDENT,
|
||||
QSE_XLI_TOK_TEXT,
|
||||
QSE_XLI_TOK_TAG
|
||||
QSE_XLI_TOK_TAG,
|
||||
QSE_XLI_TOK_NL
|
||||
};
|
||||
|
||||
typedef enum qse_xli_tok_type_t qse_xli_tok_type_t;
|
||||
|
Loading…
x
Reference in New Issue
Block a user