diff options
-rw-r--r-- | src/Client/CommandParser.cpp | 3 | ||||
-rw-r--r-- | src/Common/ConfigManager.cpp | 72 | ||||
-rw-r--r-- | src/Common/Makefile.am | 4 | ||||
-rw-r--r-- | src/Common/Makefile.in | 8 | ||||
-rw-r--r-- | src/Common/Tokenizer.cpp | 125 | ||||
-rw-r--r-- | src/Common/Tokenizer.h (renamed from src/Common/Util.h) | 19 | ||||
-rw-r--r-- | src/Common/Util.cpp | 41 |
7 files changed, 178 insertions, 94 deletions
diff --git a/src/Client/CommandParser.cpp b/src/Client/CommandParser.cpp index ab3dd50..d75eb0a 100644 --- a/src/Client/CommandParser.cpp +++ b/src/Client/CommandParser.cpp @@ -28,6 +28,7 @@ #include <Common/Requests/FSInfoRequest.h> #include <Common/Requests/DisconnectRequest.h> #include <Common/Requests/StatusRequest.h> +#include <Common/Tokenizer.h> #include <Net/Packets/HostListPacket.h> #include <Net/Packets/HostStatusPacket.h> @@ -316,7 +317,7 @@ bool CommandParser::split(const std::string &str, std::vector<std::string> &ret) bool CommandParser::parse(const std::string &cmd) { std::vector<std::string> splitCmd; - split(cmd, splitCmd); + Common::Tokenizer::tokenize(cmd, splitCmd); if(splitCmd.empty()) return true; diff --git a/src/Common/ConfigManager.cpp b/src/Common/ConfigManager.cpp index bfb38a0..487e901 100644 --- a/src/Common/ConfigManager.cpp +++ b/src/Common/ConfigManager.cpp @@ -21,7 +21,7 @@ #include "ConfigEntry.h" #include "Configurable.h" #include "Logger.h" -#include "Util.h" +#include "Tokenizer.h" #include <fstream> #include <stdexcept> @@ -55,67 +55,61 @@ void ConfigManager::handleConfigEntry(const ConfigEntry &entry) { bool ConfigManager::loadFile(const std::string &filename, bool finish) { std::ifstream file(filename.c_str()); ConfigEntry entry; - std::vector<std::string> subEntry; - std::string line; + std::string line, input; + char delim; + std::vector<std::string> splitLine, lastConfigLine; if(!file.good()) return false; - while(!(file.eof() && line.empty())) { - std::string nextLine; - char bracket = 0; + while(!(file.eof() && line.empty() && input.empty())) { + while(input.empty() && !file.eof()) + std::getline(file, input); - if(line.empty()) { - std::getline(file, line); + if(input.empty()) + break; - size_t pos = line.find_first_of('#'); - if(pos != std::string::npos) - line = line.substr(0, pos); - - line = Util::trim(line); - - if(line.empty()) - continue; + size_t pos = input.find_first_of("#{}"); + if(pos == std::string::npos) { + line += input; + delim = 0; + input.clear(); + } + else { + line += input.substr(0, pos); + delim = input[pos]; + input = input.substr(pos+1); } - size_t pos = line.find_first_of("{}"); + if(!Tokenizer::tokenize(line, splitLine)) { + if(delim) + line += delim; - if(pos != std::string::npos) { - bracket = line[pos]; - line = Util::trim(line.substr(0, pos)); - try { - nextLine = Util::trim(line.substr(pos+1)); - } - catch(std::out_of_range& e) {} + continue; } - if(!line.empty()) { + if(!splitLine.empty()) { pos = line.find_first_of(" \t"); - subEntry.clear(); - - if(pos == std::string::npos) { - subEntry.push_back(line); - } - else { - subEntry.push_back(line.substr(0, pos)); - subEntry.push_back(Util::trim(line.substr(pos))); - } - - entry.push(subEntry); + entry.push(splitLine); handleConfigEntry(entry); entry.pop(); + + lastConfigLine = splitLine; } - switch(bracket) { + switch(delim) { + case '#': + input.clear(); + break; case '{': - entry.push(subEntry); + entry.push(lastConfigLine); break; case '}': entry.pop(); } - line = nextLine; + line.clear(); } // TODO Depth check diff --git a/src/Common/Makefile.am b/src/Common/Makefile.am index 0e82f18..7cfa0d4 100644 --- a/src/Common/Makefile.am +++ b/src/Common/Makefile.am @@ -1,8 +1,8 @@ SUBDIRS = Backends Requests RequestHandlers noinst_LTLIBRARIES = libcommon.la -libcommon_la_SOURCES = ConfigEntry.cpp ConfigManager.cpp Configurable.cpp Exception.cpp Logger.cpp RemoteLogger.cpp RequestManager.cpp SystemBackend.cpp Util.cpp +libcommon_la_SOURCES = ConfigEntry.cpp ConfigManager.cpp Configurable.cpp Exception.cpp Logger.cpp RemoteLogger.cpp RequestManager.cpp SystemBackend.cpp Tokenizer.cpp libcommon_la_LIBADD = Backends/libbackends.la Requests/librequests.la RequestHandlers/librequesthandlers.la noinst_HEADERS = ConfigEntry.h ConfigManager.h Configurable.h Exception.h HostInfo.h Logger.h LoggerBase.h RemoteLogger.h Request.h RequestBase.h \ - RequestHandler.h RequestManager.h SystemBackend.h Util.h + RequestHandler.h RequestManager.h SystemBackend.h Tokenizer.h diff --git a/src/Common/Makefile.in b/src/Common/Makefile.in index a030c7e..37a874d 100644 --- a/src/Common/Makefile.in +++ b/src/Common/Makefile.in @@ -51,7 +51,7 @@ libcommon_la_DEPENDENCIES = Backends/libbackends.la \ Requests/librequests.la RequestHandlers/librequesthandlers.la am_libcommon_la_OBJECTS = ConfigEntry.lo ConfigManager.lo \ Configurable.lo Exception.lo Logger.lo RemoteLogger.lo \ - RequestManager.lo SystemBackend.lo Util.lo + RequestManager.lo SystemBackend.lo Tokenizer.lo libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -201,10 +201,10 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = Backends Requests RequestHandlers noinst_LTLIBRARIES = libcommon.la -libcommon_la_SOURCES = ConfigEntry.cpp ConfigManager.cpp Configurable.cpp Exception.cpp Logger.cpp RemoteLogger.cpp RequestManager.cpp SystemBackend.cpp Util.cpp +libcommon_la_SOURCES = ConfigEntry.cpp ConfigManager.cpp Configurable.cpp Exception.cpp Logger.cpp RemoteLogger.cpp RequestManager.cpp SystemBackend.cpp Tokenizer.cpp libcommon_la_LIBADD = Backends/libbackends.la Requests/librequests.la RequestHandlers/librequesthandlers.la noinst_HEADERS = ConfigEntry.h ConfigManager.h Configurable.h Exception.h HostInfo.h Logger.h LoggerBase.h RemoteLogger.h Request.h RequestBase.h \ - RequestHandler.h RequestManager.h SystemBackend.h Util.h + RequestHandler.h RequestManager.h SystemBackend.h Tokenizer.h all: all-recursive @@ -265,7 +265,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RemoteLogger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SystemBackend.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Tokenizer.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/Common/Tokenizer.cpp b/src/Common/Tokenizer.cpp new file mode 100644 index 0000000..1d7462f --- /dev/null +++ b/src/Common/Tokenizer.cpp @@ -0,0 +1,125 @@ +/* + * Tokenizer.cpp + * + * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Tokenizer.h" + +#include <iostream> + +namespace Mad { +namespace Common { + +const std::string Tokenizer::delimiters = " \t\n\"'\\"; + + +std::vector<std::string> Tokenizer::split(const std::string &str) { + std::vector<std::string> ret; + + for(size_t s = 0; s < str.length();) { + size_t index = str.find_first_of(delimiters, s); + size_t length = (index == std::string::npos) ? std::string::npos : index-s; + + ret.push_back(str.substr(s, length)); + + if(index != std::string::npos) { + size_t index2 = str.find_first_not_of(delimiters, index); + + length = (index2 == std::string::npos) ? std::string::npos : index2-index; + + ret.push_back(str.substr(index, length)); + + if(index2 != std::string::npos) + s = index2; + else + break; + } + else + break; + } + + return ret; +} + +bool Tokenizer::tokenize(const std::string &str, std::vector<std::string> &out) { + std::vector<std::string> splitString = split(str); + + bool singleQuotes = false, doubleQuotes = false, escape = false; + std::string token; + bool forceToken = false; + + out.clear(); + + for(std::vector<std::string>::iterator s = splitString.begin(); s != splitString.end(); ++s) { + token += *s; + escape = false; + + if(++s == splitString.end()) + break; + + for(std::string::iterator c = s->begin(); c != s->end(); ++c) { + if(escape || (singleQuotes && *c != '\'')) { + token += *c; + escape = false; + continue; + } + + switch(*c) { + case ' ': + case '\t': + case '\n': + if(doubleQuotes) { + token += *c; + } + else { + if(!token.empty() || forceToken) { + out.push_back(token); + token.clear(); + forceToken = false; + } + } + break; + + case '"': + doubleQuotes = !doubleQuotes; + forceToken = true; + break; + + case '\'': + if(doubleQuotes) { + token += *c; + } + else { + singleQuotes = !singleQuotes; + forceToken = true; + } + break; + + case '\\': + escape = true; + } + } + } + + if(!token.empty() || forceToken) + out.push_back(token); + + return !(singleQuotes || doubleQuotes || escape); +} + +} +} diff --git a/src/Common/Util.h b/src/Common/Tokenizer.h index ec31beb..6b8436b 100644 --- a/src/Common/Util.h +++ b/src/Common/Tokenizer.h @@ -1,5 +1,5 @@ /* - * Util.h + * Tokenizer.h * * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> * @@ -17,23 +17,28 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef MAD_COMMON_UTIL_H_ -#define MAD_COMMON_UTIL_H_ +#ifndef MAD_COMMON_TOKENIZER_H_ +#define MAD_COMMON_TOKENIZER_H_ #include <string> +#include <vector> namespace Mad { namespace Common { -class Util { +class Tokenizer { private: - Util(); + static const std::string delimiters; + + Tokenizer(); + + static std::vector<std::string> split(const std::string &str); public: - static std::string trim(const std::string &str); + static bool tokenize(const std::string &str, std::vector<std::string> &out); }; } } -#endif /* MAD_COMMON_UTIL_H_ */ +#endif /* MAD_COMMON_TOKENIZER_H_ */ diff --git a/src/Common/Util.cpp b/src/Common/Util.cpp deleted file mode 100644 index f34aa1e..0000000 --- a/src/Common/Util.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Util.cpp - * - * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "Util.h" - -namespace Mad { -namespace Common { - -std::string Util::trim(const std::string &str) { - size_t beg, end; - - beg = str.find_first_not_of(" \t"); - end = str.find_last_not_of(" \t"); - - if(beg == std::string::npos) - beg = 0; - - if(end != std::string::npos) - end = end-beg+1; - - return str.substr(beg, end); -} - -} -} |