From c8a7b02d6e521136176203f45996bc6dd029e30a Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A1n=20Kupec?= Date: Thu, 22 Jan 2009 16:24:28 +0100 Subject: [PATCH] str::splitFieldsEscaped() added str::splitFieldsEscaped() added and str::splitEscaped() extened by an optional bool parameter 'withEmpty', to include empty fields in the result. --- tests/zypp/base/String_test.cc | 24 +++++++++++++ zypp/base/String.h | 63 +++++++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/tests/zypp/base/String_test.cc b/tests/zypp/base/String_test.cc index a17aa128a..db76e0741 100644 --- a/tests/zypp/base/String_test.cc +++ b/tests/zypp/base/String_test.cc @@ -84,6 +84,30 @@ BOOST_AUTO_TEST_CASE(testsplitEscaped) BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end(), 'o' ) ); } +BOOST_AUTO_TEST_CASE(testsplitEscapedWithEmpty) +{ + string s( "simple:non-escaped:string" ); + vector v; + + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3); + BOOST_CHECK_EQUAL(v.size(), 3); + + v.clear(); + s = "non-escaped:with::spaces:"; + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 5); + BOOST_CHECK_EQUAL(v.size(), 5); + + v.clear(); + s = "::"; + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3); + BOOST_CHECK_EQUAL(v.size(), 3); + + v.clear(); + s = ":escaped::with\\:spaces"; + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 4); + BOOST_CHECK_EQUAL(v.size(), 4); +} + BOOST_AUTO_TEST_CASE(test_escape) { string badass = "bad|ass\\|worse"; diff --git a/zypp/base/String.h b/zypp/base/String.h index a562f9791..1c306a5e4 100644 --- a/zypp/base/String.h +++ b/zypp/base/String.h @@ -372,19 +372,43 @@ namespace zypp * "quoted line" -> 1 element same as above * 'quoted line' -> 1 element same as above * "escaped quote\'" -> 1 element ( "escaped quote'" ) + * + * \param line_r The string to parse. + * \param result_r + * \param sepchars_r String of separator characters. + * \param withEmpty Whether to include empty fields between separators in the result. + * * \endcode - */ + */ template unsigned splitEscaped( const C_Str & line_r, _OutputIterator result_r, - const C_Str & sepchars_r = " \t" ) + const C_Str & sepchars_r = " \t", + bool withEmpty = false) { const char * beg = line_r; const char * cur = beg; + unsigned ret = 0; + // skip leading sepchars while ( *cur && ::strchr( sepchars_r, *cur ) ) + { ++cur; - unsigned ret = 0; + if (withEmpty) + { + *result_r = ""; + ++ret; + } + } + + // there were only sepchars in the string + if (!*cur && withEmpty) + { + *result_r = ""; + return ++ret; + } + + // after the leading sepchars for ( beg = cur; *beg; beg = cur, ++result_r, ++ret ) { if ( *cur == '"' || *cur == '\'' ) @@ -452,8 +476,23 @@ namespace zypp *result_r = s; } // skip sepchars + if ( *cur && ::strchr( sepchars_r, *cur ) ) + ++cur; while ( *cur && ::strchr( sepchars_r, *cur ) ) + { ++cur; + if (withEmpty) + { + *result_r = ""; + ++ret; + } + } + // the last was a separator => one more field + if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) ) + { + *result_r = ""; + ++ret; + } } return ret; } @@ -471,7 +510,7 @@ namespace zypp * ":a:" -> words 3 ||a|| * * \endcode - * + * * \code * std::vector words; * str::split( "some line", std::back_inserter(words) ) @@ -508,6 +547,22 @@ namespace zypp } return ret; } + + /** + * Split \a line_r into fields handling also escaped separators. + * + * \see splitFields() + * \see splitEscaped() + */ + template + unsigned splitFieldsEscaped( const C_Str & line_r, + _OutputIterator result_r, + const C_Str & sepchars_r = ":" ) + { + return + splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ ); + } + //@} /////////////////////////////////////////////////////////////////// -- 2.34.1