From: Peter Powell Date: Fri, 10 Aug 2018 06:46:42 +0000 (+0100) Subject: Split irc::tokenparser::GetToken into GetMiddle and GetTrailing. X-Git-Url: https://git.netwichtig.de/gitweb/?a=commitdiff_plain;h=8b418f081f7ecbfdd51c84fae2298f927155fac0;p=user%2Fhenk%2Fcode%2Finspircd.git Split irc::tokenparser::GetToken into GetMiddle and GetTrailing. This simplifies the logic of irc::tokenparser considerably and removes all of the magic index guessing that was used previously. --- diff --git a/include/hashcomp.h b/include/hashcomp.h index 9a3169435..b9c568135 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -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 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 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. diff --git a/src/command_parse.cpp b/src/command_parse.cpp index 97980112e..fb8ea2565 100644 --- a/src/command_parse.cpp +++ b/src/command_parse.cpp @@ -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); diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index d510e40b1..47c36b91b 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -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 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 token so it must be a token. + return GetMiddle(token); +} + irc::sepstream::sepstream(const std::string& source, char separator, bool allowempty) : tokens(source), sep(separator), pos(0), allow_empty(allowempty) { diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 433397123..76ccc6ebc 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -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); } diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index f7d73ac4a..fa78e833b 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -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++) diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp index dc00d6ff3..b2967af3b 100644 --- a/src/modules/m_spanningtree/compat.cpp +++ b/src/modules/m_spanningtree/compat.cpp @@ -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 { diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index d9083016c..3bc1fc71a 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -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); } diff --git a/src/modules/m_xline_db.cpp b/src/modules/m_xline_db.cpp index fe6dabca0..90f9de9d2 100644 --- a/src/modules/m_xline_db.cpp +++ b/src/modules/m_xline_db.cpp @@ -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++;