summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/cgi/cgiStagePresent.cpp4
-rw-r--r--project2/common/presenter.h2
-rw-r--r--project2/json/presenter.cpp52
-rw-r--r--project2/json/serialize.cpp51
-rw-r--r--project2/json/transformStream.cpp17
-rw-r--r--project2/xml/xmlPresenter.h2
6 files changed, 113 insertions, 15 deletions
diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp
index f1fd5e3..d8af5d9 100644
--- a/project2/cgi/cgiStagePresent.cpp
+++ b/project2/cgi/cgiStagePresent.cpp
@@ -37,8 +37,8 @@ CgiApplicationEngine::ResponseStage::ResponseStage(const CgiEnvironment * e) :
CgiApplicationEngine::HttpHeaderPtr
CgiApplicationEngine::PresentStage::getHeader() const
{
- ContentPresenter * cp = boost::dynamic_pointer_cast<ContentPresenter>(presenter).get();
- Project2HttpHeader * header = new Project2HttpHeader("200 OK", cp ? cp->contentType : "text/plain");
+ const ContentPresenter * cp = dynamic_cast<const ContentPresenter *>(presenter.get());
+ Project2HttpHeader * header = new Project2HttpHeader("200 OK", cp ? cp->contentType : "text/plain; charset=UTF-8");
header->addHeader("Cache-control", "no-cache");
return HttpHeaderPtr(header);
}
diff --git a/project2/common/presenter.h b/project2/common/presenter.h
index f7f447e..6a72495 100644
--- a/project2/common/presenter.h
+++ b/project2/common/presenter.h
@@ -62,7 +62,7 @@ class Presenter : public MultiRowSetPresenter {
void finishRowSet() const;
};
-class ContentPresenter : public Presenter {
+class ContentPresenter {
public:
ContentPresenter(const Glib::ustring & contentType);
const Glib::ustring contentType;
diff --git a/project2/json/presenter.cpp b/project2/json/presenter.cpp
new file mode 100644
index 0000000..25849b2
--- /dev/null
+++ b/project2/json/presenter.cpp
@@ -0,0 +1,52 @@
+#include "pch.hpp"
+#include "logger.h"
+#include "../common/presenter.h"
+#include "json.h"
+#include "conversion.h"
+#include "transform.h"
+#include <stack>
+
+class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf<json::Object> {
+ public:
+ JsonPresenter(const xmlpp::Element *) :
+ ContentPresenter("application/json; charset=UTF-8") {
+ curRowSet.push(&object);
+ }
+ void addNamedValue(const Glib::ustring & name, const VariableType & value) const {
+ (*curRowSet.top())[name] = json::ValuePtr(new json::Value(boost::apply_visitor(Project2ToJson(), value)));
+ }
+ void addNewRow(const Glib::ustring & name) const {
+ if (!curRowArray.top()) {
+ json::Value * v = new json::Value(json::Array());
+ curRowArray.top() = boost::get<json::Array>(v);
+ (*curRowSet.top())[name] = json::ValuePtr(v);
+ }
+ json::Value * v = new json::Value(json::Object());
+ curRowSet.push(boost::get<json::Object>(v));
+ curRowArray.top()->push_back(json::ValuePtr(v));
+ }
+ void finishRow() const {
+ curRowSet.pop();
+ }
+ void addNewRowSet(const Glib::ustring & name) const {
+ json::Value * v = new json::Value(json::Object());
+ (*curRowSet.top())[name] = json::ValuePtr(v);
+ curRowSet.push(boost::get<json::Object>(v));
+ curRowArray.push(NULL);
+ }
+ void addNewRowSet(const Glib::ustring & name, const Glib::ustring & ns) const {
+ addNewRowSet(ns + ":" + name);
+ }
+ void finishRowSet() const {
+ curRowArray.pop();
+ curRowSet.pop();
+ }
+ operator const json::Object *() const {
+ return &object;
+ }
+ private:
+ mutable json::Object object;
+ mutable std::stack<json::Object *> curRowSet;
+ mutable std::stack<json::Array *> curRowArray;
+};
+DECLARE_COMPONENT_LOADER("json", JsonPresenter, PresenterLoader)
diff --git a/project2/json/serialize.cpp b/project2/json/serialize.cpp
index f3245e9..5b9deb9 100644
--- a/project2/json/serialize.cpp
+++ b/project2/json/serialize.cpp
@@ -50,23 +50,52 @@ namespace json {
if (&v != &*a.begin()) {
s += ',';
}
- serializeValue(v, s);
+ serializeValue(*v, s);
}
s += ']';
}
void serializeString(const String & str, Glib::ustring & s) {
s += '"';
BOOST_FOREACH(gunichar c, str) {
- switch (c) {
- case '\\':
- s += "\\\\";
- break;
- case '"':
- s += "\\\"";
- break;
- default:
- s += c;
- break;
+ if (c < 32) {
+ switch (c) {
+ case '\f':
+ s += "\\f";
+ break;
+ case '\t':
+ s += "\\t";
+ break;
+ case '\n':
+ s += "\\n";
+ break;
+ case '\b':
+ s += "\\b";
+ break;
+ case '\r':
+ s += "\\r";
+ break;
+ default:
+ char buf[7];
+ snprintf(buf, sizeof(buf), "\\u%04x", c);
+ s += buf;
+ break;
+ }
+ }
+ else {
+ switch (c) {
+ case '/':
+ s += "\\/";
+ break;
+ case '\\':
+ s += "\\\\";
+ break;
+ case '"':
+ s += "\\\"";
+ break;
+ default:
+ s += c;
+ break;
+ }
}
}
s += '"';
diff --git a/project2/json/transformStream.cpp b/project2/json/transformStream.cpp
new file mode 100644
index 0000000..f9537ea
--- /dev/null
+++ b/project2/json/transformStream.cpp
@@ -0,0 +1,17 @@
+#include <pch.hpp>
+#include "transform.h"
+#include "logger.h"
+#include "json.h"
+#include "ostreamWrapper.h"
+
+class TransformJsonToHttpStream : public TransformImpl<json::Object, ostreamWrapper> {
+ public:
+ void transform(const json::Object * obj, ostreamWrapper * o) const
+ {
+ Glib::ustring str = json::serializeObject(*obj);
+ o->strm << str.raw();
+ }
+};
+DECLARE_TRANSFORM(TransformJsonToHttpStream);
+
+
diff --git a/project2/xml/xmlPresenter.h b/project2/xml/xmlPresenter.h
index bfb3375..4f3fdbb 100644
--- a/project2/xml/xmlPresenter.h
+++ b/project2/xml/xmlPresenter.h
@@ -8,7 +8,7 @@ namespace xmlpp {
class Document;
}
-class XmlPresenter : public ContentPresenter, public SourceOf<xmlpp::Document>, public SourceOf<xmlDoc>, public SourceOf<boost::shared_ptr<xmlpp::Document> > {
+class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<xmlpp::Document>, public SourceOf<xmlDoc>, public SourceOf<boost::shared_ptr<xmlpp::Document> > {
public:
typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr;
XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & contentType);