]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Rewrote sepstream and tokenstream to be less ugly
authorAdam <Adam@anope.org>
Sun, 26 May 2013 22:24:53 +0000 (18:24 -0400)
committerAdam <Adam@anope.org>
Sun, 2 Jun 2013 00:45:53 +0000 (02:45 +0200)
include/hashcomp.h
src/hashcomp.cpp

index e142dcfd39393560721e259d81b20ecdd94309a9..0f530e97e30709334109c69d7cadba2af470698d 100644 (file)
@@ -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 seperator, bool allowempty = false);
 
                /** Fetch the next token from the stream
                 * @param token The next token from the stream is placed here
@@ -375,7 +313,7 @@ namespace irc
         public:
                /** Initialize with comma seperator
                 */
-               commasepstream(const std::string &source) : sepstream(source, ',')
+               commasepstream(const std::string &source, bool allowempty = false) : sepstream(source, ',', allowempty)
                {
                }
        };
@@ -387,11 +325,55 @@ namespace irc
         public:
                /** Initialize with space seperator
                 */
-               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
index 1d37c2a80e7858370b9f37116ade3b78475ccbb1..29b67aea46e75c9ea007137d64ec7dbf4fb2cd79 100644 (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())
-       {
-               /** 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 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;
+       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)