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:
		| @ -1212,7 +1212,7 @@ static int load_server_config (qse_httpd_t* httpd, qse_httpd_server_t* server, q | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* load host/location specific configuration */ | 	/* 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 */ | 	if (host_count <= 0) return 0; /* nothing to load */ | ||||||
|  |  | ||||||
| 	QSE_ASSERT (server_xtn->cfgtab == QSE_NULL); | 	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)  | 		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) || | 			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; | 			    ((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; | 		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) | 	if (g_lookup_key) | ||||||
| 	{ | 	{ | ||||||
| 		qse_xli_pair_t* pair; | 		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); | 		pair = qse_xli_findpair (xli, QSE_NULL, g_lookup_key); | ||||||
| 		if (pair == QSE_NULL) | 		if (pair == QSE_NULL) | ||||||
| 		{ | 		{ | ||||||
|  | |||||||
| @ -148,7 +148,8 @@ struct qse_xli_str_t | |||||||
| 	qse_xli_atom_type_t type; \ | 	qse_xli_atom_type_t type; \ | ||||||
| 	qse_xli_atom_t* prev; \ | 	qse_xli_atom_t* prev; \ | ||||||
| 	qse_xli_atom_t* next; \ | 	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 | struct qse_xli_atom_t | ||||||
| { | { | ||||||
| @ -160,7 +161,7 @@ struct qse_xli_pair_t | |||||||
| 	QSE_XLI_ATOM_HDR; | 	QSE_XLI_ATOM_HDR; | ||||||
| 	const qse_char_t* key; | 	const qse_char_t* key; | ||||||
| 	const qse_char_t* alias;  | 	const qse_char_t* alias;  | ||||||
| 	qse_xli_val_t* val; | 	qse_xli_val_t*    val; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct qse_xli_text_t | struct qse_xli_text_t | ||||||
| @ -524,6 +525,16 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstr ( | |||||||
| 	const qse_cstr_t* value | 	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_EXPORT qse_xli_text_t* qse_xli_inserttext ( | ||||||
|         qse_xli_t* xli, |         qse_xli_t* xli, | ||||||
| 	qse_xli_list_t* parent, | 	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_EXPORT qse_xli_pair_t* qse_xli_findpair ( | ||||||
| 	qse_xli_t*            xli, | 	qse_xli_t*            xli, | ||||||
| 	const qse_xli_list_t* list, | 	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, | 	qse_xli_t*            xli, | ||||||
| 	const qse_xli_list_t* list, | 	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 | 	qse_xli_t* xli | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The qse_xli_definepair() function defines a pair structure. | ||||||
|  |  */ | ||||||
| QSE_EXPORT int qse_xli_definepair ( | QSE_EXPORT int qse_xli_definepair ( | ||||||
| 	qse_xli_t*           xli, | 	qse_xli_t*           xli, | ||||||
| 	const qse_char_t*    pair_name, | 	const qse_char_t*    fqpn, | ||||||
| 	const qse_xli_scm_t* scm | 	const qse_xli_scm_t* scm | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT int qse_xli_undefinepair ( | QSE_EXPORT int qse_xli_undefinepair ( | ||||||
| 	qse_xli_t*           xli, | 	qse_xli_t*           xli, | ||||||
| 	const qse_char_t*    pair_name | 	const qse_char_t*    fqpn | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT void qse_xli_undefinepairs ( | QSE_EXPORT void qse_xli_undefinepairs ( | ||||||
|  | |||||||
| @ -21,6 +21,10 @@ | |||||||
| #include "xli.h" | #include "xli.h" | ||||||
| #include <qse/cmn/chr.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* qse_xli_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) | ||||||
| { | { | ||||||
| 	qse_xli_t* xli; | 	qse_xli_t* xli; | ||||||
| @ -196,40 +200,64 @@ static void insert_atom ( | |||||||
| 		atom->next = peer; | 		atom->next = peer; | ||||||
| 		peer->prev = atom; | 		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_pair_t* qse_xli_insertpair ( | ||||||
| 	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* key, const qse_char_t* alias, qse_xli_val_t* value) | 	const qse_char_t* key, const qse_char_t* alias, qse_xli_val_t* value) | ||||||
| { | { | ||||||
| 	qse_xli_pair_t* pair; | 	qse_cstr_t k; | ||||||
| 	qse_size_t klen, nlen; |  | ||||||
| 	qse_char_t* kptr, * nptr; |  | ||||||
|  |  | ||||||
| 	klen = qse_strlen (key); | 	k.ptr = key; | ||||||
| 	nlen = alias? qse_strlen (alias): 0; | 	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) | 	if (alias) | ||||||
| 	{ | 	{ | ||||||
| 		nptr = kptr + klen + 1; | 		qse_cstr_t a; | ||||||
| 		qse_strcpy (nptr, alias); |  | ||||||
| 		pair->alias = nptr; |  | ||||||
| 	} |  | ||||||
| 	pair->val = value;  /* this assumes it points to a dynamically allocated atom  */ |  | ||||||
|  |  | ||||||
| 	insert_atom (xli, parent, peer, (qse_xli_atom_t*)pair); | 		a.ptr = alias; | ||||||
| 	return pair; | 		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 ( | qse_xli_pair_t* qse_xli_insertpairwithemptylist ( | ||||||
| @ -269,6 +297,38 @@ qse_xli_pair_t* qse_xli_insertpairwithstr ( | |||||||
| 	return tmp; | 	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_text_t* qse_xli_inserttext ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* str) | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* str) | ||||||
| { | { | ||||||
| @ -327,35 +387,32 @@ qse_xli_eof_t* qse_xli_inserteof ( | |||||||
|  |  | ||||||
| /* ------------------------------------------------------ */ | /* ------------------------------------------------------ */ | ||||||
|  |  | ||||||
| static void free_list (qse_xli_t* xli, qse_xli_list_t* list); | static void free_val (qse_xli_t* xli, qse_xli_val_t* val) | ||||||
|  | { | ||||||
|  | 	if ((qse_xli_nil_t*)val != &xli->xnil) | ||||||
|  | 	{ | ||||||
|  | 		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*)val)->next; | ||||||
|  | 			while (cur) | ||||||
|  | 			{ | ||||||
|  | 				next = cur->next; | ||||||
|  | 				QSE_MMGR_FREE (xli->mmgr, cur); | ||||||
|  | 				cur = next; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		QSE_MMGR_FREE (xli->mmgr, val); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| static void free_atom (qse_xli_t* xli, qse_xli_atom_t* atom) | static void free_atom (qse_xli_t* xli, qse_xli_atom_t* atom) | ||||||
| { | { | ||||||
| 	if (atom->type == QSE_XLI_PAIR) | 	if (atom->type == QSE_XLI_PAIR) free_val (xli, ((qse_xli_pair_t*)atom)->val); | ||||||
| 	{ |  | ||||||
| 		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) |  | ||||||
| 			{ |  | ||||||
| 				qse_xli_str_t* cur, * next;  |  | ||||||
|  |  | ||||||
| 				cur = ((qse_xli_str_t*)pair->val)->next; |  | ||||||
| 				while (cur) |  | ||||||
| 				{ |  | ||||||
| 					next = cur->next; |  | ||||||
| 					QSE_MMGR_FREE (xli->mmgr, cur); |  | ||||||
| 					cur = next; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			QSE_MMGR_FREE (xli->mmgr, pair->val); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	QSE_MMGR_FREE (xli->mmgr, atom); | 	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 ( | static qse_size_t count_pairs_by_key ( | ||||||
| 	qse_xli_t* xli, const qse_xli_list_t* list,  | 	qse_xli_t* xli, const qse_xli_list_t* list, const qse_cstr_t* key) | ||||||
| 	const qse_cstr_t* key, const qse_cstr_t* alias) |  | ||||||
| { | { | ||||||
| 	qse_xli_atom_t* p; | 	qse_xli_atom_t* p; | ||||||
| 	qse_size_t count = 0; | 	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) | 		if (p->type == QSE_XLI_PAIR) | ||||||
| 		{ | 		{ | ||||||
| 			qse_xli_pair_t* pair = (qse_xli_pair_t*)p; | 			qse_xli_pair_t* pair = (qse_xli_pair_t*)p; | ||||||
| 			if (qse_strxcmp (key->ptr, key->len, pair->key) == 0)  | 			if (qse_strxcmp (key->ptr, key->len, pair->key) == 0) count++; | ||||||
| 			{ |  | ||||||
| 				if (alias == QSE_NULL ||  |  | ||||||
| 				    qse_strxcmp (alias->ptr, alias->len, pair->alias) == 0) count++; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		p = p->next; | 		p = p->next; | ||||||
| @ -478,103 +530,145 @@ static qse_xli_pair_t* find_pair_by_key_and_index ( | |||||||
| 	return 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* 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; | ||||||
|  |  | ||||||
|  | 	seg->key.ptr = ptr = fqpn; | ||||||
|  | 	while (*ptr != QSE_T('\0') && *ptr != QSE_T('.') && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++; | ||||||
|  | 	if (ptr == seg->key.ptr) goto inval; /* no key part */ | ||||||
|  | 	seg->key.len = ptr - seg->key.ptr; | ||||||
|  |  | ||||||
|  | 	if (*ptr == QSE_T('[')) | ||||||
|  | 	{ | ||||||
|  | 		/*  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; | ||||||
|  |  | ||||||
|  | 			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') && *ptr != QSE_T('.')) goto inval; | ||||||
|  | 	} | ||||||
|  | 	else if (*ptr == QSE_T('{')) | ||||||
|  | 	{ | ||||||
|  | 		/* word index - alias */ | ||||||
|  | 		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. */ | ||||||
|  | 		seg->idxtype = FQPN_SEG_IDX_ALIAS; | ||||||
|  | 		seg->idx.alias.ptr = ptr; | ||||||
|  | 		while (*ptr != QSE_T('}') && *ptr != QSE_T('\0')) ptr++; | ||||||
|  | 		seg->idx.alias.len = ptr - seg->idx.alias.ptr; | ||||||
|  |  | ||||||
|  | 		seg->ki.ptr = seg->key.ptr; | ||||||
|  | 		seg->ki.len = seg->key.len + seg->idx.alias.len + 2; | ||||||
|  |  | ||||||
|  | 		if (*ptr != QSE_T('}') || seg->idx.alias.len == 0) goto inval; | ||||||
|  |  | ||||||
|  | 		ptr++;  /* skip } */ | ||||||
|  | 		if (*ptr != QSE_T('\0') && *ptr != QSE_T('.')) goto inval; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		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_char_t* ptr; | ||||||
| 	const qse_xli_list_t* curlist; | 	const qse_xli_list_t* curlist; | ||||||
| 	qse_xli_pair_t* pair; | 	fqpn_seg_t seg; | ||||||
| 	qse_cstr_t seg; |  | ||||||
|  |  | ||||||
| 	curlist = list? list: &xli->root; | 	curlist = list? list: &xli->root; | ||||||
|  |  | ||||||
| 	ptr = pair_name; | 	ptr = fqpn; | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		seg.ptr = ptr; | 		qse_xli_pair_t* pair; | ||||||
| 		while (*ptr != QSE_T('\0') && *ptr != QSE_T('.') && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++; |  | ||||||
| 		if (ptr == seg.ptr) goto inval; | 		ptr = get_next_fqpn_segment (xli, ptr, &seg); | ||||||
| 		seg.len = ptr - seg.ptr; | 		if (ptr == QSE_NULL) return QSE_NULL; | ||||||
|  |  | ||||||
| 		if (curlist->type != QSE_XLI_LIST)  | 		if (curlist->type != QSE_XLI_LIST)  | ||||||
| 		{ | 		{ | ||||||
| 			/* check the type of curlist. this check is needed | 			/* check the type of curlist. this check is needed | ||||||
| 			 * because of the unconditional switching at the bottom of the  | 			 * because of the unconditional switching at the bottom of the  | ||||||
| 			 * this loop. this implementation strategy has been chosen | 			 * 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; | 			goto noent; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (*ptr == QSE_T('[')) | 		switch (seg.idxtype) | ||||||
| 		{ | 		{ | ||||||
| 			/*  index is specified */ | 			case FQPN_SEG_IDX_NONE:  | ||||||
| 			ptr++; /* skip [ */ | 				pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, QSE_NULL); | ||||||
|  | 				break; | ||||||
|  |  | ||||||
| 			if (QSE_ISDIGIT(*ptr)) | 			case FQPN_SEG_IDX_NUMBER: | ||||||
| 			{ | 				pair = find_pair_by_key_and_index (xli, curlist, &seg.key, seg.idx.number); | ||||||
| 				/* numeric index */ | 				break; | ||||||
| 				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; | 			default: /*case FQPN_SEG_IDX_ALIAS:*/ | ||||||
|  | 				pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, &seg.idx.alias); | ||||||
| 				pair = find_pair_by_key_and_index (xli, curlist, &seg, index); | 				break; | ||||||
| 				if (pair == QSE_NULL)  |  | ||||||
| 				{ |  | ||||||
| 					seg.len += count + 2; /* adjustment for error message */ |  | ||||||
| 					goto noent; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			else goto inval; |  | ||||||
|  |  | ||||||
| 			ptr++;  /* skip ] */ |  | ||||||
|  |  | ||||||
| 			if (*ptr == QSE_T('\0')) break; /* no more segments */ |  | ||||||
| 			else if (*ptr != QSE_T('.')) goto inval; |  | ||||||
| 		} | 		} | ||||||
| 		else if (*ptr == QSE_T('{')) |  | ||||||
| 		{ |  | ||||||
| 			/* word index - alias */ |  | ||||||
| 			qse_cstr_t idx; |  | ||||||
|  |  | ||||||
| 			ptr++; /* skip { */ | 		if (pair == QSE_NULL) goto noent; | ||||||
|  | 		if (*ptr == QSE_T('\0')) return pair; /* no more segments */ | ||||||
| 			/* 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; |  | ||||||
| 			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; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			ptr++;  /* skip } */ |  | ||||||
|  |  | ||||||
| 			if (*ptr == QSE_T('\0')) break; /* no more segments */ |  | ||||||
| 			else if (*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 */ |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		/* more segments to handle */ | 		/* more segments to handle */ | ||||||
| 		QSE_ASSERT (*ptr == QSE_T('.')); | 		QSE_ASSERT (*ptr == QSE_T('.')); | ||||||
| 		ptr++; | 		ptr++; /* skip . */ | ||||||
|  |  | ||||||
| 		/* switch to the value regardless of its type. | 		/* switch to the value regardless of its type. | ||||||
| 		 * check if it is a list in the beginning of the loop | 		 * 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; | 		curlist = (qse_xli_list_t*)pair->val; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return pair; | 	/* this part must never be reached */ | ||||||
|  | 	qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL); | ||||||
| inval: |  | ||||||
| 	qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL); |  | ||||||
| 	return QSE_NULL; | 	return QSE_NULL; | ||||||
|  |  | ||||||
| noent: | noent: | ||||||
| 	qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg); | 	qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg.ki); | ||||||
| 	return QSE_NULL; | 	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_char_t* ptr; | ||||||
| 	const qse_xli_list_t* curlist; | 	const qse_xli_list_t* curlist; | ||||||
| 	qse_xli_pair_t* pair; | 	fqpn_seg_t seg; | ||||||
| 	qse_cstr_t seg; |  | ||||||
|  |  | ||||||
| 	curlist = list? list: &xli->root; | 	curlist = list? list: &xli->root; | ||||||
|  |  | ||||||
| 	ptr = pair_name; | 	ptr = fqpn; | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		seg.ptr = ptr; | 		qse_xli_pair_t* pair; | ||||||
| 		while (*ptr != QSE_T('\0') && *ptr != QSE_T('.') && *ptr != QSE_T('[') && *ptr != QSE_T('{')) ptr++; |  | ||||||
| 		if (ptr == seg.ptr) goto inval; | 		ptr = get_next_fqpn_segment (xli, ptr, &seg); | ||||||
| 		seg.len = ptr - seg.ptr; | 		if (ptr == QSE_NULL) return 0; | ||||||
|  |  | ||||||
| 		if (curlist->type != QSE_XLI_LIST)  | 		if (curlist->type != QSE_XLI_LIST)  | ||||||
| 		{ | 		{ | ||||||
| 			/* check the type of curlist. this check is needed | 			/* check the type of curlist. this check is needed | ||||||
| 			 * because of the unconditional switching at the bottom of the  | 			 * because of the unconditional switching at the bottom of the  | ||||||
| 			 * this loop. this implementation strategy has been chosen | 			 * 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; | 			goto noent; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (*ptr == QSE_T('[')) | 		switch (seg.idxtype) | ||||||
| 		{ | 		{ | ||||||
| 			/*  index is specified */ | 			case FQPN_SEG_IDX_NONE: | ||||||
| 			ptr++; /* skip [ */ | 				if (*ptr == QSE_T('\0'))  | ||||||
|  |  | ||||||
| 			if (QSE_ISDIGIT(*ptr)) |  | ||||||
| 			{ |  | ||||||
| 				/* numeric index */ |  | ||||||
| 				qse_size_t index = 0, count = 0; |  | ||||||
| 				do  |  | ||||||
| 				{ | 				{ | ||||||
| 					index = index * 10 + (*ptr++ - QSE_T('0'));  | 					/* last segment */ | ||||||
| 					count++; | 					return count_pairs_by_key (xli, curlist, &seg.key); | ||||||
| 				} | 				} | ||||||
| 				while (QSE_ISDIGIT(*ptr)); |  | ||||||
|  |  | ||||||
| 				if (*ptr != QSE_T(']')) goto inval; | 				pair = find_pair_by_key_and_alias (xli, curlist, &seg.key, QSE_NULL); | ||||||
|  |  | ||||||
| 				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 ] */ |  | ||||||
|  |  | ||||||
| 			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; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			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); |  | ||||||
| 			if (pair == QSE_NULL) goto noent; |  | ||||||
|  |  | ||||||
| 			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); |  | ||||||
| 				if (pair == QSE_NULL) goto noent; | 				if (pair == QSE_NULL) goto noent; | ||||||
| 			} | 				break; | ||||||
|  |  | ||||||
|  | 			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 */ | 		/* more segments to handle */ | ||||||
| 		QSE_ASSERT (*ptr == QSE_T('.')); | 		QSE_ASSERT (*ptr == QSE_T('.')); | ||||||
| 		ptr++; | 		ptr++; /* skip . */ | ||||||
|  |  | ||||||
| 		/* switch to the value regardless of its type. | 		/* switch to the value regardless of its type. | ||||||
| 		 * check if it is a list in the beginning of the loop | 		 * 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; | 		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); | 	qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL); | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| inval: |  | ||||||
| 	qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL); |  | ||||||
| 	return 0; |  | ||||||
|  |  | ||||||
| noent: | noent: | ||||||
| 	qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg); | 	qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &seg.ki); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| qse_xli_str_t* qse_xli_addsegtostr ( | qse_xli_str_t* qse_xli_addsegtostr ( | ||||||
| 	qse_xli_t* xli, qse_xli_str_t* str, const qse_cstr_t* value) | 	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');  | 	tmp[x] = QSE_T('\0');  | ||||||
|  |  | ||||||
| 	if (len) *len = x; | 	if (len) *len = x; /* the length of the flattened string */ | ||||||
| 	if (nsegs) *nsegs = y; | 	if (nsegs) *nsegs = y; /* the number of string segments used for flattening */ | ||||||
|  |  | ||||||
| 	return tmp; | 	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; | 	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); | 	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) | 	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; | 		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); | 		qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL); | ||||||
| 		return -1; | 		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; | 	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; | 		qse_cstr_t ea; | ||||||
| 		ea.ptr = pair_name; | 		ea.ptr = fqpn; | ||||||
| 		ea.len = qse_strlen (ea.ptr); | 		ea.len = qse_strlen (ea.ptr); | ||||||
| 		qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &ea); | 		qse_xli_seterrnum (xli, QSE_XLI_ENOENT, &ea); | ||||||
| 		return -1; | 		return -1; | ||||||
| @ -806,3 +844,93 @@ void qse_xli_undefinepairs (qse_xli_t* xli) | |||||||
| { | { | ||||||
| 	qse_rbt_clear (xli->schema); | 	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 | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user