enhanced the json writer to inject {} or [] manually when the outermost enclosers are not found
This commit is contained in:
		| @ -30,7 +30,7 @@ | |||||||
| #include <qse/types.h> | #include <qse/types.h> | ||||||
| #include <qse/macros.h> | #include <qse/macros.h> | ||||||
|  |  | ||||||
| /** @file | /** \file | ||||||
|  * This file defines functions and data structures to process  |  * This file defines functions and data structures to process  | ||||||
|  * command-line arguments.  |  * command-line arguments.  | ||||||
|  */ |  */ | ||||||
|  | |||||||
| @ -199,7 +199,11 @@ typedef enum qse_xli_list_flag_t qse_xli_list_flag_t; | |||||||
| enum qse_xli_text_flag_t | enum qse_xli_text_flag_t | ||||||
| { | { | ||||||
| 	QSE_XLI_TEXT_VERBATIM            = (1 << 0), | 	QSE_XLI_TEXT_VERBATIM            = (1 << 0), | ||||||
| 	QSE_XLI_TEXT_DEINDENT = (1 << 1) | 	QSE_XLI_TEXT_DEINDENT            = (1 << 1), | ||||||
|  | 	QSE_XLI_TEXT_LIST_OPENER         = (1 << 2), | ||||||
|  | 	QSE_XLI_TEXT_LIST_CLOSER         = (1 << 3), | ||||||
|  | 	QSE_XLI_TEXT_ARRAYED_LIST_OPENER = (1 << 4), | ||||||
|  | 	QSE_XLI_TEXT_ARRAYED_LIST_CLOSER = (1 << 5) | ||||||
| }; | }; | ||||||
| typedef enum qse_xli_text_flag_t qse_xli_text_flag_t; | typedef enum qse_xli_text_flag_t qse_xli_text_flag_t; | ||||||
|  |  | ||||||
|  | |||||||
| @ -832,7 +832,7 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 			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)); | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
| 			if (!ta) goto oops; | 			if (!ta) goto oops; | ||||||
| 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT | QSE_XLI_TEXT_ARRAYED_LIST_OPENER; | ||||||
| 			xli->tok_status &= ~TOK_STATUS_DEINDENT_TEXT; | 			xli->tok_status &= ~TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| @ -842,7 +842,7 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 			qse_xli_text_t* ta; | 			qse_xli_text_t* ta; | ||||||
| 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
| 			if (!ta) goto oops; | 			if (!ta) goto oops; | ||||||
| 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT | QSE_XLI_TEXT_LIST_OPENER; | ||||||
| 			xli->tok_status &= ~TOK_STATUS_DEINDENT_TEXT; | 			xli->tok_status &= ~TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| @ -865,7 +865,7 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 			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)); | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
| 			if (!ta) goto oops; | 			if (!ta) goto oops; | ||||||
| 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT | QSE_XLI_TEXT_ARRAYED_LIST_CLOSER; | ||||||
| 			xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | 			xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
| @ -876,7 +876,7 @@ static int read_root_list (qse_xli_t* xli) | |||||||
| 			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)); | 			ta = qse_xli_inserttext(xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(xli->tok.name)); | ||||||
| 			if (!ta) goto oops; | 			if (!ta) goto oops; | ||||||
| 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT; | 			ta->flags |= QSE_XLI_TEXT_VERBATIM | QSE_XLI_TEXT_DEINDENT | QSE_XLI_TEXT_LIST_CLOSER; | ||||||
| 			xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | 			xli->tok_status |= TOK_STATUS_DEINDENT_TEXT; | ||||||
| 			if (get_token(xli) <= -1) goto oops; | 			if (get_token(xli) <= -1) goto oops; | ||||||
| 			break; | 			break; | ||||||
|  | |||||||
| @ -228,9 +228,25 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static int have_opening_marker (qse_xli_t* xli, qse_xli_list_t* list) | ||||||
|  | { | ||||||
|  | 	qse_xli_atom_t* curatom; | ||||||
|  |  | ||||||
|  | 	for (curatom = list->head; curatom; curatom = curatom->next) | ||||||
|  | 	{ | ||||||
|  | 		qse_xli_text_t* ta; | ||||||
|  | 		if (curatom->type != QSE_XLI_TEXT) break; | ||||||
|  | 		ta = (qse_xli_text_t*)curatom; | ||||||
|  | 		if (ta->flags & (QSE_XLI_TEXT_ARRAYED_LIST_OPENER | QSE_XLI_TEXT_LIST_OPENER)) return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| 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, marker; | ||||||
|  |  | ||||||
| 	if (io == QSE_NULL) | 	if (io == QSE_NULL) | ||||||
| 	{ | 	{ | ||||||
| @ -248,8 +264,23 @@ int qse_xli_writejson (qse_xli_t* xli, qse_xli_list_t* root_list, qse_xli_io_imp | |||||||
| 	/* open the top level stream */ | 	/* open the top level stream */ | ||||||
| 	if (qse_xli_openwstream (xli, QSE_NULL, 0) <= -1) return -1; | 	if (qse_xli_openwstream (xli, QSE_NULL, 0) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 	if (!root_list) root_list = &xli->root->list; | ||||||
|  |  | ||||||
|  | 	marker = have_opening_marker(xli, root_list); | ||||||
|  | 	if (!marker) | ||||||
|  | 	{ | ||||||
|  | 		/* if the data has been loaded from a different format like xli or ini, | ||||||
|  | 		 * there are no opening and closing markers. so emit them manually */ | ||||||
|  | 		if (write_to_current_stream(xli, ((root_list->flags & QSE_XLI_LIST_ARRAYED)? QSE_T("[\n"): QSE_T("{\n")), 2, 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), 1); | 	n = write_list (xli, root_list, 1); | ||||||
|  |  | ||||||
|  | 	if (!marker) | ||||||
|  | 	{ | ||||||
|  | 		if (write_to_current_stream(xli, ((root_list->flags & QSE_XLI_LIST_ARRAYED)? QSE_T("]\n"): QSE_T("}\n")), 2, 0) <= -1) return -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 */ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user