diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index fde1812f..ef911230 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -175,6 +175,33 @@ namespace simgear { return result; } + + string_list split_on_any_of(const std::string& str, const char* seperators) + { + if (seperators == nullptr || (strlen(seperators) == 0)) { + throw sg_exception("illegal/missing seperator string"); + } + + string_list result; + size_t pos = 0; + size_t startPos = str.find_first_not_of(seperators, 0); + for(;;) + { + pos = str.find_first_of(seperators, startPos); + if (pos == string::npos) { + result.push_back(str.substr(startPos)); + break; + } + result.push_back(str.substr(startPos, pos - startPos)); + startPos = str.find_first_not_of(seperators, pos); + if (startPos == string::npos) { + break; + } + } + return result; + + } + /** * The lstrip(), rstrip() and strip() functions are implemented * in do_strip() which uses an additional parameter to indicate what diff --git a/simgear/misc/strutils.hxx b/simgear/misc/strutils.hxx index 4343971a..94008afe 100644 --- a/simgear/misc/strutils.hxx +++ b/simgear/misc/strutils.hxx @@ -122,6 +122,17 @@ namespace simgear { const char* sep = 0, int maxsplit = 0 ); + /** + * split a string on any of several characters. Commonly used to deal + * with strings containing whitespace, newlines. To parse CSS style + * string, use with '\n\t ,' as the seperator list. + * + * Note consecutive seperators will not produce empty entries in the + * the result, i.e splitting 'a,b,,c,d' with a ',' will produce a result + * with four entries, not five. + */ + string_list split_on_any_of(const std::string&, const char* seperators); + /** * create a single string by joining the elements of a list with * another string. diff --git a/simgear/misc/strutils_test.cxx b/simgear/misc/strutils_test.cxx index e0fdbdee..81d12a2d 100644 --- a/simgear/misc/strutils_test.cxx +++ b/simgear/misc/strutils_test.cxx @@ -119,6 +119,24 @@ void test_split() l = strutils::split(" ", ","); SG_CHECK_EQUAL(l.size(), 1); SG_CHECK_EQUAL(l[0], " "); + + + const char* testCases[] = { + "alpha,bravo, charlie\tdelta\n\recho, \t\r\nfoxtrot golf,\n\t\n \n", + " alpha bravo \t charlie,,,delta echo\nfoxtrot\rgolf" + }; + + for (const char* data: testCases) { + l = strutils::split_on_any_of(data, "\n\t\r ,"); + SG_CHECK_EQUAL(l.size(), 7); + SG_CHECK_EQUAL(l[0], "alpha"); + SG_CHECK_EQUAL(l[1], "bravo"); + SG_CHECK_EQUAL(l[2], "charlie"); + SG_CHECK_EQUAL(l[3], "delta"); + SG_CHECK_EQUAL(l[4], "echo"); + SG_CHECK_EQUAL(l[5], "foxtrot"); + SG_CHECK_EQUAL(l[6], "golf"); + } } void test_unescape()