summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2010-07-15 19:16:04 +0000
committerrandomdan <randomdan@localhost>2010-07-15 19:16:04 +0000
commitacb942d007582484ec7ad1ddca022bf1c68491d1 (patch)
treee59cbb92f81399603baff743bdfcd833c76e5a14
parentSet the content-type header according to the existance of a stylesheet name (diff)
downloadproject2-acb942d007582484ec7ad1ddca022bf1c68491d1.tar.bz2
project2-acb942d007582484ec7ad1ddca022bf1c68491d1.tar.xz
project2-acb942d007582484ec7ad1ddca022bf1c68491d1.zip
Big ugly but working char separated values view
-rw-r--r--project2/fileView.cpp173
-rw-r--r--project2/fileView.h36
-rw-r--r--project2/view.cpp2
3 files changed, 211 insertions, 0 deletions
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 <stdexcept>
+#include <glibmm/iochannel.h>
+
+_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<const xmlpp::Element *>(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 <libxml++/nodes/element.h>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#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<gunichar> CharSet;
+ const Glib::ustring path;
+
+ private:
+ gunichar fieldSep;
+ gunichar quoteChar;
+ std::string newline;
+ std::string encoding;
+ typedef std::vector<Glib::ustring> Columns;
+ mutable Columns columns;
+ typedef std::map<Glib::ustring, Glib::ustring> Record;
+ mutable Record record;
+};
+typedef boost::shared_ptr<_FileView> FileView;
+typedef std::map<std::string, FileView> 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