]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Split irc::tokenparser::GetToken into GetMiddle and GetTrailing.
authorPeter Powell <petpow@saberuk.com>
Fri, 10 Aug 2018 06:46:42 +0000 (07:46 +0100)
committerPeter Powell <petpow@saberuk.com>
Fri, 10 Aug 2018 12:55:32 +0000 (13:55 +0100)
This simplifies the logic of irc::tokenparser considerably and
removes all of the magic index guessing that was used previously.

include/hashcomp.h
src/command_parse.cpp
src/hashcomp.cpp
src/modules/m_alias.cpp
src/modules/m_filter.cpp
src/modules/m_spanningtree/compat.cpp
src/modules/m_spanningtree/treesocket2.cpp
src/modules/m_xline_db.cpp

index 9a31694359d0bee6de0b1fbcc6667a211ff46293..b9c568135f7da730de600a0308ea288f022e4b19 100644 (file)
@@ -186,18 +186,30 @@ namespace irc
         * list will be ":item". This is to allow for parsing 'source' fields
         * from data.
         */
-       class CoreExport tokenstream : private spacesepstream
+       class CoreExport tokenstream
        {
+       private:
+               /** The message we are parsing tokens from. */
+               std::string message;
+
+               /** The current position within the message. */
+               size_t position;
+
         public:
-               /** Create a tokenstream and fill it with the provided data
+               /** Create a tokenstream and fill it with the provided data. */
+               tokenstream(const std::string& msg, size_t start = 0);
+
+               /** Retrieve the next <middle> token in the token stream.
+                * @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.
                 */
-               tokenstream(const std::string &source);
+               bool GetMiddle(std::string& token);
 
-               /** Fetch the next token from the stream as a std::string
-                * @param token The next token available, or an empty string if none remain
+               /** Retrieve the next <trailing> token in the token stream.
+                * @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);
+               bool GetTrailing(std::string& token);
        };
 
        /** The portparser class seperates out a port range into integers.
index 97980112e7503113cabb532c7b0fc4aa51ed93c3..fb8ea25652c27d65e35698917fe340f7822802b1 100644 (file)
@@ -164,7 +164,7 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
        CommandBase::Params command_p;
        irc::tokenstream tokens(cmd);
        std::string command, token;
-       tokens.GetToken(command);
+       tokens.GetMiddle(command);
 
        /* A client sent a nick prefix on their command (ick)
         * rhapsody and some braindead bouncers do this --
@@ -172,9 +172,9 @@ void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
         * discard it if they do.
         */
        if (command[0] == ':')
-               tokens.GetToken(command);
+               tokens.GetMiddle(command);
 
-       while (tokens.GetToken(token))
+       while (tokens.GetTrailing(token))
                command_p.push_back(token);
 
        std::transform(command.begin(), command.end(), command.begin(), ::toupper);
index d510e40b179b322762e64fe7a0c30a0c224fd24c..47c36b91bac176c03ff84124cbbc67d797d1cdb6 100644 (file)
@@ -193,32 +193,57 @@ size_t irc::insensitive::operator()(const std::string &s) const
        return t;
 }
 
-irc::tokenstream::tokenstream(const std::string &source) : spacesepstream(source)
+irc::tokenstream::tokenstream(const std::string& msg, size_t start)
+       : message(msg, start)
+       , position(0)
 {
 }
 
-bool irc::tokenstream::GetToken(std::string &token)
+bool irc::tokenstream::GetMiddle(std::string& token)
 {
-       bool first = !pos;
-
-       if (!spacesepstream::GetToken(token))
+       // If we are past the end of the string we can't do anything.
+       if (position >= message.length())
+       {
+               token.clear();
                return false;
+       }
 
-       /* This is the last parameter */
-       if (token[0] == ':' && !first)
+       // If we can't find another separator this is the last token in the message.
+       size_t separator = message.find(' ', position);
+       if (separator == std::string::npos)
        {
-               token.erase(token.begin());
-               if (!StreamEnd())
-               {
-                       token += ' ';
-                       token += GetRemaining();
-               }
-               pos = tokens.length() + 1;
+               token.assign(message, position);
+               position = message.length();
+               return true;
        }
 
+       token.assign(message, position, separator - position);
+       position = message.find_first_not_of(' ', separator);
        return true;
 }
 
