diff options
-rw-r--r-- | baltisot-config.in | 4 | ||||
-rw-r--r-- | include/BString.h | 5 | ||||
-rw-r--r-- | include/ConfigFile.h | 27 | ||||
-rw-r--r-- | include/Makefile.am | 2 | ||||
-rw-r--r-- | include/SQL.h | 17 | ||||
-rw-r--r-- | lib/ConfigFile.cc | 43 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/SQL.cc | 61 | ||||
-rw-r--r-- | lib/String.cc | 28 |
9 files changed, 170 insertions, 19 deletions
diff --git a/baltisot-config.in b/baltisot-config.in index c9e846d..6262e8a 100644 --- a/baltisot-config.in +++ b/baltisot-config.in @@ -39,11 +39,11 @@ while test $# -gt 0; do echo @VERSION@ ;; --cflags) - echo -I@includedir@/Baltisot + echo -I@includedir@/Baltisot @CFLAGS@ @MYSQL_CFLAGS@ ;; --libs) libdirs="-L@libdir@" - echo $libdirs -lBaltisot @LIBS@ + echo $libdirs -lBaltisot @LIBS@ @MYSQL_LIBS@ ;; *) echo "${usage}" 1>&2 diff --git a/include/BString.h b/include/BString.h index b5a273f..4540e70 100644 --- a/include/BString.h +++ b/include/BString.h @@ -47,6 +47,9 @@ class String : public Base { ssize_t strrchr(char) const; ssize_t strstr(const String &) const; int strchrcnt(char) const; + String ltrim() const; + String rtrim() const; + String trim() const; String & operator=(const String &); String operator+(const String &) const; String & operator+=(const String &); @@ -73,6 +76,4 @@ std::istream & operator>>(std::istream &, String &); String operator+(const char *, const String &); -bool compare(String, String); - #endif diff --git a/include/ConfigFile.h b/include/ConfigFile.h new file mode 100644 index 0000000..8a7c34d --- /dev/null +++ b/include/ConfigFile.h @@ -0,0 +1,27 @@ +#ifndef __CONFIGFILE_H__ +#define __CONFIGFILE_H__ + +#include <Exceptions.h> +#include <Handle.h> +#include <map> + +namespace BConfigFile { + struct ltstr { + bool operator()(String s1, String s2) const { + return s1 < s2; + } + }; +}; + +typedef std::map<String, String, BConfigFile::ltstr> ConfigSectionContents; +typedef std::map<String, ConfigSectionContents, BConfigFile::ltstr> ConfigSection; + +class ConfigFile : public Base { + public: + ConfigFile(Handle *) throw (GeneralException); + ConfigSectionContents & operator[](String); + private: + ConfigSection c; +}; + +#endif diff --git a/include/Makefile.am b/include/Makefile.am index a84dd81..3fc5f29 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,6 +2,6 @@ pkginclude_HEADERS = \ Exceptions.h Handle.h BString.h Output.h Socket.h HttpServ.h Variables.h Menu.h \ Action.h Message.h Form.h Confirm.h Table.h IRC.h Task.h Buffer.h generic.h \ CopyJob.h ReadJob.h Regex.h TaskMan.h InPipe.h OutPipe.h Input.h Image.h \ -Main.h Color.h GMPString.h SQL.h +Main.h Color.h GMPString.h SQL.h ConfigFile.h noinst_HEADERS = gettext.h diff --git a/include/SQL.h b/include/SQL.h index ee28eb0..846afe2 100644 --- a/include/SQL.h +++ b/include/SQL.h @@ -1,20 +1,33 @@ #ifndef __SQL_H__ #define __SQL_H__ -#include <set> +#include <map> #include <mysql.h> #include <Exceptions.h> -//typedef AssocArray std::set<String, compare>; +namespace BMySQL { + struct ltstr { + bool operator()(String s1, String s2) const { + return s1 < s2; + } + }; +}; + +typedef std::map<String, String, BMySQL::ltstr> AssocArray; class SQLConnection : public Base { public: SQLConnection(String host, String user, String passwd, String db, int port = 3306, String socket = "", unsigned long clags = 0) throw (GeneralException); ~SQLConnection(); void query(String) throw (GeneralException); + int numrows(); + int numfields(); + AssocArray fetchrow(); private: MYSQL con; MYSQL_RES * res; + int nr, nf; + MYSQL_FIELD * fields; }; #endif diff --git a/lib/ConfigFile.cc b/lib/ConfigFile.cc new file mode 100644 index 0000000..85cbb00 --- /dev/null +++ b/lib/ConfigFile.cc @@ -0,0 +1,43 @@ +#include "ConfigFile.h" +#include "Regex.h" + +ConfigFile::ConfigFile(Handle * f) throw (GeneralException) { + Regex r("^\\[.*\\]$"), comment("^#.*$"), empty("^ *$"), line("^.*=.*$"); + bool started = false; + String s, section, key, value; + ConfigSectionContents contents; + int pos; + + while (!f->IsClosed()) { + (*f) >> s; + if (comment.Match(s) || empty.Match(s)) + continue; + if (r.Match(s)) { + if (!started) { + started = true; + } else { + c[section] = contents; + contents.clear(); + } + section = s.extract(1, s.strlen() - 2); + continue; + } + if (line.Match(s)) { + if (!started) { + throw GeneralException("Config file must begin with a section"); + } + pos = s.strchr('='); + key = s.extract(0, pos - 1).trim(); + value = s.extract(pos + 1).trim(); + contents[key] = value; + continue; + } + throw GeneralException("Invalid line: " + s); + } + + c[section] = contents; +} + +ConfigSectionContents & ConfigFile::operator[](String s) { + return c[s]; +} diff --git a/lib/Makefile.am b/lib/Makefile.am index c843753..29edcf1 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -9,4 +9,4 @@ libBaltisot_la_SOURCES = Action.cc Buffer.cc checkargs.c Confirm.cc CopyJob.cc \ datecalc.c Exceptions.cc Form.cc GMPString.cc Handle.cc HttpServ.cc Image.cc \ InPipe.cc Input.cc IRC.cc Main.cc Menu.cc Message.cc OutPipe.cc Output.cc \ ReadJob.cc Regex.cc Socket.cc String.cc Table.cc Task.cc TaskMan.cc \ -Variables.cc generic.cc fileutils.cc SQL.cc +Variables.cc generic.cc fileutils.cc SQL.cc ConfigFile.cc @@ -5,15 +5,17 @@ SQLConnection::SQLConnection(String host, String user, String passwd, unsigned long cflags) throw (GeneralException) : res(0) { mysql_init(&con); - char * p; - - if (!mysql_real_connect(&con, - p = ((ugly_string)(host)).p ? p : 0, - ((ugly_string)(user)).p, - ((ugly_string)(passwd)).p, - ((ugly_string)(db)).p, port, - ((ugly_string)(socket)).p, cflags)) { - throw GeneralException(String("Could not connect to MySQL host ") + p); + const char * phost = ((ugly_string) host).p; + const char * puser = ((ugly_string) user).p; + const char * ppasswd = ((ugly_string) passwd).p; + const char * pdb = ((ugly_string) db).p; + const char * psocket = ((ugly_string) socket).p; + + phost = *phost ? phost : 0; + psocket = *psocket ? psocket : 0; + + if (!mysql_real_connect(&con, phost, puser, ppasswd, pdb, port, psocket, cflags)) { + throw GeneralException("Could not connect to MySQL host " + host); } } @@ -22,4 +24,45 @@ SQLConnection::~SQLConnection() { } void SQLConnection::query(String q) throw(GeneralException) { + if (res) { + mysql_free_result(res); + } + + if (mysql_real_query(&con, ((ugly_string)q).p, q.strlen())) { + throw GeneralException(String("Couldn't run query ") + q); + } + + res = mysql_store_result(&con); + + if (res) { + nr = mysql_num_rows(res); + nf = mysql_num_fields(res); + fields = mysql_fetch_fields(res); + } else { + nr = 0; + nf = 0; + fields = 0; + } +} + +int SQLConnection::numrows() { + return nr; +} + +int SQLConnection::numfields() { + return nf; +} + +AssocArray SQLConnection::fetchrow() { + AssocArray r; + MYSQL_ROW row; + int i; + + row = mysql_fetch_row(res); + + for (i = 0; i < nf; i++) { + r[fields[i].name] = row[i]; + } + + return r; } diff --git a/lib/String.cc b/lib/String.cc index 402424c..f24dcca 100644 --- a/lib/String.cc +++ b/lib/String.cc @@ -475,6 +475,30 @@ String & String::tolower() { return *this; } -bool compare(String a, String b) { - return a < b; +String String::ltrim() const { + char * d = (char *) malloc(strlen() + 1), * p, * r; + int s; + + r = d; + + for (p = str; *p && *p == ' '; p++); + for (s = 0; *p; *(d++) = *(p++), s++); + *d = 0; + + return String(s, r); +} + +String String::rtrim() const { + char * d = strdup(), * r; + int s = strlen(); + + r = d; + + for (d += s - 1; s && (*d == ' '); *(d--) = 0, s--); + + return String(s, r); +} + +String String::trim() const { + return rtrim().ltrim(); } |