From 01f075111070103a57a2aeae0678e4f48fdde275 Mon Sep 17 00:00:00 2001 From: randomdan Date: Thu, 15 Jul 2010 19:16:04 +0000 Subject: Big ugly but working char separated values view --- project2/fileView.cpp | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ project2/fileView.h | 36 +++++++++++ project2/view.cpp | 2 + 3 files changed, 211 insertions(+) create mode 100644 project2/fileView.cpp create mode 100644 project2/fileView.h diff --git a/project2/fileView.cpp b/project2/fileView.cpp new file mode 100644 index 0000000..61a6059 --- /dev/null +++ b/project2/fileView.cpp @@ -0,0 +1,173 @@ +#include "fileView.h" +#include +#include + +_FileView::_FileView(const xmlpp::Element * p) : + _SourceObject(p), + _View(p), + path(p->get_attribute_value("path")), + fieldSep(p->get_attribute_value("fieldSeps")[0]), + quoteChar(p->get_attribute_value("quoteChars")[0]), + newline(p->get_attribute_value("newline")), + encoding(p->get_attribute_value("encoding")) +{ + BOOST_FOREACH(const xmlpp::Node * node, p->find("columns/column")) { + const xmlpp::Element * elem = dynamic_cast(node); + if (elem) { + columns.push_back(elem->get_child_text()->get_content()); + } + } +} + +_FileView::~_FileView() +{ +} + +class FileStrChannel : public Glib::IOChannel { + public: + FileStrChannel(FILE * f) : Glib::IOChannel(), file(f) + { + gobj()->is_seekable = 1; + gobj()->is_readable = 1; + gobj()->is_writeable = 0; + } + ~FileStrChannel() + { + if (file) + fclose(file); + } + virtual Glib::IOStatus close_vfunc() + { + if (file) { + fclose(file); + file = NULL; + } + return Glib::IO_STATUS_NORMAL; + } + virtual Glib::IOStatus set_flags_vfunc(Glib::IOFlags flags) + { + return Glib::IO_STATUS_NORMAL; + } + virtual Glib::IOFlags get_flags_vfunc() + { + return Glib::IO_FLAG_IS_SEEKABLE | Glib::IO_FLAG_IS_READABLE; + } + virtual Glib::IOStatus seek_vfunc(gint64 offset, Glib::SeekType type) + { + if (fseek(file, offset, type)) { + return Glib::IO_STATUS_ERROR; + } + return Glib::IO_STATUS_NORMAL; + } + virtual Glib::IOStatus read_vfunc(char* buf, gsize count, gsize& bytes_read) + { + bytes_read = fread(buf, 1, count, file); + if (bytes_read == 0) { + if (feof(file)) { + return Glib::IO_STATUS_EOF; + } + if (ferror(file)) { + return Glib::IO_STATUS_ERROR; + } + return Glib::IO_STATUS_AGAIN; + } + return Glib::IO_STATUS_NORMAL; + } + private: + FILE * file; +}; + +void +_FileView::execute(xmlpp::Element * par, const ApplicationEngine * ep, const _View * parent) const +{ + FILE * f = fopen(path.c_str(), "r"); + if (!f) { + throw std::runtime_error("Could not open file"); + } + FileStrChannel c(f); + c.set_encoding(encoding); + c.set_line_term(newline); + xmlpp::Element * set = par->add_child(name); + Glib::ustring line; + while (c.read_line(line) == Glib::IO_STATUS_NORMAL) { + line.erase(line.length() - newline.length()); + Columns::const_iterator curCol = columns.begin(); + bool mkCols = columns.empty(); + xmlpp::Element * recordNode = NULL; + if (!mkCols) { + recordNode = set->add_child(recordName); + } + bool inQuotes = false; + bool prevWasQuote = false; + Glib::ustring tok; + BOOST_FOREACH(gunichar c, line) { + if (c == quoteChar) { + if (prevWasQuote) { + tok += c; + prevWasQuote = false; + } + else { + inQuotes = !inQuotes; + prevWasQuote = true; + } + } + else if ((!inQuotes) && (c == fieldSep)) { + prevWasQuote = false; + if (mkCols) { + for (Glib::ustring::iterator i = tok.begin(); i != tok.end(); ) { + if (!isalnum(*i)) { + tok.erase(i); + } + else { + i++; + } + } + columns.push_back(tok); + } + else { + recordNode->add_child(*curCol)->set_child_text(tok); + record[*curCol] = tok; + curCol++; + } + tok.clear(); + } + else { + prevWasQuote = false; + tok += c; + } + } + if (tok.length()) { + if (mkCols) { + for (Glib::ustring::iterator i = tok.begin(); i != tok.end(); ) { + if (!isalnum(*i)) { + tok.erase(i); + } + else { + i++; + } + } + columns.push_back(tok); + } + else { + recordNode->add_child(*curCol)->set_child_text(tok); + record[*curCol] = tok; + curCol++; + } + } + if (!mkCols) { + while (curCol != columns.end()) { + recordNode->add_child(*curCol); + record[*curCol].clear(); + curCol++; + } + } + executeChildren(recordNode, ep, this); + } +} + +Glib::ustring +_FileView::getCurrentValue(const Glib::ustring & id) const +{ + return record[id]; +} + diff --git a/project2/fileView.h b/project2/fileView.h new file mode 100644 index 0000000..7b7ab9b --- /dev/null +++ b/project2/fileView.h @@ -0,0 +1,36 @@ +#ifndef FILEVIEW_H +#define FILEVIEW_H + +#include +#include +#include +#include "view.h" + +class ApplicationEngine; + +class _FileView : public _View { + public: + _FileView(const xmlpp::Element * p); + ~_FileView(); + void execute(xmlpp::Element *, const ApplicationEngine *, const _View * parent = NULL) const; + Glib::ustring getCurrentValue(const Glib::ustring & id) const; + + typedef std::set CharSet; + const Glib::ustring path; + + private: + gunichar fieldSep; + gunichar quoteChar; + std::string newline; + std::string encoding; + typedef std::vector Columns; + mutable Columns columns; + typedef std::map Record; + mutable Record record; +}; +typedef boost::shared_ptr<_FileView> FileView; +typedef std::map FileViews; + +#endif + + diff --git a/project2/view.cpp b/project2/view.cpp index 3a99aa6..e2ea7d9 100644 --- a/project2/view.cpp +++ b/project2/view.cpp @@ -3,6 +3,7 @@ #include "xmlObjectLoader.h" #include "sqlView.h" #include "rawView.h" +#include "fileView.h" _View::_View(const xmlpp::Element * p) : _SourceObject(p), @@ -19,6 +20,7 @@ _View::AddLoaders(Loaders & l, Views & views) { l.insert(LoadersVT("sqlview", _LoaderBase::Make<_SqlView, _View, std::string, _SourceObject, &_SourceObject::name>(&views))); l.insert(LoadersVT("rawview", _LoaderBase::Make<_RawView, _View, std::string, _SourceObject, &_SourceObject::name>(&views))); + l.insert(LoadersVT("fileview", _LoaderBase::Make<_FileView, _View, std::string, _SourceObject, &_SourceObject::name>(&views))); } void -- cgit v1.2.3