diff --git a/bstring/bstraux.c b/bstring/bstraux.c index 18d33c9..92d57fe 100644 --- a/bstring/bstraux.c +++ b/bstring/bstraux.c @@ -909,6 +909,25 @@ bYDecode(const bstring src) return out; } +/* int bSGMLEncode (bstring b) + * + * Change the string into a version that is quotable in SGML (HTML, XML). + */ +int +bSGMLEncode(bstring b) +{ +static struct tagbstring fr[4][2] = { + { bsStatic("&"), bsStatic("&") }, + { bsStatic("\""), bsStatic(""") }, + { bsStatic("<"), bsStatic("<") }, + { bsStatic(">"), bsStatic(">") } }; + for (int i = 0; i < 4; i++) { + int ret = bfindreplace(b, &fr[i][0], &fr[i][1], 0); + if (0 > ret) return ret; + } + return 0; +} + bstring bStrfTime(const char * fmt, const struct tm * timeptr) { diff --git a/bstring/bstraux.h b/bstring/bstraux.h index 12e6125..ac9a2ba 100644 --- a/bstring/bstraux.h +++ b/bstring/bstraux.h @@ -322,6 +322,16 @@ bYEncode(const bstring src); BSTR_PUBLIC bstring bYDecode(const bstring src); +/** + * Change the string into a version that is quotable in SGML (HTML, XML). + * Replaces &, ", <, > with their SGML entity equivalents. + * + * @param b the bstring to encode in-place + * @return BSTR_OK on success, BSTR_ERR on error + */ +BSTR_PUBLIC int +bSGMLEncode(bstring b); + /* Writable stream */ typedef int (*bNwrite)(const void *buf, size_t elsize, size_t nelem, void *parm); diff --git a/tests/testaux.c b/tests/testaux.c index 6cc6983..ff80d96 100644 --- a/tests/testaux.c +++ b/tests/testaux.c @@ -483,6 +483,33 @@ START_TEST(core_013) } END_TEST +START_TEST(core_014) +{ + bstring b; + + /* All four entities: &, ", <, > */ + b = bfromcstr("<\"Hello, you, me, & world\">"); + ck_assert_int_eq(bSGMLEncode(b), BSTR_OK); + ck_assert_int_eq(biseqcstr(b, "<"Hello, you, me, & world">"), 1); + bdestroy(b); + + /* No special characters — string should be unchanged */ + b = bfromcstr("Hello, world"); + ck_assert_int_eq(bSGMLEncode(b), BSTR_OK); + ck_assert_int_eq(biseqcstr(b, "Hello, world"), 1); + bdestroy(b); + + /* Empty string */ + b = bfromcstr(""); + ck_assert_int_eq(bSGMLEncode(b), BSTR_OK); + ck_assert_int_eq(biseqcstr(b, ""), 1); + bdestroy(b); + + /* NULL input */ + ck_assert_int_eq(bSGMLEncode(NULL), BSTR_ERR); +} +END_TEST + int main(void) { @@ -504,6 +531,7 @@ main(void) tcase_add_test(core, core_011); tcase_add_test(core, core_012); tcase_add_test(core, core_013); + tcase_add_test(core, core_014); suite_add_tcase(suite, core); /* Run tests */ SRunner *runner = srunner_create(suite);