From 6e76c4540e37280d0c161e7d7035e2e9022b18ce Mon Sep 17 00:00:00 2001 From: deva Date: Wed, 26 Mar 2008 13:04:30 +0000 Subject: Implemented a SAXPaser class, and made the macro and xml parsers use it. --- server/src/Makefile.am | 2 + server/src/macro_parser.cc | 145 +++++++++++++-------------------------------- server/src/macro_parser.h | 20 ++++++- server/src/sax_parser.cc | 125 ++++++++++++++++++++++++++++++++++++++ server/src/sax_parser.h | 50 ++++++++++++++++ server/src/server.cc | 9 ++- server/src/xmlparser.cc | 79 ++++-------------------- server/src/xmlparser.h | 17 +++++- 8 files changed, 271 insertions(+), 176 deletions(-) create mode 100644 server/src/sax_parser.cc create mode 100644 server/src/sax_parser.h (limited to 'server/src') diff --git a/server/src/Makefile.am b/server/src/Makefile.am index f145250..f06cbb9 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -15,6 +15,7 @@ pracrod_SOURCES = \ log.cc \ macro_parser.cc \ resumeparser.cc \ + sax_parser.cc \ server.cc \ tcpsocket.cc \ tostring.cc \ @@ -32,6 +33,7 @@ EXTRA_DIST = \ macro.h \ macro_parser.h \ resumeparser.h \ + sax_parser.h \ server.h \ tcpsocket.h \ tostring.h \ diff --git a/server/src/macro_parser.cc b/server/src/macro_parser.cc index aba7fda..84572d3 100644 --- a/server/src/macro_parser.cc +++ b/server/src/macro_parser.cc @@ -37,47 +37,41 @@ #include #include -#include -#include -#include - -class MacroParser { -public: - Macro *macro; - std::vector< Widget* > stack; - bool done; -}; - -static void start_hndl(void *p, const char *el, const char **attr) +MacroParser::MacroParser(std::string name, Macro ¯o) { - MacroParser *parser = (MacroParser*)XML_GetUserData(p); - - // printf("Start tag [%s]\n", el); + this->macro = ¯o; - // Convert to comfy C++ values... - std::string name = el; - std::map< std::string, std::string > attributes; - - while(*attr) { - std::string at_name = *attr; - attr++; - std::string at_value = *attr; - attr++; + std::string macrofile = std::string(XML) + "/" + name + ".xml"; + fd = open(macrofile.c_str(), O_RDONLY); - attributes.insert(make_pair(at_name, at_value)); + if(fd == -1) { + printf("Cannot open file \"%s\"...", macrofile.c_str()); + printf("failed!\n"); + return; } +} - // Do something reasonable with them... +MacroParser::~MacroParser() +{ + if(fd != -1) close(fd); +} - if(name == "include") { +int MacroParser::readData(char *data, size_t size) +{ + return read(fd, data, size); +} +void MacroParser::startTag(std::string name, std::map< std::string, std::string> attributes) +{ + if(name == "include") { Macro inc; - parse_macro(attributes["name"], inc); + MacroParser parser(attributes["name"], inc); + parser.parse(); WidgetList::iterator w = inc.widgets.front().widgets.begin(); while(w != inc.widgets.front().widgets.end()) { - parser->stack.back()->widgets.push_back(*w); + stack.back()->widgets.push_back(*w); w++; } @@ -86,9 +80,9 @@ static void start_hndl(void *p, const char *el, const char **attr) if(name == "macro") { - parser->macro->name = attributes["name"]; - parser->macro->version = attributes["version"]; - parser->macro->format = attributes["resume"]; + macro->name = attributes["name"]; + macro->version = attributes["version"]; + macro->format = attributes["resume"]; return; // Don't do further parsing of this tag. } @@ -110,14 +104,14 @@ static void start_hndl(void *p, const char *el, const char **attr) Widget macrolist; Widget *wp; - if(parser->stack.size() > 0) {// We only pushback the child if there is a parent. - parser->stack.back()->widgets.push_back(macrolist); - wp = &parser->stack.back()->widgets.back(); + if(stack.size() > 0) {// We only pushback the child if there is a parent. + stack.back()->widgets.push_back(macrolist); + wp = &stack.back()->widgets.back(); } else { - parser->macro->widgets.push_back(macrolist); - wp = &parser->macro->widgets.back(); + macro->widgets.push_back(macrolist); + wp = ¯o->widgets.back(); } - parser->stack.push_back(wp); + stack.push_back(wp); wp->type = "listbox"; wp->properties["name"] = attributes["name"]; @@ -187,82 +181,25 @@ static void start_hndl(void *p, const char *el, const char **attr) Widget *wp; - if(parser->stack.size() > 0) {// We only pushback the child if there is a parent. - parser->stack.back()->widgets.push_back(widget); - wp = &parser->stack.back()->widgets.back(); + if(stack.size() > 0) {// We only pushback the child if there is a parent. + stack.back()->widgets.push_back(widget); + wp = &stack.back()->widgets.back(); } else { - parser->macro->widgets.push_back(widget); - wp = &parser->macro->widgets.back(); + macro->widgets.push_back(widget); + wp = ¯o->widgets.back(); } - parser->stack.push_back(wp); + stack.push_back(wp); std::map< std::string, std::string >::iterator i = attributes.begin(); while(i != attributes.end()) { - // WidgetProperty prop; - // prop.name = i->first; - // prop.value = i->second; - // wp->properties.push_back(prop); wp->properties[i->first] = i->second; i++; } } -static void end_hndl(void *p, const char *el) -{ - MacroParser *parser = (MacroParser*)XML_GetUserData(p); - - // printf("End tag [%s]\n", el); - - if(std::string("include") != el) parser->stack.pop_back(); - - if(!strcmp(el, "macro")) parser->done = true; -} - -void parse_macro(std::string name, Macro ¯o) +void MacroParser::endTag(std::string name) { - - XML_Parser p = XML_ParserCreate(NULL); - if (! p) { - fprintf(stderr, "Couldn't allocate memory for parser\n"); - // throw Exception(...); - return; - } - - MacroParser parser; - parser.macro = ¯o; - parser.done = false; - - XML_SetUserData(p, &parser); - XML_UseParserAsHandlerArg(p); - XML_SetElementHandler(p, start_hndl, end_hndl); - - std::string macrofile = std::string(XML) + "/" + name + ".xml"; - int fd = open(macrofile.c_str(), O_RDONLY); - - if(fd == -1) { - printf("Cannot open file \"%s\"...", macrofile.c_str()); - printf("failed!\n"); - return; - } - - while(!parser.done) { - char buf[32]; - int len; - - memset(buf, 0, sizeof(buf)); - len = read(fd, buf, sizeof(buf) - 1); - - parser.done = len == 0; - - if (! XML_Parse(p, buf, len, parser.done)) { - fprintf(stderr, "Parse error at line %d:\n%s\n", - XML_GetCurrentLineNumber(p), - XML_ErrorString(XML_GetErrorCode(p))); - // throw Exception(...); - return; - } - } - - // printf("%d requests\n", transaction.requests.size()); + if(name != "include") stack.pop_back(); + // if(!strcmp(el, "macro")) done = true; } diff --git a/server/src/macro_parser.h b/server/src/macro_parser.h index 9f701d4..248e586 100644 --- a/server/src/macro_parser.h +++ b/server/src/macro_parser.h @@ -29,8 +29,26 @@ #include +#include "sax_parser.h" #include "macro.h" -void parse_macro(std::string name, Macro ¯o); +class MacroParser : public SAXParser { +public: + MacroParser(std::string name, Macro ¯o); + ~MacroParser(); + + void startTag(std::string name, std::map< std::string, std::string> attributes); + void endTag(std::string name); + +protected: + int readData(char *data, size_t size); + +private: + Macro *macro; + std::vector< Widget* > stack; + bool done; + + int fd; +}; #endif/*__PRACRO_MACRO_PARSER_H__*/ diff --git a/server/src/sax_parser.cc b/server/src/sax_parser.cc new file mode 100644 index 0000000..dd0a7a3 --- /dev/null +++ b/server/src/sax_parser.cc @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * sax_parser.cc + * + * Mon Mar 24 14:40:15 CET 2008 + * Copyright 2008 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup + * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro 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 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "sax_parser.h" + +static void start_hndl(void *p, const char *el, const char **attr) +{ + SAXParser *parser = (SAXParser*)XML_GetUserData(p); + + // Convert to comfy C++ values... + std::string name = el; + std::map< std::string, std::string > attributes; + + while(*attr) { + std::string at_name = *attr; + attr++; + std::string at_value = *attr; + attr++; + + attributes.insert(make_pair(at_name, at_value)); + } + + parser->startTag(name, attributes); +} + +static void end_hndl(void *p, const char *el) +{ + SAXParser *parser = (SAXParser*)XML_GetUserData(p); + std::string name = el; + parser->endTag(name); +} + + +SAXParser::SAXParser() +{ + p = XML_ParserCreate(NULL); + if(!p) { + fprintf(stderr, "Couldn't allocate memory for parser\n"); + // throw Exception(...); + return; + } + + XML_SetUserData(p, this); + XML_UseParserAsHandlerArg(p); + XML_SetElementHandler(p, start_hndl, end_hndl); +} + +int SAXParser::parse() +{ + char buf[32]; + int len; + + do { + len = readData(buf, sizeof(buf) - 1); + if (! XML_Parse(p, buf, len, len == 0)) { + fprintf(stderr, "Parse error at line %d:\n%s\n", + XML_GetCurrentLineNumber(p), + XML_ErrorString(XML_GetErrorCode(p))); + return -1; + } + + memset(buf, 0, sizeof(buf)); + } while(len); + + return 0; +} + +#ifdef TEST_SAXPARSER +/** + * Compile with: g++ -DTEST_SAXPARSER sax_parser.cc -lexpat -otext_saxparser + * Run with: ./test_saxparser [xmlfile] + */ +#include +#include +#include + +class MyParser :public SAXParser { +public: + MyParser(char *file) { + fd = open(file, O_RDONLY); + } + + int readData(char *data, size_t size) { + return read(fd, data, size); + } + + void startTag(std::string name, std::map< std::string, std::string> attributes) + { + printf("<%s>\n", name.c_str()); + } + +private: + int fd; +}; + +int main(int argc, char *argv[]) { + if(argc < 2) return 1; + MyParser parser(argv[1]); + parser.parse(); +} + +#endif/*TEST_SAXPARSER*/ diff --git a/server/src/sax_parser.h b/server/src/sax_parser.h new file mode 100644 index 0000000..b6b48ba --- /dev/null +++ b/server/src/sax_parser.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * sax_parser.h + * + * Mon Mar 24 14:40:15 CET 2008 + * Copyright 2008 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup + * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro 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 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_SAX_PARSER_H__ +#define __PRACRO_SAX_PARSER_H__ + +#include +#include +#include + +class SAXParser { +public: + SAXParser(); + + int parse(); + + virtual void startTag(std::string name, std::map< std::string, std::string> attributes) {} + virtual void endTag(std::string name) {} + +protected: + virtual int readData(char *data, size_t size) { return 0; } + +private: + XML_Parser p; +}; + +#endif/*__PRACRO_SAX_PARSER_H__*/ diff --git a/server/src/server.cc b/server/src/server.cc index 2a4c882..930a6e7 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -81,7 +81,8 @@ static void connection(TCPSocket &socket) printf("Got connection...\n"); Transaction transaction; - parse(socket, transaction); + XMLParser parser(socket, transaction); + parser.parse(); socket.write("\n"); socket.write("\n"); @@ -94,7 +95,8 @@ static void connection(TCPSocket &socket) printf("Handling request for \"%s\"...", request.macro.c_str()); Macro macro; - parse_macro(request.macro, macro); + MacroParser parser(request.macro, macro); + parser.parse(); socket.write(" \n"); @@ -122,7 +124,8 @@ static void connection(TCPSocket &socket) db.post(transaction.user, transaction.cpr, now, commit); Macro macro; - parse_macro(commit.macro, macro); + MacroParser parser(commit.macro, macro); + parser.parse(); std::string resume = resume_parser(macro.format.c_str(), commit); diff --git a/server/src/xmlparser.cc b/server/src/xmlparser.cc index 6ef7338..71bb753 100644 --- a/server/src/xmlparser.cc +++ b/server/src/xmlparser.cc @@ -35,33 +35,8 @@ static bool done = false; -static void start_hndl(void *p, const char *el, const char **attr) +void XMLParser::startTag(std::string name, std::map< std::string, std::string> attributes) { - Transaction *transaction = (Transaction*)XML_GetUserData(p); - - // printf("Start tag [%s]\n", el); - - // Convert to comfy C++ values... - std::string name = el; - std::map< std::string, std::string > attributes; - - while(*attr) { - std::string at_name = *attr; - attr++; - std::string at_value = *attr; - attr++; - - attributes.insert(make_pair(at_name, at_value)); - } - /* - std::map< std::string, std::string >::iterator i = attributes.begin(); - while(i != attributes.end()) { - printf("%s=%s\n", i->first.c_str(), i->second.c_str()); - i++; - } - */ - - // Do something reasonable with them... if(name == "pracro") { transaction->user = attributes["user"]; transaction->cpr = attributes["cpr"]; @@ -82,54 +57,24 @@ static void start_hndl(void *p, const char *el, const char **attr) } if(name == "field") { - // Field f; - // f.name = attributes["name"]; - // f.value = attributes["value"]; - // transaction->commits.back().fields.push_back(f); transaction->commits.back().fields[attributes["name"]] = attributes["value"]; - // printf("[%s]=[%s]\n", f.name.c_str(), f.value.c_str()); } - } -static void end_hndl(void *p, const char *el) +void XMLParser::endTag(std::string name) { - // printf("End tag [%s]\n", el); - if(!strcmp(el, "pracro")) done = true; + if(name == "pracro") done = true; } -void parse(TCPSocket &socket, Transaction &transaction) +int XMLParser::readData(char *data, size_t size) { + if(done) return 0; + return socket->read(data, size); +} - XML_Parser p = XML_ParserCreate(NULL); - if (! p) { - fprintf(stderr, "Couldn't allocate memory for parser\n"); - // throw Exception(...); - return; - } - - XML_SetUserData(p, &transaction); - XML_UseParserAsHandlerArg(p); - XML_SetElementHandler(p, start_hndl, end_hndl); - - while(!done) { - char buf[32]; - int len; - - memset(buf, 0, sizeof(buf)); - len = socket.read(buf, sizeof(buf) - 1); - - done = len == 0; - - if (! XML_Parse(p, buf, len, done)) { - fprintf(stderr, "Parse error at line %d:\n%s\n", - XML_GetCurrentLineNumber(p), - XML_ErrorString(XML_GetErrorCode(p))); - // throw Exception(...); - return; - } - } - - // printf("%d requests\n", transaction.requests.size()); - +XMLParser::XMLParser(TCPSocket &socket, Transaction &transaction) +{ + this->transaction = &transaction; + this->socket = &socket; + done = false; } diff --git a/server/src/xmlparser.h b/server/src/xmlparser.h index 8e6b7aa..30e6767 100644 --- a/server/src/xmlparser.h +++ b/server/src/xmlparser.h @@ -27,9 +27,24 @@ #ifndef __PRACRO_XMLPARSER_H__ #define __PRACRO_XMLPARSER_H__ +#include "sax_parser.h" #include "tcpsocket.h" #include "transaction.h" -void parse(TCPSocket &socket, Transaction &transaction); +class XMLParser : public SAXParser { +public: + XMLParser(TCPSocket &socket, Transaction &transaction); + + void startTag(std::string name, std::map< std::string, std::string> attributes); + void endTag(std::string name); + +protected: + int readData(char *data, size_t size); + +private: + Transaction *transaction; + TCPSocket *socket; + bool done; +}; #endif/*__PRACRO_XMLPARSER_H__*/ -- cgit v1.2.3