summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <matthias@gamezock.de>2008-10-22 20:56:56 +0200
committerMatthias Schiffer <matthias@gamezock.de>2008-10-22 20:56:56 +0200
commit1226366351300139f2d8b7c10fee29d744591426 (patch)
treed8b927ce6a75370e741677cf59c1a4b00eab1f01
parent6bd58c61a1668d336f45443c602e850e965ad368 (diff)
downloadmad-1226366351300139f2d8b7c10fee29d744591426.tar
mad-1226366351300139f2d8b7c10fee29d744591426.zip
Alte Split-Funktion durch neuen Tokenizer ersetzt
-rw-r--r--src/Client/CommandParser.cpp3
-rw-r--r--src/Common/ConfigManager.cpp72
-rw-r--r--src/Common/Makefile.am4
-rw-r--r--src/Common/Makefile.in8
-rw-r--r--src/Common/Tokenizer.cpp125
-rw-r--r--src/Common/Tokenizer.h (renamed from src/Common/Util.h)19
-rw-r--r--src/Common/Util.cpp41
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);
-}
-
-}
-}