summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <adam@sigterm.info>2013-06-01 19:05:51 -0700
committerAdam <adam@sigterm.info>2013-06-01 19:05:51 -0700
commit94c248f9dac7b32189f45445896eeecd57ad1d36 (patch)
tree24a86b0ef0832dcd8db95ce424ea9706f97a1603
parent81fce393e99a940682cf58a1203f4ed03d1887fc (diff)
parentfdac3263c0ee8423bac88007af19f4873986ae26 (diff)
Merge pull request #550 from Adam-/master+sepstream
Rewrote sepstream and tokenstream to be less ugly
-rw-r--r--include/hashcomp.h134
-rw-r--r--src/hashcomp.cpp103
2 files changed, 97 insertions, 140 deletions
diff --git a/include/hashcomp.h b/include/hashcomp.h
index e142dcfd3..0d3857d56 100644
--- a/include/hashcomp.h
+++ b/include/hashcomp.h
@@ -164,7 +164,7 @@ namespace irc
typedef std::basic_string<char, irc_char_traits, std::allocator<char> > string;
/** irc::stringjoiner joins string lists into a string, using
- * the given seperator string.
+ * the given separator string.
* This class can join a vector of std::string, a deque of
* std::string, or a const char* const* array, using overloaded
* constructors.
@@ -180,12 +180,12 @@ namespace irc
public:
/** Join elements of a vector, between (and including) begin and end
- * @param seperator The string to seperate values with
+ * @param separator The string to seperate values with
* @param sequence One or more items to seperate
* @param begin The starting element in the sequence to be joined
* @param end The ending element in the sequence to be joined
*/
- stringjoiner(const std::string& seperator, const std::vector<std::string>& sequence, unsigned int begin, unsigned int end);
+ stringjoiner(const std::string& separator, const std::vector<std::string>& sequence, unsigned int begin, unsigned int end);
/** Get the joined sequence
* @return A constant reference to the joined string
@@ -264,68 +264,6 @@ namespace irc
};
- /** irc::tokenstream reads a string formatted as per RFC1459 and RFC2812.
- * It will split the string into 'tokens' each containing one parameter
- * from the string.
- * For instance, if it is instantiated with the string:
- * "PRIVMSG #test :foo bar baz qux"
- * then each successive call to tokenstream::GetToken() will return
- * "PRIVMSG", "#test", "foo bar baz qux", "".
- * Note that if the whole string starts with a colon this is not taken
- * to mean the string is all one parameter, and the first item in the
- * list will be ":item". This is to allow for parsing 'source' fields
- * from data.
- */
- class CoreExport tokenstream
- {
- private:
-
- /** Original string
- */
- std::string tokens;
-
- /** Last position of a seperator token
- */
- std::string::iterator last_starting_position;
-
- /** Current string position
- */
- std::string::iterator n;
-
- /** True if the last value was an ending value
- */
- bool last_pushed;
- public:
-
- /** Create a tokenstream and fill it with the provided data
- */
- tokenstream(const std::string &source);
-
- /** Fetch the next token from the stream as a std::string
- * @param token The next token available, or an empty string if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(std::string &token);
-
- /** Fetch the next token from the stream as an irc::string
- * @param token The next token available, or an empty string if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(irc::string &token);
-
- /** Fetch the next token from the stream as an integer
- * @param token The next token available, or undefined if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(int &token);
-
- /** Fetch the next token from the stream as a long integer
- * @param token The next token available, or undefined if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(long &token);
- };
-
/** irc::sepstream allows for splitting token seperated lists.
* Each successive call to sepstream::GetToken() returns
* the next token, until none remain, at which point the method returns
@@ -333,23 +271,23 @@ namespace irc
*/
class CoreExport sepstream
{
- private:
+ protected:
/** Original string.
*/
std::string tokens;
- /** Last position of a seperator token
+ /** Separator value
*/
- std::string::iterator last_starting_position;
+ char sep;
/** Current string position
*/
- std::string::iterator n;
- /** Seperator value
+ size_t pos;
+ /** If set then GetToken() can return an empty string
*/
- char sep;
+ bool allow_empty;
public:
/** Create a sepstream and fill it with the provided data
*/
- sepstream(const std::string &source, char seperator);
+ sepstream(const std::string &source, char separator, bool allowempty = false);
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
@@ -373,9 +311,9 @@ namespace irc
class CoreExport commasepstream : public sepstream
{
public:
- /** Initialize with comma seperator
+ /** Initialize with comma separator
*/
- commasepstream(const std::string &source) : sepstream(source, ',')
+ commasepstream(const std::string &source, bool allowempty = false) : sepstream(source, ',', allowempty)
{
}
};
@@ -385,13 +323,57 @@ namespace irc
class CoreExport spacesepstream : public sepstream
{
public:
- /** Initialize with space seperator
+ /** Initialize with space separator
*/
- spacesepstream(const std::string &source) : sepstream(source, ' ')
+ spacesepstream(const std::string &source, bool allowempty = false) : sepstream(source, ' ', allowempty)
{
}
};
+ /** irc::tokenstream reads a string formatted as per RFC1459 and RFC2812.
+ * It will split the string into 'tokens' each containing one parameter
+ * from the string.
+ * For instance, if it is instantiated with the string:
+ * "PRIVMSG #test :foo bar baz qux"
+ * then each successive call to tokenstream::GetToken() will return
+ * "PRIVMSG", "#test", "foo bar baz qux", "".
+ * Note that if the whole string starts with a colon this is not taken
+ * to mean the string is all one parameter, and the first item in the
+ * list will be ":item". This is to allow for parsing 'source' fields
+ * from data.
+ */
+ class CoreExport tokenstream : private spacesepstream
+ {
+ public:
+ /** Create a tokenstream and fill it with the provided data
+ */
+ tokenstream(const std::string &source);
+
+ /** Fetch the next token from the stream as a std::string
+ * @param token The next token available, or an empty string if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(std::string &token);
+
+ /** Fetch the next token from the stream as an irc::string
+ * @param token The next token available, or an empty string if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(irc::string &token);
+
+ /** Fetch the next token from the stream as an integer
+ * @param token The next token available, or undefined if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(int &token);
+
+ /** Fetch the next token from the stream as a long integer
+ * @param token The next token available, or undefined if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(long &token);
+ };
+
/** The portparser class seperates out a port range into integers.
* A port range may be specified in the input string in the form
* "6660,6661,6662-6669,7020". The end of the stream is indicated by
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 1d37c2a80..06b3ce669 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -238,56 +238,30 @@ const char* irc::irc_char_traits::find(const char* s1, int n, char c)
return (n >= 0) ? s1 : NULL;
}
-irc::tokenstream::tokenstream(const std::string &source) : tokens(source), last_pushed(false)
+irc::tokenstream::tokenstream(const std::string &source) : spacesepstream(source)
{
- /* Record starting position and current position */
- last_starting_position = tokens.begin();
- n = tokens.begin();
}
bool irc::tokenstream::GetToken(std::string &token)
{
- std::string::iterator lsp = last_starting_position;
+ bool first = !pos;
- while (n != tokens.end())
- {
- /** Skip multi space, converting " " into " "
- */
- while ((n+1 != tokens.end()) && (*n == ' ') && (*(n+1) == ' '))
- n++;
-
- if ((last_pushed) && (*n == ':'))
- {
- /* If we find a token thats not the first and starts with :,
- * this is the last token on the line
- */
- std::string::iterator curr = ++n;
- n = tokens.end();
- token = std::string(curr, tokens.end());
- return true;
- }
-
- last_pushed = false;
+ if (!spacesepstream::GetToken(token))
+ return false;
- if ((*n == ' ') || (n+1 == tokens.end()))
+ /* This is the last parameter */
+ if (token[0] == ':' && !first)
+ {
+ token = token.substr(1);
+ if (!StreamEnd())
{
- /* If we find a space, or end of string, this is the end of a token.
- */
- last_starting_position = n+1;
- last_pushed = *n == ' ';
-
- std::string strip(lsp, n+1 == tokens.end() ? n+1 : n++);
- while ((strip.length()) && (strip.find_last_of(' ') == strip.length() - 1))
- strip.erase(strip.end() - 1);
-
- token = strip;
- return !token.empty();
+ token += ' ';
+ token += GetRemaining();
}
-
- n++;
+ pos = tokens.length() + 1;
}
- token.clear();
- return false;
+
+ return true;
}
bool irc::tokenstream::GetToken(irc::string &token)
@@ -314,47 +288,48 @@ bool irc::tokenstream::GetToken(long &token)
return returnval;
}
-irc::sepstream::sepstream(const std::string &source, char seperator) : tokens(source), sep(seperator)
+irc::sepstream::sepstream(const std::string& source, char separator, bool allowempty)
+ : tokens(source), sep(separator), pos(0), allow_empty(allowempty)
{
- last_starting_position = tokens.begin();
- n = tokens.begin();
}
bool irc::sepstream::GetToken(std::string &token)
{
- std::string::iterator lsp = last_starting_position;
+ if (this->StreamEnd())
+ {
+ token.clear();
+ return false;
+ }
- while (n != tokens.end())
+ if (!this->allow_empty)
{
- if ((*n == sep) || (n+1 == tokens.end()))
+ this->pos = this->tokens.find_first_not_of(this->sep, this->pos);
+ if (this->pos == std::string::npos)
{
- last_starting_position = n+1;
- token = std::string(lsp, n+1 == tokens.end() ? n+1 : n++);
-
- while ((token.length()) && (token.find_last_of(sep) == token.length() - 1))
- token.erase(token.end() - 1);
-
- if (token.empty())
- n++;
-
- return n == tokens.end() ? false : true;
+ this->pos = this->tokens.length() + 1;
+ token.clear();
+ return false;
}
-
- n++;
}
- token.clear();
- return false;
+ size_t p = this->tokens.find(this->sep, this->pos);
+ if (p == std::string::npos)
+ p = this->tokens.length();
+
+ token = this->tokens.substr(this->pos, p - this->pos);
+ this->pos = p + 1;
+
+ return true;
}
const std::string irc::sepstream::GetRemaining()
{
- return std::string(n, tokens.end());
+ return !this->StreamEnd() ? this->tokens.substr(this->pos) : "";
}
bool irc::sepstream::StreamEnd()
{
- return ((n + 1) == tokens.end());
+ return this->pos > this->tokens.length();
}
irc::modestacker::modestacker(bool add) : adding(add)
@@ -422,13 +397,13 @@ int irc::modestacker::GetStackedLine(std::vector<std::string> &result, int max_l
return n;
}
-irc::stringjoiner::stringjoiner(const std::string& seperator, const std::vector<std::string>& sequence, unsigned int begin, unsigned int end)
+irc::stringjoiner::stringjoiner(const std::string& separator, const std::vector<std::string>& sequence, unsigned int begin, unsigned int end)
{
if (end < begin)
return; // nothing to do here
for (unsigned int v = begin; v < end; v++)
- joined.append(sequence[v]).append(seperator);
+ joined.append(sequence[v]).append(separator);
joined.append(sequence[end]);
}