added a working json format writer
This commit is contained in:
		| @ -169,7 +169,6 @@ typedef struct qse_xli_list_t   qse_xli_list_t; | |||||||
| typedef struct qse_xli_atom_t   qse_xli_atom_t; | typedef struct qse_xli_atom_t   qse_xli_atom_t; | ||||||
| typedef struct qse_xli_pair_t   qse_xli_pair_t; | typedef struct qse_xli_pair_t   qse_xli_pair_t; | ||||||
| typedef struct qse_xli_text_t   qse_xli_text_t; | typedef struct qse_xli_text_t   qse_xli_text_t; | ||||||
| typedef struct qse_xli_vtext_t  qse_xli_vtext_t; |  | ||||||
| typedef struct qse_xli_file_t   qse_xli_file_t; | typedef struct qse_xli_file_t   qse_xli_file_t; | ||||||
| typedef struct qse_xli_eof_t    qse_xli_eof_t; | typedef struct qse_xli_eof_t    qse_xli_eof_t; | ||||||
|  |  | ||||||
| @ -197,16 +196,23 @@ enum qse_xli_list_flag_t | |||||||
| }; | }; | ||||||
| typedef enum qse_xli_list_flag_t qse_xli_list_flag_t; | typedef enum qse_xli_list_flag_t qse_xli_list_flag_t; | ||||||
|  |  | ||||||
|  | enum qse_xli_text_flag_t | ||||||
|  | { | ||||||
|  | 	QSE_XLI_TEXT_VERBATIM = (1 << 0), | ||||||
|  | 	QSE_XLI_TEXT_DEINDENT = (1 << 1) | ||||||
|  | }; | ||||||
|  | typedef enum qse_xli_text_flag_t qse_xli_text_flag_t; | ||||||
|  |  | ||||||
| enum qse_xli_atom_type_t | enum qse_xli_atom_type_t | ||||||
| { | { | ||||||
| 	QSE_XLI_PAIR, | 	QSE_XLI_PAIR, | ||||||
| 	QSE_XLI_TEXT, | 	QSE_XLI_TEXT, | ||||||
| 	QSE_XLI_VTEXT, /* verbatim text */ |  | ||||||
| 	QSE_XLI_FILE, | 	QSE_XLI_FILE, | ||||||
| 	QSE_XLI_EOF | 	QSE_XLI_EOF | ||||||
| }; | }; | ||||||
| typedef enum qse_xli_atom_type_t qse_xli_atom_type_t; | typedef enum qse_xli_atom_type_t qse_xli_atom_type_t; | ||||||
|  |  | ||||||
|  |  | ||||||
| #define QSE_XLI_VAL_HDR \ | #define QSE_XLI_VAL_HDR \ | ||||||
| 	qse_xli_val_type_t type | 	qse_xli_val_type_t type | ||||||
|  |  | ||||||
| @ -272,12 +278,7 @@ struct qse_xli_pair_t | |||||||
| struct qse_xli_text_t | struct qse_xli_text_t | ||||||
| { | { | ||||||
| 	QSE_XLI_ATOM_HDR; | 	QSE_XLI_ATOM_HDR; | ||||||
| 	const qse_char_t* ptr; | 	int flags; | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct qse_xli_vtext_t |  | ||||||
| { |  | ||||||
| 	QSE_XLI_ATOM_HDR; |  | ||||||
| 	const qse_char_t* ptr; | 	const qse_char_t* ptr; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -688,13 +689,6 @@ QSE_EXPORT qse_xli_text_t* qse_xli_inserttext ( | |||||||
| 	const qse_char_t* str | 	const qse_char_t* str | ||||||
| ); | ); | ||||||
|  |  | ||||||
| QSE_EXPORT qse_xli_vtext_t* qse_xli_insertvtext ( |  | ||||||
| 	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_EXPORT qse_xli_file_t* qse_xli_insertfile ( | ||||||
| 	qse_xli_t*        xli, | 	qse_xli_t*        xli, | ||||||
| 	qse_xli_list_t*   parent, | 	qse_xli_list_t*   parent, | ||||||
|  | |||||||
| @ -28,16 +28,27 @@ | |||||||
| #include <qse/cmn/chr.h> | #include <qse/cmn/chr.h> | ||||||
|  |  | ||||||
| /* | /* | ||||||
| 	"key1" { | { | ||||||
|  | 	"key1": { | ||||||
| 		# comment | 		# comment | ||||||
| 		[keytag]key11 "alias" = [strtag]"test machine; | 		"key11": = "test machine, | ||||||
| 		key1122 { | 		"key1122": [ | ||||||
| 			key112233 = "hello"; | 			1, | ||||||
| 		} |  			2, | ||||||
|  |  			{  | ||||||
|  | 				"a": 10, | ||||||
|  |  				"b": 20, | ||||||
|  			} |  			} | ||||||
|  | 		] | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
| */ | */ | ||||||
|  |  | ||||||
|  | enum | ||||||
|  | { | ||||||
|  | 	TOK_STATUS_DEINDENT_TEXT = (1 << 0) | ||||||
|  | }; | ||||||
|  |  | ||||||
| static int get_token (qse_xli_t* xli); | static int get_token (qse_xli_t* xli); | ||||||
| static int read_list (qse_xli_t* xli, qse_xli_list_t* lv); | static int read_list (qse_xli_t* xli, qse_xli_list_t* lv); | ||||||
| static int read_array (qse_xli_t* xli, qse_xli_list_t* lv); | static int read_array (qse_xli_t* xli, qse_xli_list_t* lv); | ||||||
| @ -123,8 +134,14 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok) | |||||||
| 		} | 		} | ||||||
| 		while (1); | 		while (1); | ||||||
|  |  | ||||||
| 		if ((xli->opt.trait & QSE_XLI_KEEPTEXT) &&  | 		if (xli->opt.trait & QSE_XLI_KEEPTEXT) | ||||||
| 		    qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(tok->name)) == QSE_NULL) return -1; | 		{ | ||||||
|  | 			qse_xli_text_t* ta; | ||||||
|  | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(tok->name)); | ||||||
|  | 			if (!ta) return -1; | ||||||
|  |  | ||||||
|  | 			if (xli->tok_status & TOK_STATUS_DEINDENT_TEXT) ta->flags |= QSE_XLI_TEXT_DEINDENT; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		GET_CHAR (xli); /* eat the new line letter */ | 		GET_CHAR (xli); /* eat the new line letter */ | ||||||
| 		return 1; /* comment by # */ | 		return 1; /* comment by # */ | ||||||
| @ -803,11 +820,12 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 	link = qse_xli_makelistlink (xli, &xli->root->list); | 	link = qse_xli_makelistlink (xli, &xli->root->list); | ||||||
| 	if (!link) goto oops; | 	if (!link) goto oops; | ||||||
|  |  | ||||||
|  | 	xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | ||||||
| 	if (qse_xli_getchar(xli) <= -1 || get_token(xli) <= -1) goto oops; | 	if (qse_xli_getchar(xli) <= -1 || get_token(xli) <= -1) goto oops; | ||||||
|  |  | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		if (MATCH(xli, QSE_XLI_TOK_XINCLUDE)) | 		/*if (MATCH(xli, QSE_XLI_TOK_XINCLUDE)) | ||||||
| 		{ | 		{ | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
|  |  | ||||||
| @ -823,14 +841,24 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 		{ | 		{ | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 		} | 		} | ||||||
| 		else if (MATCH(xli, QSE_XLI_TOK_LBRACK)) | 		else*/if (MATCH(xli, QSE_XLI_TOK_LBRACK)) | ||||||
| 		{ | 		{ | ||||||
|  | 			qse_xli_text_t* ta; | ||||||
| 			xli->root->list.flags |= QSE_XLI_LIST_ARRAYED;  | 			xli->root->list.flags |= QSE_XLI_LIST_ARRAYED;  | ||||||
|  | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
|  | 			if (!ta) goto oops; | ||||||
|  | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | ||||||
|  | 			xli->tok_status &= ~TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		else if (MATCH(xli, QSE_XLI_TOK_LBRACE)) | 		else if (MATCH(xli, QSE_XLI_TOK_LBRACE)) | ||||||
| 		{ | 		{ | ||||||
|  | 			qse_xli_text_t* ta; | ||||||
|  | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
|  | 			if (!ta) goto oops; | ||||||
|  | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | ||||||
|  | 			xli->tok_status &= ~TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -845,7 +873,7 @@ static int read_root_list (qse_xli_t* xli) | |||||||
|  |  | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		if (MATCH(xli, QSE_XLI_TOK_XINCLUDE)) | 		/*if (MATCH(xli, QSE_XLI_TOK_XINCLUDE)) | ||||||
| 		{ | 		{ | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
|  |  | ||||||
| @ -861,15 +889,25 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 		{ | 		{ | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 		} | 		} | ||||||
| 		else if (MATCH(xli, QSE_XLI_TOK_RBRACK)) | 		else*/if (MATCH(xli, QSE_XLI_TOK_RBRACK)) | ||||||
| 		{ | 		{ | ||||||
|  | 			qse_xli_text_t* ta; | ||||||
| 			if (!(xli->root->list.flags & QSE_XLI_LIST_ARRAYED)) goto oops_rbrac; | 			if (!(xli->root->list.flags & QSE_XLI_LIST_ARRAYED)) goto oops_rbrac; | ||||||
|  | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
|  | 			if (!ta) goto oops; | ||||||
|  | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | ||||||
|  | 			xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		else if (MATCH(xli, QSE_XLI_TOK_RBRACE)) | 		else if (MATCH(xli, QSE_XLI_TOK_RBRACE)) | ||||||
| 		{ | 		{ | ||||||
|  | 			qse_xli_text_t* ta; | ||||||
| 			if (xli->root->list.flags & QSE_XLI_LIST_ARRAYED) goto oops_rbrac; | 			if (xli->root->list.flags & QSE_XLI_LIST_ARRAYED) goto oops_rbrac; | ||||||
|  | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
|  | 			if (!ta) goto oops; | ||||||
|  | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | ||||||
|  | 			xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -884,7 +922,6 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	QSE_ASSERT (link == xli->parlink); | 	QSE_ASSERT (link == xli->parlink); | ||||||
| 	qse_xli_freelistlink (xli, link); | 	qse_xli_freelistlink (xli, link); | ||||||
|  |  | ||||||
|  | |||||||
| @ -146,19 +146,13 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
| 			{ | 			{ | ||||||
| 				const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr; | 				const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr; | ||||||
|  |  | ||||||
|  | 				/* don't honor VERBATIM and DEINDENT flags */ | ||||||
| 				if (write_to_current_stream(xli, QSE_T(";"), 1) <= -1 || | 				if (write_to_current_stream(xli, QSE_T(";"), 1) <= -1 || | ||||||
| 				    write_to_current_stream(xli, str, qse_strlen(str)) <= -1 || | 				    write_to_current_stream(xli, str, qse_strlen(str)) <= -1 || | ||||||
| 				    write_to_current_stream(xli, QSE_T("\n"), 1) <= -1) return -1; | 				    write_to_current_stream(xli, QSE_T("\n"), 1) <= -1) return -1; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			case QSE_XLI_VTEXT: |  | ||||||
| 			{ |  | ||||||
| 				/* no vtext element can be included in the ini format */ |  | ||||||
| 				/* do nothing */ |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			case QSE_XLI_FILE: | 			case QSE_XLI_FILE: | ||||||
| 				/* no file inclusion is supported by the ini-format. ignore it */ | 				/* no file inclusion is supported by the ini-format. ignore it */ | ||||||
| 				break; | 				break; | ||||||
|  | |||||||
| @ -33,8 +33,6 @@ struct arg_data_t | |||||||
| 	int org_depth; | 	int org_depth; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| static int write_to_current_stream(qse_xli_t* xli, const qse_char_t* ptr, qse_size_t len, int escape) | static int write_to_current_stream(qse_xli_t* xli, const qse_char_t* ptr, qse_size_t len, int escape) | ||||||
| { | { | ||||||
| 	qse_xli_io_arg_t* arg; | 	qse_xli_io_arg_t* arg; | ||||||
| @ -85,111 +83,20 @@ static int write_indentation (qse_xli_t* xli, int depth) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int need_comma (qse_xli_atom_t* start) | ||||||
| static int key_needs_quoting (qse_xli_t* xli, const qse_char_t* str, int nstr) |  | ||||||
| { | { | ||||||
| 	/* this determines if a key or an alias requires quoting for output. | 	qse_xli_atom_t* cur; | ||||||
| 	 * NSTR is not taken into account because it's only allowed as a value */ | 	for (cur = start; cur; cur = cur->next) | ||||||
|  |  | ||||||
| 	/* refer to the tokenization rule in get_token_into() in read.c */ |  | ||||||
| 	qse_char_t c; |  | ||||||
|  |  | ||||||
| 	c = *str++; |  | ||||||
| 	if (c == QSE_T('\0')) return 1; /* an empty string requires a quoting */ |  | ||||||
|  |  | ||||||
| 	if (c == QSE_T('_') || QSE_ISALPHA(c) || (!nstr && (xli->opt.trait & QSE_XLI_LEADDIGIT) && QSE_ISDIGIT(c))) |  | ||||||
| 	{ | 	{ | ||||||
| 		int lead_digit = QSE_ISDIGIT(c); | 		if (cur->type == QSE_XLI_PAIR) return 1; | ||||||
| 		int all_digits = 1; | 		if (cur->type == QSE_XLI_EOF) return 0; /* if EOF encountered in the included file, i don't want a comma at the end of the file */ | ||||||
|  |  | ||||||
| 		/* a normal identifier can be composed of wider varieties of  |  | ||||||
| 		 * characters than a keyword/directive */ |  | ||||||
| 		while (1) |  | ||||||
| 		{ |  | ||||||
| 			c = *str++; |  | ||||||
| 			if (c == QSE_T('\0')) break; |  | ||||||
|  |  | ||||||
| 			if (c == QSE_T('_') || c == QSE_T('-') ||  |  | ||||||
| 			    (!(xli->opt.trait & QSE_XLI_JSON) && c == QSE_T(':')) || |  | ||||||
| 			    c == QSE_T('*') || c == QSE_T('/') || QSE_ISALPHA(c))  |  | ||||||
| 			{ |  | ||||||
| 				all_digits = 0; |  | ||||||
| 	} | 	} | ||||||
| 			else if (QSE_ISDIGIT(c))  | 	return 0; | ||||||
| 			{ |  | ||||||
| 				/* nothing to do */ |  | ||||||
| 			} |  | ||||||
| 			else  |  | ||||||
| 			{ |  | ||||||
| 				/* a disallowed character for an identifier */ |  | ||||||
| 				return 1; /* quote it */ |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (lead_digit && all_digits) |  | ||||||
| 		{ |  | ||||||
| 			/* if an identifier begins with a digit, it must contain a non-digit character */ |  | ||||||
| 			/* in fact, it is not a valid identifer. so quote it */ |  | ||||||
| 			return 1; |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			/* this must be a normal identifer */ |  | ||||||
| 			return 0; /* no quoting needed */ |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	else if (nstr && QSE_ISDIGIT(c)) |  | ||||||
| 	{ |  | ||||||
| 		do  |  | ||||||
| 		{ |  | ||||||
| 			c = *str++; |  | ||||||
| 			if (c == QSE_T('\0')) return 0; /* it's a numeric string */ |  | ||||||
| 		} |  | ||||||
| 		while (QSE_ISDIGIT(c)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* quote all the rest */ |  | ||||||
| 	return 1; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | ||||||
| { | { | ||||||
| 	static struct |  | ||||||
| 	{ |  | ||||||
| 		qse_char_t* qptr; |  | ||||||
| 		qse_size_t  qlen; |  | ||||||
| 	} quotes[] = |  | ||||||
| 	{ |  | ||||||
| 		{ QSE_T(""),   0 }, |  | ||||||
| 		{ QSE_T("\'"), 1 }, |  | ||||||
| 		{ QSE_T("\""), 1 } |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	static qse_char_t tag_opener[] = { QSE_T('['), QSE_T('(') }; |  | ||||||
| 	static qse_char_t tag_closer[] = { QSE_T(']'), QSE_T(')') }; |  | ||||||
|  |  | ||||||
| 	static struct |  | ||||||
| 	{ |  | ||||||
| 		qse_char_t* ptr; |  | ||||||
| 		qse_size_t  len; |  | ||||||
| 	} assign_symbol[] = |  | ||||||
| 	{ |  | ||||||
| 		{ QSE_T(" = "), 3 }, |  | ||||||
| 		{ QSE_T(": "),  2 } |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	static struct |  | ||||||
| 	{ |  | ||||||
| 		qse_char_t* ptr; |  | ||||||
| 		qse_size_t  len; |  | ||||||
| 	} list_assign_symbol[] = |  | ||||||
| 	{ |  | ||||||
| 		{ QSE_T(" "), 1 }, |  | ||||||
| 		{ QSE_T(": "),  2 } |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	qse_xli_atom_t* curatom; | 	qse_xli_atom_t* curatom; | ||||||
| 	int tag_mode = (xli->opt.trait & QSE_XLI_JSON)? 1: 0; |  | ||||||
|  |  | ||||||
| 	for (curatom = list->head; curatom; curatom = curatom->next) | 	for (curatom = list->head; curatom; curatom = curatom->next) | ||||||
| 	{ | 	{ | ||||||
| @ -197,104 +104,98 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
| 		{ | 		{ | ||||||
| 			case QSE_XLI_PAIR: | 			case QSE_XLI_PAIR: | ||||||
| 			{ | 			{ | ||||||
| 				int qtype; |  | ||||||
| 				qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom; | 				qse_xli_pair_t* pair = (qse_xli_pair_t*)curatom; | ||||||
|  |  | ||||||
| 				if (write_indentation(xli, depth) <= -1) return -1; | 				if (write_indentation(xli, depth) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 				if (!(list->flags & QSE_XLI_LIST_ARRAYED)) | ||||||
|  | 				{ | ||||||
| 					if (pair->tag) | 					if (pair->tag) | ||||||
| 					{ | 					{ | ||||||
| 					if (write_to_current_stream(xli, &tag_opener[tag_mode], 1, 0) <= -1 || | 						/* ignore tag in the json format */ | ||||||
| 					    write_to_current_stream(xli, pair->tag, qse_strlen(pair->tag), 0) <= -1 ||  |  | ||||||
| 					    write_to_current_stream(xli, &tag_closer[tag_mode], 1, 0) <= -1) return -1; |  | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 				QSE_ASSERT(pair->_key_quoted >= 0 && pair->_key_quoted < QSE_COUNTOF(quotes)); | 					if (write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1 || | ||||||
| 				qtype = pair->_key_quoted; | 					    write_to_current_stream(xli, pair->key, qse_strlen(pair->key), 1) <= -1 || | ||||||
| 				if (qtype <= 0 && key_needs_quoting(xli, pair->key, 0)) qtype = 2; /* force double quoting */ | 					    write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1; | ||||||
|  |  | ||||||
| 				if (write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1 || |  | ||||||
| 				    write_to_current_stream(xli, pair->key, qse_strlen(pair->key), (qtype >= 2)) <= -1 || |  | ||||||
| 				    write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1) return -1; |  | ||||||
|  |  | ||||||
| 					if (pair->alias)  | 					if (pair->alias)  | ||||||
| 					{ | 					{ | ||||||
| 					QSE_ASSERT(pair->_alias_quoted >= 0 && pair->_alias_quoted < QSE_COUNTOF(quotes)); | 						/* ignore alias in the json format */ | ||||||
| 					qtype = pair->_alias_quoted; | 					} | ||||||
| 					if (qtype <= 0 && key_needs_quoting(xli, pair->alias, 1)) qtype = 2; |  | ||||||
|  |  | ||||||
| 					if (write_to_current_stream(xli, QSE_T(" "), 1, 0) <= -1 || | 					if (write_to_current_stream(xli, QSE_T(": "), 2, 0) <= -1) return -1; | ||||||
| 					    write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1 || |  | ||||||
| 					    write_to_current_stream(xli, pair->alias, qse_strlen(pair->alias), (qtype >= 2)) <= -1 || |  | ||||||
| 					    write_to_current_stream(xli, quotes[qtype].qptr, quotes[qtype].qlen, 0) <= -1) return -1; |  | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				switch (pair->val->type) | 				switch (pair->val->type) | ||||||
| 				{ | 				{ | ||||||
| 					case QSE_XLI_NIL: | 					case QSE_XLI_NIL: | ||||||
| 						if (write_to_current_stream(xli, QSE_T("nil;\n"), 5, 0) <= -1) return -1; | 						if (write_to_current_stream(xli, QSE_T("nil"), 5, 0) <= -1) return -1; | ||||||
| 						break; | 						break; | ||||||
|  |  | ||||||
| 					case QSE_XLI_TRUE: | 					case QSE_XLI_TRUE: | ||||||
| 						if (write_to_current_stream(xli, QSE_T("true;\n"), 6, 0) <= -1) return -1; | 						if (write_to_current_stream(xli, QSE_T("true"), 6, 0) <= -1) return -1; | ||||||
| 						break; | 						break; | ||||||
|  |  | ||||||
| 					case QSE_XLI_FALSE: | 					case QSE_XLI_FALSE: | ||||||
| 						if (write_to_current_stream(xli, QSE_T("false;\n"), 7, 0) <= -1) return -1; | 						if (write_to_current_stream(xli, QSE_T("false"), 7, 0) <= -1) return -1; | ||||||
| 						break; | 						break; | ||||||
|  |  | ||||||
| 					case QSE_XLI_STR: | 					case QSE_XLI_STR: | ||||||
| 					{ | 					{ | ||||||
| 						qse_xli_str_t* str = (qse_xli_str_t*)pair->val; | 						qse_xli_str_t* str = (qse_xli_str_t*)pair->val; | ||||||
|  |  | ||||||
| 						if (write_to_current_stream(xli, assign_symbol[tag_mode].ptr, assign_symbol[tag_mode].len, 0) <= -1) return -1; | 						/* ignore the string tag(str->tag) in the json format. | ||||||
|  | 						 * concatenate multi-segmented string into 1 */ | ||||||
|  | 						if (write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1; | ||||||
| 						while (1) | 						while (1) | ||||||
| 						{ | 						{ | ||||||
| 							if (str->tag) | 							if (write_to_current_stream(xli, str->ptr, str->len, 1) <= -1) return -1; | ||||||
| 							{ |  | ||||||
| 								if (write_to_current_stream(xli, &tag_opener[tag_mode], 1, 0) <= -1 || |  | ||||||
| 								    write_to_current_stream(xli, str->tag, qse_strlen(str->tag), 0) <= -1 ||  |  | ||||||
| 								    write_to_current_stream(xli, &tag_closer[tag_mode], 1, 0) <= -1) return -1; |  | ||||||
| 							} |  | ||||||
|  |  | ||||||
| 							if (write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1 || |  | ||||||
| 							    write_to_current_stream(xli, str->ptr, str->len, 1) <= -1 || |  | ||||||
| 							    write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1; |  | ||||||
| 							if (!str->next) break; | 							if (!str->next) break; | ||||||
|  |  | ||||||
| 							if (write_to_current_stream(xli, QSE_T(", "), 2, 0) <= -1) return -1; |  | ||||||
| 							str = str->next; | 							str = str->next; | ||||||
| 						} | 						} | ||||||
| 						if (write_to_current_stream(xli, QSE_T(";\n"), 2, 0) <= -1) return -1; |  | ||||||
|  | 						if (write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					case QSE_XLI_LIST: | 					case QSE_XLI_LIST: | ||||||
| 					{ | 					{ | ||||||
| 						if (write_to_current_stream(xli, list_assign_symbol[tag_mode].ptr, list_assign_symbol[tag_mode].len, 0) <= -1) return -1; | 						static qse_char_t* obrac[] = | ||||||
|  | 						{ | ||||||
| 						if (write_to_current_stream(xli, QSE_T("{\n"), 2, 0) <= -1 || | 							QSE_T("{\n"), | ||||||
|  | 							QSE_T("[\n") | ||||||
|  | 						}; | ||||||
|  | 						static qse_char_t* cbrac[] = | ||||||
|  | 						{ | ||||||
|  | 							QSE_T("}"), | ||||||
|  | 							QSE_T("]") | ||||||
|  | 						}; | ||||||
|  | 						qse_xli_list_t* lv = (qse_xli_list_t*)pair->val; | ||||||
|  | 						if (write_to_current_stream(xli, obrac[lv->flags & QSE_XLI_LIST_ARRAYED], 2, 0) <= -1 || | ||||||
| 						    write_list (xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1 || | 						    write_list (xli, (qse_xli_list_t*)pair->val, depth + 1) <= -1 || | ||||||
| 						    write_indentation (xli, depth) <= -1 || | 						    write_indentation (xli, depth) <= -1 || | ||||||
| 						    write_to_current_stream(xli, QSE_T("}\n"), 2, 0) <= -1) return -1; | 						    write_to_current_stream(xli, cbrac[lv->flags & QSE_XLI_LIST_ARRAYED], 1, 0) <= -1) return -1; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				if (need_comma(curatom->next) && write_to_current_stream(xli, QSE_T(","), 1, 0) <= -1) return -1; | ||||||
|  | 				if (write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			case QSE_XLI_TEXT: | 			case QSE_XLI_TEXT: | ||||||
| 			{ | 			{ | ||||||
| 				int i; | 				qse_xli_text_t* ta; | ||||||
| 				const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr; | 				const qse_char_t* str; | ||||||
|  |  | ||||||
| 				for (i = 0; i < depth; i++)  | 				ta = (qse_xli_text_t*)curatom; | ||||||
| 				{ | 				str = ta->ptr; | ||||||
| 					if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if (write_to_current_stream(xli, QSE_T("#"), 1, 0) <= -1 || | 				if (write_indentation(xli, depth - !!(ta->flags & QSE_XLI_TEXT_DEINDENT)) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 				if ((!(ta->flags & QSE_XLI_TEXT_VERBATIM) && write_to_current_stream(xli, QSE_T("#"), 1, 0) <= -1) || | ||||||
| 				    write_to_current_stream(xli, str, qse_strlen(str), 0) <= -1 || | 				    write_to_current_stream(xli, str, qse_strlen(str), 0) <= -1 || | ||||||
| 				    write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1; | 				    write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1; | ||||||
| 				break; | 				break; | ||||||
| @ -302,17 +203,13 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
|  |  | ||||||
| 			case QSE_XLI_FILE: | 			case QSE_XLI_FILE: | ||||||
| 			{ | 			{ | ||||||
| 				int i; |  | ||||||
| 				const qse_char_t* path = ((qse_xli_file_t*)curatom)->path; | 				const qse_char_t* path = ((qse_xli_file_t*)curatom)->path; | ||||||
|  |  | ||||||
| 				for (i = 0; i < depth; i++)  | 				if (write_indentation(xli, depth) <= -1) return -1; | ||||||
| 				{ |  | ||||||
| 					if (write_to_current_stream(xli, QSE_T("\t"), 1, 0) <= -1) return -1; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if (write_to_current_stream(xli, QSE_T("@include \""), 10, 0) <= -1 || | 				if (write_to_current_stream(xli, QSE_T("@include \""), 10, 0) <= -1 || | ||||||
| 				    write_to_current_stream(xli, path, qse_strlen(path), 1) <= -1 || | 				    write_to_current_stream(xli, path, qse_strlen(path), 1) <= -1 || | ||||||
| 				    write_to_current_stream(xli, QSE_T("\";\n"), 3, 0) <= -1) return -1; | 				    write_to_current_stream(xli, QSE_T("\""), 1, 0) <= -1) return -1; | ||||||
|  |  | ||||||
| 				if (qse_xli_openwstream (xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1; | 				if (qse_xli_openwstream (xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1; | ||||||
| 				depth = 0; | 				depth = 0; | ||||||
| @ -320,21 +217,21 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			case QSE_XLI_EOF: | 			case QSE_XLI_EOF: | ||||||
| 				if (qse_xli_closeactivewstream (xli, &depth) <= -1) return -1; | 				if (qse_xli_closeactivewstream(xli, &depth) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 				if (need_comma(curatom->next) && write_to_current_stream(xli, QSE_T(","), 1, 0) <= -1) return -1; | ||||||
|  | 				if (write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1; | ||||||
| 				break; | 				break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| #endif |  | ||||||
|  |  | ||||||
|  |  | ||||||
| int qse_xli_writejson (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_io_impl_t io) | int qse_xli_writejson (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_io_impl_t io) | ||||||
| { | { | ||||||
| 	int n; | 	int n; | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| 	if (io == QSE_NULL) | 	if (io == QSE_NULL) | ||||||
| 	{ | 	{ | ||||||
| 		qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL); | 		qse_xli_seterrnum (xli, QSE_XLI_EINVAL, QSE_NULL); | ||||||
| @ -352,12 +249,11 @@ int qse_xli_writejson (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_io_imp | |||||||
| 	if (qse_xli_openwstream (xli, QSE_NULL, 0) <= -1) return -1; | 	if (qse_xli_openwstream (xli, QSE_NULL, 0) <= -1) return -1; | ||||||
|  |  | ||||||
| 	/* begin writing the root list */ | 	/* begin writing the root list */ | ||||||
| 	n = write_list (xli, (root_list? root_list: &xli->root->list), 0); | 	n = write_list (xli, (root_list? root_list: &xli->root->list), 1); | ||||||
|  |  | ||||||
| 	/* close all open streams. there should be only the | 	/* close all open streams. there should be only the | ||||||
| 	 * top-level stream here if there occurred no errors */ | 	 * top-level stream here if there occurred no errors */ | ||||||
| 	while (xli->wio.inp) qse_xli_closeactivewstream (xli, QSE_NULL); | 	while (xli->wio.inp) qse_xli_closeactivewstream (xli, QSE_NULL); | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	return n; | 	return n; | ||||||
| } | } | ||||||
|  | |||||||
| @ -346,40 +346,24 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
|  |  | ||||||
| 			case QSE_XLI_TEXT: | 			case QSE_XLI_TEXT: | ||||||
| 			{ | 			{ | ||||||
| 				int i; |  | ||||||
| 				const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr; | 				const qse_char_t* str = ((qse_xli_text_t*)curatom)->ptr; | ||||||
|  |  | ||||||
| 				for (i = 0; i < depth; i++)  | 				/* don't honor VERBATIM and DEINDENT flags */ | ||||||
| 				{ | 				if (write_indentation(xli, depth) <= -1 || | ||||||
| 					if (write_to_current_stream (xli, QSE_T("\t"), 1, 0) <= -1) return -1; | 				    write_to_current_stream(xli, QSE_T("#"), 1, 0) <= -1 || | ||||||
| 				} | 				    write_to_current_stream(xli, str, qse_strlen(str), 0) <= -1 || | ||||||
|  | 				    write_to_current_stream(xli, QSE_T("\n"), 1, 0) <= -1) return -1; | ||||||
| 				if (write_to_current_stream (xli, QSE_T("#"), 1, 0) <= -1 || |  | ||||||
| 				    write_to_current_stream (xli, str, qse_strlen(str), 0) <= -1 || |  | ||||||
| 				    write_to_current_stream (xli, QSE_T("\n"), 1, 0) <= -1) return -1; |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			case QSE_XLI_VTEXT: |  | ||||||
| 			{ |  | ||||||
| 				/* no vtext element can be included in the xli format */ |  | ||||||
| 				/* do nothing */ |  | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			case QSE_XLI_FILE: | 			case QSE_XLI_FILE: | ||||||
| 			{ | 			{ | ||||||
| 				int i; |  | ||||||
| 				const qse_char_t* path = ((qse_xli_file_t*)curatom)->path; | 				const qse_char_t* path = ((qse_xli_file_t*)curatom)->path; | ||||||
|  |  | ||||||
| 				for (i = 0; i < depth; i++)  | 				if (write_indentation(xli, depth) <= -1 || | ||||||
| 				{ | 				    write_to_current_stream(xli, QSE_T("@include \""), 10, 0) <= -1 || | ||||||
| 					if (write_to_current_stream (xli, QSE_T("\t"), 1, 0) <= -1) return -1; | 				    write_to_current_stream(xli, path, qse_strlen(path), 1) <= -1 || | ||||||
| 				} | 				    write_to_current_stream(xli, QSE_T("\";\n"), 3, 0) <= -1) return -1; | ||||||
|  |  | ||||||
| 				if (write_to_current_stream (xli, QSE_T("@include \""), 10, 0) <= -1 || |  | ||||||
| 				    write_to_current_stream (xli, path, qse_strlen(path), 1) <= -1 || |  | ||||||
| 				    write_to_current_stream (xli, QSE_T("\";\n"), 3, 0) <= -1) return -1; |  | ||||||
|  |  | ||||||
| 				if (qse_xli_openwstream(xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1; | 				if (qse_xli_openwstream(xli, ((qse_xli_file_t*)curatom)->path, depth) <= -1) return -1; | ||||||
| 				depth = 0; | 				depth = 0; | ||||||
|  | |||||||
| @ -542,20 +542,6 @@ qse_xli_text_t* qse_xli_inserttext ( | |||||||
| 	return text; | 	return text; | ||||||
| } | } | ||||||
|  |  | ||||||
| qse_xli_vtext_t* qse_xli_insertvtext ( |  | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* str) |  | ||||||
| { |  | ||||||
| 	qse_xli_text_t* text; |  | ||||||
|  |  | ||||||
| 	QSE_ASSERT (QSE_SIZEOF(qse_xli_text_t) == QSE_SIZEOF(qse_xli_vtext_t)); |  | ||||||
|  |  | ||||||
| 	text = qse_xli_inserttext (xli, parent, peer, str); |  | ||||||
| 	if (!text) return QSE_NULL; |  | ||||||
|  |  | ||||||
| 	((qse_xli_vtext_t*)text)->type = QSE_XLI_VTEXT; |  | ||||||
| 	return (qse_xli_vtext_t*)text; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| qse_xli_file_t* qse_xli_insertfile ( | qse_xli_file_t* qse_xli_insertfile ( | ||||||
| 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* path) | 	qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* path) | ||||||
| { | { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user