+bool irc::tokenstream::GetTrailing(std::string& token)
+{
+       // If we are past the end of the string we can't do anything.
+       if (position >= message.length())
+       {
+               token.clear();
+               return false;
+       }
+
+       // If this is true then we have a <trailing> token!
+       if (message[position] == ':')
+       {
+               token.assign(message, position + 1);
+               position = message.length();
+               ServerInstance->Logs->Log("HASHCOMP", LOG_DEBUG, "TRAILING %s next (none)", token.c_str());
+               return true;
+       }
+
+       // There is no <trailing> token so it must be a <middle> token.
+       return GetMiddle(token);
+}
+
 irc::sepstream::sepstream(const std::string& source, char separator, bool allowempty)
        : tokens(source), sep(separator), pos(0), allow_empty(allowempty)
 {
index 4333971236ce28c2bce638cf36065275ae15e940..76ccc6ebc0a0ca0df8050a6d73f852f95887451d 100644 (file)
@@ -346,8 +346,8 @@ class ModuleAlias : public Module
                CommandBase::Params pars;
                std::string command, token;
 
-               ss.GetToken(command);
-               while (ss.GetToken(token))
+               ss.GetMiddle(command);
+               while (ss.GetTrailing(token))
                {
                        pars.push_back(token);
                }
index f7d73ac4a25405a126d997ac88db3265ec10a182..fa78e833b7cb778ea56d286f0203b4e4840cd1b6 100644 (file)
@@ -576,22 +576,22 @@ FilterResult ModuleFilter::DecodeFilter(const std::string &data)
        std::string filteraction;
        FilterResult res;
        irc::tokenstream tokens(data);
-       tokens.GetToken(res.freeform);
-       tokens.GetToken(filteraction);
+       tokens.GetMiddle(res.freeform);
+       tokens.GetMiddle(filteraction);
        if (!StringToFilterAction(filteraction, res.action))
                throw ModuleException("Invalid action: " + filteraction);
 
        std::string filterflags;
-       tokens.GetToken(filterflags);
+       tokens.GetMiddle(filterflags);
        char c = res.FillFlags(filterflags);
        if (c != 0)
                throw ModuleException("Invalid flag: '" + std::string(1, c) + "'");
 
        std::string duration;
-       tokens.GetToken(duration);
+       tokens.GetMiddle(duration);
        res.duration = ConvToInt(duration);
 
-       tokens.GetToken(res.reason);
+       tokens.GetTrailing(res.reason);
 
        /* Hax to allow spaces in the freeform without changing the design of the irc protocol */
        for (std::string::iterator n = res.freeform.begin(); n != res.freeform.end(); n++)
index dc00d6ff3cf18d076be10e32da79cf94498f1012..b2967af3bd377bb7789f4f268cc98f598682a2eb 100644 (file)
@@ -512,11 +512,11 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, Comm
                irc::tokenstream ts(params.back());
 
                std::string srcstr;
-               ts.GetToken(srcstr);
+               ts.GetMiddle(srcstr);
                srcstr.erase(0, 1);
 
                std::string token;
-               ts.GetToken(token);
+               ts.GetMiddle(token);
 
                // See if it's a numeric being sent to the target via PUSH
                unsigned int numeric_number = 0;
@@ -545,10 +545,10 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, Comm
                        params.push_back(InspIRCd::Format("%03u", numeric_number));
 
                        // Ignore the nickname in the numeric in PUSH
-                       ts.GetToken(token);
+                       ts.GetMiddle(token);
 
                        // Rest of the tokens are the numeric parameters, add them to NUM
-                       while (ts.GetToken(token))
+                       while (ts.GetTrailing(token))
                                params.push_back(token);
                }
                else if ((token == "PRIVMSG") || (token == "NOTICE"))
@@ -557,7 +557,7 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, Comm
                        cmd.swap(token);
 
                        // Check if the PRIVMSG/NOTICE target is a nickname
-                       ts.GetToken(token);
+                       ts.GetMiddle(token);
                        if (token.c_str()[0] == '#')
                        {
                                ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Unable to translate PUSH %s to user %s from 1202 protocol server %s, target \"%s\"", cmd.c_str(), params[0].c_str(), this->MyRoot->GetName().c_str(), token.c_str());
@@ -565,7 +565,7 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, Comm
                        }
 
                        // Replace second parameter with the message
-                       ts.GetToken(params[1]);
+                       ts.GetTrailing(params[1]);
                }
                else
                {
index d9083016cc8d0b6d807aa599fe9c171df2260a97..3bc1fc71a0042cffcdf3bfda82703cb914988e6d 100644 (file)
@@ -42,7 +42,7 @@ void TreeSocket::Split(const std::string& line, std::string& prefix, std::string
 {
        irc::tokenstream tokens(line);
 
-       if (!tokens.GetToken(prefix))
+       if (!tokens.GetMiddle(prefix))
                return;
 
        if (prefix[0] == ':')
@@ -54,7 +54,7 @@ void TreeSocket::Split(const std::string& line, std::string& prefix, std::string
                        this->SendError("BUG (?) Empty prefix received: " + line);
                        return;
                }
-               if (!tokens.GetToken(command))
+               if (!tokens.GetMiddle(command))
                {
                        this->SendError("BUG (?) Empty command received: " + line);
                        return;
@@ -69,7 +69,7 @@ void TreeSocket::Split(const std::string& line, std::string& prefix, std::string
                this->SendError("BUG (?) Empty command received: " + line);
 
        std::string param;
-       while (tokens.GetToken(param))
+       while (tokens.GetTrailing(param))
        {
                params.push_back(param);
        }
index fe6dabca070a5144c74b953f5d0d0a2b42871a7b..90f9de9d2958f1a98e5b489b7b709478da9f6c1d 100644 (file)
@@ -166,7 +166,7 @@ class ModuleXLineDB : public Module
                        std::string command_p[7];
                        std::string tmp;
 
-                       while (tokens.GetToken(tmp) && (items < 7))
+                       while (tokens.GetTrailing(tmp) && (items < 7))
                        {
                                command_p[items] = tmp;
                                items++;