From 736cb1fcee04ac2ffcd46fe8d7599b8b0b6430f9 Mon Sep 17 00:00:00 2001 From: Aleksandar Fabijanic Date: Wed, 31 Dec 2008 19:31:03 +0000 Subject: [PATCH] [SF 2479446] Extend StringTokenizer interface --- Foundation/include/Poco/StringTokenizer.h | 37 ++++++++++++--- Foundation/src/StringTokenizer.cpp | 47 +++++++++++++++++-- .../testsuite/src/StringTokenizerTest.cpp | 35 ++++++++++++++ 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/Foundation/include/Poco/StringTokenizer.h b/Foundation/include/Poco/StringTokenizer.h index 42fd87042..b6b3ad594 100644 --- a/Foundation/include/Poco/StringTokenizer.h +++ b/Foundation/include/Poco/StringTokenizer.h @@ -61,7 +61,8 @@ public: TOK_TRIM = 2 /// remove leading and trailing whitespace from tokens }; - typedef std::vector::const_iterator Iterator; + typedef std::vector TokenVec; + typedef TokenVec::const_iterator Iterator; StringTokenizer(const std::string& str, const std::string& separators, int options = 0); /// Splits the given string into tokens. The tokens are expected to be @@ -81,22 +82,37 @@ public: Iterator end() const; const std::string& operator [] (std::size_t index) const; - /// Returns the index'th token. + /// Returns const reference the index'th token. /// Throws a RangeException if the index is out of range. - std::size_t find(const std::string& key, std::size_t pos = 0) const; - /// Returns the index of the first occurence of the key token + std::string& operator [] (std::size_t index); + /// Returns reference to the index'th token. + /// Throws a RangeException if the index is out of range. + + bool has(const std::string& token) const; + /// Returns true if token exists, false otherwise. + + std::size_t find(const std::string& token, std::size_t pos = 0) const; + /// Returns the index of the first occurence of the token /// starting at position pos. - /// Throws a NotFoundException if the key is not found. + /// Throws a NotFoundException if the token is not found. + + std::size_t replace(const std::string& oldToken, const std::string& newToken, std::size_t pos = 0); + /// Starting at position pos, replaces all subsequent tokens having value + /// equal to oldToken with newToken. + /// Returns the number of modified tokens. std::size_t count() const; - /// Returns the number of tokens. + /// Returns the total number of tokens. + + std::size_t count(const std::string& token) const; + /// Returns the number of tokens equal to the specified token. private: StringTokenizer(const StringTokenizer&); StringTokenizer& operator = (const StringTokenizer&); - std::vector _tokens; + TokenVec _tokens; }; @@ -117,6 +133,13 @@ inline StringTokenizer::Iterator StringTokenizer::end() const } +inline std::string& StringTokenizer::operator [] (std::size_t index) +{ + if (index >= _tokens.size()) throw RangeException(); + return _tokens[index]; +} + + inline const std::string& StringTokenizer::operator [] (std::size_t index) const { if (index >= _tokens.size()) throw RangeException(); diff --git a/Foundation/src/StringTokenizer.cpp b/Foundation/src/StringTokenizer.cpp index 2e40d150d..afafa0e5f 100644 --- a/Foundation/src/StringTokenizer.cpp +++ b/Foundation/src/StringTokenizer.cpp @@ -83,14 +83,55 @@ StringTokenizer::~StringTokenizer() } -std::size_t StringTokenizer::find(const std::string& key, std::size_t pos) const +bool StringTokenizer::has(const std::string& token) const +{ + Iterator it = begin(); + Iterator stop = end(); + for (; it != stop; ++it) + if (*it == token) return true; + + return false; +} + + +std::size_t StringTokenizer::find(const std::string& token, std::size_t pos) const { Iterator it = begin(); Iterator stop = end(); for (it += pos; it != stop; ++it) - if (*it == key) return it - begin(); + if (*it == token) return it - begin(); - throw NotFoundException(key); + throw NotFoundException(token); +} + + +std::size_t StringTokenizer::replace(const std::string& oldToken, const std::string& newToken, std::size_t pos) +{ + std::size_t count = 0; + TokenVec::iterator it = _tokens.begin(); + TokenVec::iterator stop = _tokens.end(); + for (it += pos; it != stop; ++it) + { + if (*it == oldToken) + { + *it = newToken; + ++count; + } + } + + return count; +} + + +std::size_t StringTokenizer::count(const std::string& token) const +{ + std::size_t cnt = 0; + Iterator it = begin(); + Iterator stop = end(); + for (; it != stop; ++it) + if (*it == token) ++cnt; + + return cnt; } diff --git a/Foundation/testsuite/src/StringTokenizerTest.cpp b/Foundation/testsuite/src/StringTokenizerTest.cpp index 136e20eb1..acc201e50 100644 --- a/Foundation/testsuite/src/StringTokenizerTest.cpp +++ b/Foundation/testsuite/src/StringTokenizerTest.cpp @@ -346,7 +346,17 @@ void StringTokenizerTest::testStringTokenizer() void StringTokenizerTest::testFind() { StringTokenizer st("0,1,2,3,3,2,1,0", ",", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY); + assert (st.count() == 8); + assert (2 == st.count("0")); + assert (2 == st.count("1")); + assert (2 == st.count("2")); + assert (2 == st.count("3")); + assert (0 == st.count("4")); + assert (0 == st.count("5")); + assert (0 == st.count("6")); + assert (0 == st.count("7")); + assert (st[0] == "0"); assert (st[1] == "1"); assert (st[2] == "2"); @@ -355,6 +365,16 @@ void StringTokenizerTest::testFind() assert (st[5] == "2"); assert (st[6] == "1"); assert (st[7] == "0"); + + assert (st.has("0")); + assert (st.has("1")); + assert (st.has("2")); + assert (st.has("3")); + assert (!st.has("4")); + assert (!st.has("5")); + assert (!st.has("6")); + assert (!st.has("7")); + assert (st.find("0") == 0); assert (st.find("1") == 1); assert (st.find("2") == 2); @@ -378,6 +398,21 @@ void StringTokenizerTest::testFind() fail ("must fail"); } catch (RangeException&) { } + + st[0] = "1"; + st[7] = "1"; + assert (st[0] == "1"); + assert (st[7] == "1"); + assert (0 == st.count("0")); + assert (4 == st.count("1")); + + st.replace("2", "5"); + assert (0 == st.count("2")); + assert (2 == st.count("5")); + + st.replace("3", "6", 4); + assert (1 == st.count("3")); + assert (1 == st.count("6")); }