added qse_xli_insertpairwithstrs().
renamed qse_xli_getnumpairs() to qse_xli_countpairs(). reworked qse_xli_findpair() and qse_xli_countpairs()
This commit is contained in:
parent
2b58fc6fe3
commit
462c891e1d
@ -1212,7 +1212,7 @@ static int load_server_config (qse_httpd_t* httpd, qse_httpd_server_t* server, q
|
||||
}
|
||||
|
||||
/* load host/location specific configuration */
|
||||
host_count = qse_xli_getnumpairs (httpd_xtn->xli, list, QSE_T("host"));
|
||||
host_count = qse_xli_countpairs (httpd_xtn->xli, list, QSE_T("host"));
|
||||
if (host_count <= 0) return 0; /* nothing to load */
|
||||
|
||||
QSE_ASSERT (server_xtn->cfgtab == QSE_NULL);
|
||||
@ -1240,7 +1240,7 @@ static int load_server_config (qse_httpd_t* httpd, qse_httpd_server_t* server, q
|
||||
|
||||
if (host->val->type == QSE_XLI_LIST && host->alias)
|
||||
{
|
||||
loc_count = qse_xli_getnumpairs (httpd_xtn->xli, (qse_xli_list_t*)host->val, QSE_T("location"));
|
||||
loc_count = qse_xli_countpairs (httpd_xtn->xli, (qse_xli_list_t*)host->val, QSE_T("location"));
|
||||
|
||||
if (((hostcfg = qse_httpd_callocmem (httpd, QSE_SIZEOF(*hostcfg))) == QSE_NULL) ||
|
||||
((hostcfg->hostname = qse_httpd_strtombsdup (httpd, (host->alias[0] == QSE_T('\0')? QSE_T("*"):host->alias))) == QSE_NULL)) goto oops;
|
||||
|
@ -484,9 +484,31 @@ for (i = 0; i < QSE_COUNTOF(defs); i++) qse_xli_definepair (xli, defs[i].name, &
|
||||
goto oops;
|
||||
}
|
||||
|
||||
{
|
||||
static qse_cstr_t strs[] =
|
||||
{
|
||||
{ QSE_T("hello"), 5 },
|
||||
{ QSE_T("xli"), 3 },
|
||||
{ QSE_T("world"), 5 }
|
||||
};
|
||||
|
||||
if (qse_xli_insertpairwithstrs (xli, qse_xli_getroot(xli), QSE_NULL, QSE_T("test-key"), QSE_NULL, strs, QSE_COUNTOF(strs)) == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR,
|
||||
QSE_T("ERROR: cannot insert a string pair - %s \n"),
|
||||
qse_xli_geterrmsg(xli)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_lookup_key)
|
||||
{
|
||||
qse_xli_pair_t* pair;
|
||||
qse_size_t count;
|
||||
|
||||
count = qse_xli_countpairs (xli, QSE_NULL, g_lookup_key);
|
||||
qse_printf (QSE_T("COUNT: %lu\n"), (unsigned long)count);
|
||||
|
||||
pair = qse_xli_findpair (xli, QSE_NULL, g_lookup_key);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
|
@ -148,7 +148,8 @@ struct qse_xli_str_t
|
||||
qse_xli_atom_type_t type; \
|
||||
qse_xli_atom_t* prev; \
|
||||
qse_xli_atom_t* next; \
|
||||
qse_xli_file_t* file
|
||||
qse_xli_file_t* file; \
|
||||
qse_xli_list_t* super
|
||||
|
||||
struct qse_xli_atom_t
|
||||
{
|
||||
@ -524,6 +525,16 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstr (
|
||||
const qse_cstr_t* value
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstrs (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* list,
|
||||
qse_xli_atom_t* peer,
|
||||
const qse_char_t* key,
|
||||
const qse_char_t* alias,
|
||||
const qse_cstr_t value[],
|
||||
qse_size_t count
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_xli_text_t* qse_xli_inserttext (
|
||||
qse_xli_t* xli,
|
||||
qse_xli_list_t* parent,
|
||||
@ -547,13 +558,13 @@ QSE_EXPORT qse_xli_eof_t* qse_xli_inserteof (
|
||||
QSE_EXPORT qse_xli_pair_t* qse_xli_findpair (
|
||||
qse_xli_t* xli,
|
||||
const qse_xli_list_t* list,
|
||||
const qse_char_t* dotted_name
|
||||
const qse_char_t* fqpn
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_size_t qse_xli_getnumpairs (
|
||||
QSE_EXPORT qse_size_t qse_xli_countpairs (
|
||||
qse_xli_t* xli,
|
||||
const qse_xli_list_t* list,
|
||||
const qse_char_t* dotted_name
|
||||
const qse_char_t* fqpn
|
||||
);
|
||||
|
||||
/**
|
||||
@ -593,15 +604,18 @@ QSE_EXPORT void qse_xli_clear (
|
||||
qse_xli_t* xli
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_xli_definepair() function defines a pair structure.
|
||||
*/
|
||||
QSE_EXPORT int qse_xli_definepair (
|
||||
qse_xli_t* xli,
|
||||
const qse_char_t* pair_name,
|
||||
const qse_char_t* fqpn,
|
||||
const qse_xli_scm_t* scm
|
||||
);
|
||||
|
||||
QSE_EXPORT int qse_xli_undefinepair (
|
||||
qse_xli_t* xli,
|
||||
const qse_char_t* pair_name
|
||||
const qse_char_t* fqpn
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_xli_undefinepairs (
|
||||
|
@ -21,6 +21,10 @@
|
||||
#include "xli.h"
|
||||
#include <qse/cmn/chr.h>
|
||||
|
||||
static void free_val (qse_xli_t* xli, qse_xli_val_t* val);
|
||||
static void free_list (qse_xli_t* xli, qse_xli_list_t* list);
|
||||
static void free_atom (qse_xli_t* xli, qse_xli_atom_t* atom);
|
||||
|
||||
qse_xli_t* qse_xli_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
{
|
||||
qse_xli_t* xli;
|
||||
@ -196,40 +200,64 @@ static void insert_atom (
|
||||
atom->next = peer;
|
||||
peer->prev = atom;
|
||||
}
|
||||
atom->super = parent;
|
||||
}
|
||||
|
||||
static qse_xli_pair_t* insert_pair (
|
||||
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer,
|
||||
const qse_cstr_t* key, const qse_cstr_t* alias, qse_xli_val_t* value)
|
||||
{
|
||||
qse_xli_pair_t* pair;
|
||||
qse_size_t alen;
|
||||
qse_char_t* kptr, * nptr;
|
||||
|
||||
alen = alias? alias->len: 0;
|
||||
|
||||
pair = qse_xli_callocmem (xli,
|
||||
QSE_SIZEOF(*pair) +
|
||||
((key->len + 1) * QSE_SIZEOF(*key->ptr)) +
|
||||
((alen + 1) * QSE_SIZEOF(*alias->ptr)));
|
||||
if (pair == QSE_NULL) return QSE_NULL;
|
||||
|
||||
kptr = (qse_char_t*)(pair + 1);
|
||||
qse_strcpy (kptr, key->ptr);
|
||||
|
||||
pair->type = QSE_XLI_PAIR;
|
||||
pair->key = kptr;
|
||||
if (alias)
|
||||
{
|
||||
nptr = kptr + key->len + 1;
|
||||
qse_strcpy (nptr, alias->ptr);
|
||||
pair->alias = nptr;
|
||||
}
|
||||
pair->val = value; /* take note of no duplication here */
|
||||
|
||||
insert_atom (xli, parent, peer, (qse_xli_atom_t*)pair);
|
||||
return pair;
|
||||
}
|
||||
|
||||
qse_xli_pair_t* qse_xli_insertpair (
|
||||
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer,
|
||||
const qse_char_t* key, const qse_char_t* alias, qse_xli_val_t* value)
|
||||
{
|
||||
qse_xli_pair_t* pair;
|
||||
qse_size_t klen, nlen;
|
||||
qse_char_t* kptr, * nptr;
|
||||
qse_cstr_t k;
|
||||
|
||||
klen = qse_strlen (key);
|
||||
nlen = alias? qse_strlen (alias): 0;
|
||||
k.ptr = key;
|
||||
k.len = qse_strlen (key);
|
||||
|
||||
pair = qse_xli_callocmem (xli,
|
||||
QSE_SIZEOF(*pair) +
|
||||
((klen + 1) * QSE_SIZEOF(*key)) +
|
||||
((nlen + 1) * QSE_SIZEOF(*alias)));
|
||||
if (pair == QSE_NULL) return QSE_NULL;
|
||||
|
||||
kptr = (qse_char_t*)(pair + 1);
|
||||
qse_strcpy (kptr, key);
|
||||
|
||||
pair->type = QSE_XLI_PAIR;
|
||||
pair->key = kptr;
|
||||
if (alias)
|
||||
{
|
||||
nptr = kptr + klen + 1;
|
||||
qse_strcpy (nptr, alias);
|
||||
pair->alias = nptr;
|
||||
}
|
||||
pair->val = value; /* this assumes it points to a dynamically allocated atom */
|
||||
qse_cstr_t a;
|
||||
|
||||
insert_atom (xli, parent, peer, (qse_xli_atom_t*)pair);
|
||||
return pair;
|
||||
a.ptr = alias;
|
||||
a.len = qse_strlen (alias);
|
||||
|
||||
return insert_pair (xli, parent, peer, &k, &a, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return insert_pair (xli, parent, peer, &k, QSE_NULL, value);
|
||||
}
|
||||
}
|
||||
|
||||
qse_xli_pair_t* qse_xli_insertpairwithemptylist (
|
||||
@ -269,6 +297,38 @@ qse_xli_pair_t* qse_xli_insertpairwithstr (
|
||||
return tmp;
|
||||
}
|
||||
|
||||
qse_xli_pair_t* qse_xli_insertpairwithstrs (
|
||||
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_cstr_t value[], qse_size_t count)
|
||||
{
|
||||
qse_xli_pair_t* tmp;
|
||||
qse_xli_str_t* str;
|
||||
qse_size_t i;
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
tmp = qse_xli_insertpairwithstr (xli, parent, peer, key, alias, &value[0]);
|
||||
if (tmp == QSE_NULL) return QSE_NULL;
|
||||
|
||||
str = (qse_xli_str_t*)tmp->val;
|
||||
for (i = 1; i < count; i++)
|
||||
{
|
||||
str = qse_xli_addsegtostr (xli, str, &value[i]);
|
||||
if (str == QSE_NULL)
|
||||
{
|
||||
free_atom (xli, (qse_xli_atom_t*)tmp);
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
qse_xli_text_t* qse_xli_inserttext (
|
||||
qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* str)
|
||||
{
|
||||
@ -327,23 +387,17 @@ qse_xli_eof_t* qse_xli_inserteof (
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
static void free_list (qse_xli_t* xli, qse_xli_list_t* list);
|
||||
|
||||
static void free_atom (qse_xli_t* xli, qse_xli_atom_t* atom)
|
||||
static void free_val (qse_xli_t* xli, qse_xli_val_t* val)
|
||||
{
|
||||
if (atom->type == QSE_XLI_PAIR)
|
||||
if ((qse_xli_nil_t*)val != &xli->xnil)
|
||||
{
|
||||
qse_xli_pair_t* pair = (qse_xli_pair_t*)atom;
|
||||
|
||||
if ((qse_xli_nil_t*)pair->val != &xli->xnil)
|
||||
{
|
||||
if (pair->val->type == QSE_XLI_LIST)
|
||||
free_list (xli, (qse_xli_list_t*)pair->val);
|
||||
else if (pair->val->type == QSE_XLI_STR)
|
||||
if (val->type == QSE_XLI_LIST)
|
||||
free_list (xli, (qse_xli_list_t*)val);
|
||||
else if (val->type == QSE_XLI_STR)
|
||||
{
|
||||
qse_xli_str_t* cur, * next;
|
||||
|
||||
cur = ((qse_xli_str_t*)pair->val)->next;
|
||||
cur = ((qse_xli_str_t*)val)->next;
|
||||
while (cur)
|
||||
{
|
||||
next = cur->next;
|
||||
@ -352,10 +406,13 @@ static void free_atom (qse_xli_t* xli, qse_xli_atom_t* atom)
|
||||
}
|
||||
}
|
||||
|
||||
QSE_MMGR_FREE (xli->mmgr, pair->val);
|
||||
}
|
||||
QSE_MMGR_FREE (xli->mmgr, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_atom (qse_xli_t* xli, qse_xli_atom_t* atom)
|
||||
{
|
||||
if (atom->type == QSE_XLI_PAIR) free_val (xli, ((qse_xli_pair_t*)atom)->val);
|
||||
QSE_MMGR_FREE (xli->mmgr, atom);
|
||||
}
|
||||
|
||||
@ -398,9 +455,8 @@ void qse_xli_clearroot (qse_xli_t* xli)
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
static qse_size_t count_pairs_by_key_and_alias (
|
||||
qse_xli_t* xli, const qse_xli_list_t* list,
|
||||
const qse_cstr_t* key, const qse_cstr_t* alias)
|
||||
static qse_size_t count_pairs_by_key (
|
||||
qse_xli_t* xli, const qse_xli_list_t* list, const qse_cstr_t* key)
|
||||
{
|
||||
qse_xli_atom_t* p;
|
||||
qse_size_t count = 0;
|
||||
@ -412,11 +468,7 @@ static qse_size_t count_pairs_by_key_and_alias (
|
||||
if (p->type == QSE_XLI_PAIR)
|
||||
{
|
||||
qse_xli_pair_t* pair = (qse_xli_pair_t*)p;
|
||||
if (qse_strxcmp (key->ptr, key->len, pair->key) == 0)
|
||||
{
|
||||
if (alias == QSE_NULL ||
|
||||
qse_strxcmp (alias->ptr, alias->len, pair->alias) == 0) count++;
|
||||
}
|
||||
if (qse_strxcmp (key->ptr, key->len, pair->key) == 0) count++;
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
@ -478,31 +530,35 @@ static qse_xli_pair_t* find_pair_by_key_and_index (
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_xli_pair_t* qse_xli_findpair (qse_xli_t* xli, const qse_xli_list_t* list, const qse_char_t* pair_name)
|
||||
|
||||
struct fqpn_seg_t
|
||||
{
|
||||
qse_cstr_t ki; /* key + index */
|
||||
qse_cstr_t key;
|
||||
enum
|
||||
{
|
||||
FQPN_SEG_IDX_NONE,
|
||||
FQPN_SEG_IDX_NUMBER,
|
||||
FQPN_SEG_IDX_ALIAS
|
||||
} idxtype;
|
||||
|
||||
union
|
||||
{
|
||||
qse_size_t number;
|
||||
qse_cstr_t alias;
|
||||
} idx;
|
||||
};
|
||||
|
||||
typedef struct fqpn_seg_t fqpn_seg_t;
|
||||
|
||||
const qse_char_t* get_next_fqpn_segment (qse_xli_t* xli, const qse_char_t* fqpn, fqpn_seg_t* seg)
|
||||
{
|
||||
const qse_char_t* ptr;
|
||||
const qse_xli_list_t* curlist;
|
||||
qse_xli_pair_t* pair;
|
||||
qse_cstr_t seg;
|
||||
|
||||
curlist = list? list: &xli->root;
|
||||
|
||||
ptr = pair_name;
|
||||
while (1)
|
||||
{
|
||||
seg.ptr = ptr;
|
||||
seg->key.ptr = ptr = fqpn;
|
||||
while (*ptr != QSE_T('\0') && *ptr != QSE_T('.') && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++;
|
||||
if (ptr == seg.ptr) goto inval;
|
||||
seg.len = ptr - seg.ptr;
|
||||
|
||||
if (curlist->type != QSE_XLI_LIST)
|
||||
{
|
||||
/* check the type of curlist. this check is needed
|
||||
* because of the unconditional switching at the bottom of the
|
||||
* this loop. this implementation strategy has been chosen
|
||||
* to provide the segment name easily. */
|
||||
goto noent;
|
||||
}
|
||||
if (ptr == seg->key.ptr) goto inval; /* no key part */
|
||||
seg->key.len = ptr - seg->key.ptr;
|
||||
|
||||
if (*ptr == QSE_T('['))
|
||||
{
|
||||
@ -522,59 +578,97 @@ qse_xli_pair_t* qse_xli_findpair (qse_xli_t* xli, const qse_xli_list_t* list, co
|
||||
|
||||
if (*ptr != QSE_T(']')) goto inval;
|
||||
|
||||
pair = find_pair_by_key_and_index (xli, curlist, &seg, index);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
seg.len += count + 2; /* adjustment for error message */
|
||||
goto noent;
|
||||
}
|
||||
seg->idxtype = FQPN_SEG_IDX_NUMBER;
|
||||
seg->idx.number = index;
|
||||
|
||||
seg->ki.ptr = seg->key.ptr;
|
||||
seg->ki.len = seg->key.len + count + 2;
|
||||
}
|
||||
else goto inval;
|
||||
|
||||
ptr++; /* skip ] */
|
||||
|
||||
if (*ptr == QSE_T('\0')) break; /* no more segments */
|
||||
else if (*ptr != QSE_T('.')) goto inval;
|
||||
if (*ptr != QSE_T('\0') && *ptr != QSE_T('.')) goto inval;
|
||||
}
|
||||
else if (*ptr == QSE_T('{'))
|
||||
{
|
||||
/* word index - alias */
|
||||
qse_cstr_t idx;
|
||||
|
||||
ptr++; /* skip { */
|
||||
|
||||
/* no escaping is supported for the alias inside {}.
|
||||
* so if your alias contains these characters (in a quoted string),
|
||||
* you can't reference it using a dotted key name. */
|
||||
idx.ptr = ptr;
|
||||
seg->idxtype = FQPN_SEG_IDX_ALIAS;
|
||||
seg->idx.alias.ptr = ptr;
|
||||
while (*ptr != QSE_T('}') && *ptr != QSE_T('\0')) ptr++;
|
||||
idx.len = ptr - idx.ptr;
|
||||
seg->idx.alias.len = ptr - seg->idx.alias.ptr;
|
||||
|
||||
if (*ptr != QSE_T('}') || idx.len == 0) goto inval;
|
||||
seg->ki.ptr = seg->key.ptr;
|
||||
seg->ki.len = seg->key.len + seg->idx.alias.len + 2;
|
||||
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg, &idx);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
seg.len += idx.len + 2; /* adjustment for error message */
|
||||
goto noent;
|
||||
}
|
||||
if (*ptr != QSE_T('}') || seg->idx.alias.len == 0) goto inval;
|
||||
|
||||
ptr++; /* skip } */
|
||||
|
||||
if (*ptr == QSE_T('\0')) break; /* no more segments */
|
||||
else if (*ptr != QSE_T('.')) goto inval;
|
||||
if (*ptr != QSE_T('\0') && *ptr != QSE_T('.')) goto inval;
|
||||
}
|
||||
else
|
||||
{
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg, QSE_NULL);
|
||||
if (pair == QSE_NULL) goto noent;
|
||||
|
||||
if (*ptr == QSE_T('\0')) break; /* no more segments */
|
||||
seg->idxtype = FQPN_SEG_IDX_NONE;
|
||||
seg->ki = seg->key;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
||||
inval:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_xli_pair_t* qse_xli_findpair (qse_xli_t* xli, const qse_xli_list_t* list, const qse_char_t* fqpn)
|
||||
{
|
||||
const qse_char_t* ptr;
|
||||
const qse_xli_list_t* curlist;
|
||||
fqpn_seg_t seg;
|
||||
|
||||
curlist = list? list: &xli->root;
|
||||
|
||||
ptr = fqpn;
|
||||
while (1)
|
||||
{
|
||||
qse_xli_pair_t* pair;
|
||||
|
||||
ptr = get_next_fqpn_segment (xli, ptr, &seg);
|
||||
if (ptr == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (curlist->type != QSE_XLI_LIST)
|
||||
{
|
||||
/* check the type of curlist. this check is needed
|
||||
* because of the unconditional switching at the bottom of the
|
||||
* this loop. this implementation strategy has been chosen
|
||||
* to provide the segment name easily when setting the error. */
|
||||
goto noent;
|
||||
}
|
||||
|
||||
switch (seg.idxtype)
|
||||
{
|
||||
case FQPN_SEG_IDX_NONE:
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, QSE_NULL);
|
||||
break;
|
||||
|
||||
case FQPN_SEG_IDX_NUMBER:
|
||||
pair = find_pair_by_key_and_index (xli, curlist, &seg.key, seg.idx.number);
|
||||
break;
|
||||
|
||||
default: /*case FQPN_SEG_IDX_ALIAS:*/
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, &seg.idx.alias);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pair == QSE_NULL) goto noent;
|
||||
if (*ptr == QSE_T('\0')) return pair; /* no more segments */
|
||||
|
||||
/* more segments to handle */
|
||||
QSE_ASSERT (*ptr == QSE_T('.'));
|
||||
ptr++;
|
||||
ptr++; /* skip . */
|
||||
|
||||
/* switch to the value regardless of its type.
|
||||
* check if it is a list in the beginning of the loop
|
||||
@ -582,131 +676,74 @@ qse_xli_pair_t* qse_xli_findpair (qse_xli_t* xli, const qse_xli_list_t* list, co
|
||||
curlist = (qse_xli_list_t*)pair->val;
|
||||
}
|
||||
|
||||
return pair;
|
||||
|
||||
inval:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
||||
/* this part must never be reached */
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
||||
return QSE_NULL;
|
||||
|
||||
noent:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg);
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg.ki);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_size_t qse_xli_getnumpairs (qse_xli_t* xli, const qse_xli_list_t* list, const qse_char_t* pair_name)
|
||||
qse_size_t qse_xli_countpairs (qse_xli_t* xli, const qse_xli_list_t* list, const qse_char_t* fqpn)
|
||||
{
|
||||
|
||||
const qse_char_t* ptr;
|
||||
const qse_xli_list_t* curlist;
|
||||
qse_xli_pair_t* pair;
|
||||
qse_cstr_t seg;
|
||||
fqpn_seg_t seg;
|
||||
|
||||
curlist = list? list: &xli->root;
|
||||
|
||||
ptr = pair_name;
|
||||
ptr = fqpn;
|
||||
while (1)
|
||||
{
|
||||
seg.ptr = ptr;
|
||||
while (*ptr != QSE_T('\0') && *ptr != QSE_T('.') && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++;
|
||||
if (ptr == seg.ptr) goto inval;
|
||||
seg.len = ptr - seg.ptr;
|
||||
qse_xli_pair_t* pair;
|
||||
|
||||
ptr = get_next_fqpn_segment (xli, ptr, &seg);
|
||||
if (ptr == QSE_NULL) return 0;
|
||||
|
||||
if (curlist->type != QSE_XLI_LIST)
|
||||
{
|
||||
/* check the type of curlist. this check is needed
|
||||
* because of the unconditional switching at the bottom of the
|
||||
* this loop. this implementation strategy has been chosen
|
||||
* to provide the segment name easily. */
|
||||
* to provide the segment name easily when setting the error. */
|
||||
goto noent;
|
||||
}
|
||||
|
||||
if (*ptr == QSE_T('['))
|
||||
switch (seg.idxtype)
|
||||
{
|
||||
/* index is specified */
|
||||
ptr++; /* skip [ */
|
||||
|
||||
if (QSE_ISDIGIT(*ptr))
|
||||
{
|
||||
/* numeric index */
|
||||
qse_size_t index = 0, count = 0;
|
||||
do
|
||||
{
|
||||
index = index * 10 + (*ptr++ - QSE_T('0'));
|
||||
count++;
|
||||
}
|
||||
while (QSE_ISDIGIT(*ptr));
|
||||
|
||||
if (*ptr != QSE_T(']')) goto inval;
|
||||
|
||||
pair = find_pair_by_key_and_index (xli, curlist, &seg, index);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
seg.len += count + 2; /* adjustment for error message */
|
||||
goto noent;
|
||||
}
|
||||
}
|
||||
else goto inval;
|
||||
|
||||
ptr++; /* skip ] */
|
||||
|
||||
case FQPN_SEG_IDX_NONE:
|
||||
if (*ptr == QSE_T('\0'))
|
||||
{
|
||||
/* no more segments */
|
||||
return 1;
|
||||
}
|
||||
else if (*ptr != QSE_T('.')) goto inval;
|
||||
}
|
||||
else if (*ptr == QSE_T('{'))
|
||||
{
|
||||
/* word index - alias */
|
||||
qse_cstr_t idx;
|
||||
|
||||
ptr++; /* skip { */
|
||||
|
||||
idx.ptr = ptr;
|
||||
while (*ptr != QSE_T('}') && *ptr != QSE_T('\0')) ptr++;
|
||||
idx.len = ptr - idx.ptr;
|
||||
|
||||
if (*ptr != QSE_T('}') || idx.len == 0) goto inval;
|
||||
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg, &idx);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
seg.len += idx.len + 2; /* adjustment for error message */
|
||||
goto noent;
|
||||
/* last segment */
|
||||
return count_pairs_by_key (xli, curlist, &seg.key);
|
||||
}
|
||||
|
||||
ptr++; /* skip } */
|
||||
|
||||
if (*ptr == QSE_T('\0'))
|
||||
{
|
||||
/* no more segments */
|
||||
return 1;
|
||||
}
|
||||
else if (*ptr != QSE_T('.')) goto inval;
|
||||
}
|
||||
else
|
||||
{
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg, QSE_NULL);
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, QSE_NULL);
|
||||
if (pair == QSE_NULL) goto noent;
|
||||
break;
|
||||
|
||||
if (*ptr == QSE_T('\0'))
|
||||
{
|
||||
return count_pairs_by_key_and_alias (xli, curlist, &seg, QSE_NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg, QSE_NULL);
|
||||
case FQPN_SEG_IDX_NUMBER:
|
||||
pair = find_pair_by_key_and_index (xli, curlist, &seg.key, seg.idx.number);
|
||||
if (pair == QSE_NULL) goto noent;
|
||||
}
|
||||
if (*ptr == QSE_T('\0')) return 1;
|
||||
break;
|
||||
|
||||
default: /*case FQPN_SEG_IDX_ALIAS:*/
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, &seg.idx.alias);
|
||||
if (pair == QSE_NULL) goto noent;
|
||||
if (*ptr == QSE_T('\0')) return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* more segments to handle */
|
||||
QSE_ASSERT (*ptr == QSE_T('.'));
|
||||
ptr++;
|
||||
ptr++; /* skip . */
|
||||
|
||||
/* switch to the value regardless of its type.
|
||||
* check if it is a list in the beginning of the loop
|
||||
* just after having gotten the next segment name */
|
||||
* just after having gotten the next segment alias */
|
||||
curlist = (qse_xli_list_t*)pair->val;
|
||||
}
|
||||
|
||||
@ -714,15 +751,12 @@ qse_size_t qse_xli_getnumpairs (qse_xli_t* xli, const qse_xli_list_t* list, cons
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
||||
return 0;
|
||||
|
||||
inval:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL);
|
||||
return 0;
|
||||
|
||||
noent:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg);
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg.ki);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
qse_xli_str_t* qse_xli_addsegtostr (
|
||||
qse_xli_t* xli, qse_xli_str_t* str, const qse_cstr_t* value)
|
||||
{
|
||||
@ -759,18 +793,22 @@ qse_char_t* qse_xli_dupflatstr (qse_xli_t* xli, qse_xli_str_t* str, qse_size_t*
|
||||
}
|
||||
tmp[x] = QSE_T('\0');
|
||||
|
||||
if (len) *len = x;
|
||||
if (nsegs) *nsegs = y;
|
||||
if (len) *len = x; /* the length of the flattened string */
|
||||
if (nsegs) *nsegs = y; /* the number of string segments used for flattening */
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
int qse_xli_definepair (qse_xli_t* xli, const qse_char_t* pair_name, const qse_xli_scm_t* scm)
|
||||
int qse_xli_definepair (qse_xli_t* xli, const qse_char_t* fqpn, const qse_xli_scm_t* scm)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
/* the fully qualified pair name for this function must not contain an index or
|
||||
* an alias. it is so because the definition contains information on key duplicability
|
||||
* and whether to allow an alias */
|
||||
|
||||
tmp = scm->flags & (QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_VALNIL);
|
||||
if (tmp != QSE_XLI_SCM_VALLIST && tmp != QSE_XLI_SCM_VALSTR && tmp != QSE_XLI_SCM_VALNIL)
|
||||
{
|
||||
@ -779,7 +817,7 @@ int qse_xli_definepair (qse_xli_t* xli, const qse_char_t* pair_name, const qse_x
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qse_rbt_upsert (xli->schema, pair_name, qse_strlen(pair_name), scm, QSE_SIZEOF(*scm)) == QSE_NULL)
|
||||
if (qse_rbt_upsert (xli->schema, fqpn, qse_strlen(fqpn), scm, QSE_SIZEOF(*scm)) == QSE_NULL)
|
||||
{
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||
return -1;
|
||||
@ -788,12 +826,12 @@ int qse_xli_definepair (qse_xli_t* xli, const qse_char_t* pair_name, const qse_x
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_xli_undefinepair (qse_xli_t* xli, const qse_char_t* pair_name)
|
||||
int qse_xli_undefinepair (qse_xli_t* xli, const qse_char_t* fqpn)
|
||||
{
|
||||
if (qse_rbt_delete (xli->schema, pair_name, qse_strlen(pair_name)) <= -1)
|
||||
if (qse_rbt_delete (xli->schema, fqpn, qse_strlen(fqpn)) <= -1)
|
||||
{
|
||||
qse_cstr_t ea;
|
||||
ea.ptr = pair_name;
|
||||
ea.ptr = fqpn;
|
||||
ea.len = qse_strlen (ea.ptr);
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &ea);
|
||||
return -1;
|
||||
@ -806,3 +844,93 @@ void qse_xli_undefinepairs (qse_xli_t* xli)
|
||||
{
|
||||
qse_rbt_clear (xli->schema);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
qse_xli_pair_t* qse_xli_getpair (qse_xli_t* xli, const qse_char_t* fqpn)
|
||||
{
|
||||
return qse_xli_findpair (xli, &xli->root, fqpn);
|
||||
}
|
||||
|
||||
qse_xli_pair_t* qse_xli_setpair (qse_xli_t* xli, const qse_char_t* fqpn, const qse_xli_val_t* val) -> str, val, nil
|
||||
{
|
||||
const qse_char_t* ptr;
|
||||
const qse_xli_list_t* curlist;
|
||||
fqpn_seg_t seg;
|
||||
|
||||
curlist = list? list: &xli->root;
|
||||
|
||||
ptr = fqpn;
|
||||
while (1)
|
||||
{
|
||||
qse_xli_pair_t* pair;
|
||||
|
||||
ptr = get_next_fqpn_segment (xli, ptr, &seg);
|
||||
if (ptr == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (curlist->type != QSE_XLI_LIST)
|
||||
{
|
||||
/* for example, the second segment y in a FQPN "x.y.z" may be found.
|
||||
* however the value for it is not a list. i can't force insert a new
|
||||
* pair 'z' under a non-list atom */
|
||||
goto noent;
|
||||
}
|
||||
|
||||
switch (seg.idxtype)
|
||||
{
|
||||
case FQPN_SEG_IDX_NONE:
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, QSE_NULL);
|
||||
break;
|
||||
|
||||
case FQPN_SEG_IDX_NUMBER:
|
||||
pair = find_pair_by_key_and_index (xli, curlist, &seg.key, seg.idx.number);
|
||||
break;
|
||||
|
||||
case FQPN_SEG_IDX_ALIAS:
|
||||
pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, &seg.idx.alias);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
/* insert a new item..... */
|
||||
if (*ptr == QSE_T('\0'))
|
||||
{
|
||||
/* append according to the value */
|
||||
pair = insert_pair (xli, curlist, QSE_NULL, &seg.key, ((seg.idxtype == FQPN_SEG_IDX_ALIAS)? &seg.idx.alias: QSE_NULL), val);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is not the last segment. insert an empty list */
|
||||
/* seg.key, seg.alias */
|
||||
pair = insert_pair_with_empty_list (xli, curlist, QSE_NULL, key, alias);
|
||||
}
|
||||
|
||||
if (pair == QSE_NULL) return QSE_NULL;
|
||||
}
|
||||
|
||||
if (*ptr == QSE_T('\0'))
|
||||
{
|
||||
/* no more segment. and the final match is found.
|
||||
* update the pair with a new value */
|
||||
}
|
||||
|
||||
/* more segments to handle */
|
||||
QSE_ASSERT (*ptr == QSE_T('.'));
|
||||
ptr++; /* skip . */
|
||||
|
||||
/* switch to the value regardless of its type.
|
||||
* check if it is a list in the beginning of the loop
|
||||
* just after having gotten the next segment alias */
|
||||
curlist = (qse_xli_list_t*)pair->val;
|
||||
}
|
||||
|
||||
/* this part must never be reached */
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
||||
return QSE_NULL;
|
||||
|
||||
noent:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg.ki);
|
||||
return QSE_NULL;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user