Rewrote sepstream and tokenstream to be less ugly

This commit is contained in:
Adam 2013-05-26 18:24:53 -04:00
parent 81fce393e9
commit 01ac5148e9
2 changed files with 107 additions and 150 deletions

View File

@ -264,6 +264,72 @@ namespace irc
};
/** 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
* an empty string.
*/
class CoreExport sepstream
{
protected:
/** Original string.
*/
std::string tokens;
/** Separator value
*/
char sep;
/** Current string position
*/
size_t pos;
/** If set then GetToken() can return an empty string
*/
bool allow_empty;
public:
/** Create a sepstream and fill it with the provided data
*/
sepstream(const std::string &source, char seperator, bool allowempty = false);
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
bool GetToken(std::string& token);
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
const std::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
*/
bool StreamEnd();
};
/** A derived form of sepstream, which seperates on commas
*/
class CoreExport commasepstream : public sepstream
{
public:
/** Initialize with comma seperator
*/
commasepstream(const std::string &source, bool allowempty = false) : sepstream(source, ',', allowempty)
{
}
};
/** A derived form of sepstream, which seperates on spaces
*/
class CoreExport spacesepstream : public sepstream
{
public:
/** Initialize with space seperator
*/
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.
@ -276,27 +342,9 @@ namespace irc
* list will be ":item". This is to allow for parsing 'source' fields
* from data.
*/
class CoreExport tokenstream
class CoreExport tokenstream : private spacesepstream
{
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);
@ -326,72 +374,6 @@ namespace irc
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
* an empty string.
*/
class CoreExport sepstream
{
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;
/** Seperator value
*/
char sep;
public:
/** Create a sepstream and fill it with the provided data
*/
sepstream(const std::string &source, char seperator);
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
bool GetToken(std::string& token);
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
const std::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
*/
bool StreamEnd();
};
/** A derived form of sepstream, which seperates on commas
*/
class CoreExport commasepstream : public sepstream
{
public:
/** Initialize with comma seperator
*/
commasepstream(const std::string &source) : sepstream(source, ',')
{
}
};
/** A derived form of sepstream, which seperates on spaces
*/
class CoreExport spacesepstream : public sepstream
{
public:
/** Initialize with space seperator
*/
spacesepstream(const std::string &source) : sepstream(source, ' ')
{
}
};
/** 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

View File

@ -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())
if (!spacesepstream::GetToken(token))
return false;
/* This is the last parameter */
if (token[0] == ':' && !first)
{
/** Skip multi space, converting " " into " "
*/
while ((n+1 != tokens.end()) && (*n == ' ') && (*(n+1) == ' '))
n++;
if ((last_pushed) && (*n == ':'))
token = token.substr(1);
if (!StreamEnd())
{
/* 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;
token += ' ';
token += GetRemaining();
}
last_pushed = false;
if ((*n == ' ') || (n+1 == tokens.end()))
{
/* 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();
}
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 seperator, 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;
while (n != tokens.end())
if (this->StreamEnd())
{
if ((*n == sep) || (n+1 == tokens.end()))
{
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;
}
n++;
token.clear();
return false;
}
token.clear();
return false;
if (!this->allow_empty)
{
this->pos = this->tokens.find_first_not_of(this->sep, this->pos);
if (this->pos == std::string::npos)
{
this->pos = this->tokens.length() + 1;
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)