From 35278c38ab37293164cb195a3983b1568c07f8ef Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 29 Nov 2011 10:50:18 +0000 Subject: Make ContentPresenter a mix-in Add a JSON presenter Fix minor bugs in JSON serializer highlighter by new presenter --- project2/cgi/cgiStagePresent.cpp | 4 +-- project2/common/presenter.h | 2 +- project2/json/presenter.cpp | 52 +++++++++++++++++++++++++++++++++++++++ project2/json/serialize.cpp | 51 +++++++++++++++++++++++++++++--------- project2/json/transformStream.cpp | 17 +++++++++++++ project2/xml/xmlPresenter.h | 2 +- 6 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 project2/json/presenter.cpp create mode 100644 project2/json/transformStream.cpp 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(presenter).get(); - Project2HttpHeader * header = new Project2HttpHeader("200 OK", cp ? cp->contentType : "text/plain"); + const ContentPresenter * cp = dynamic_cast(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 + +class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf { + 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(v); + (*curRowSet.top())[name] = json::ValuePtr(v); + } + json::Value * v = new json::Value(json::Object()); + curRowSet.push(boost::get(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(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 curRowSet; + mutable std::stack 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 +#include "transform.h" +#include "logger.h" +#include "json.h" +#include "ostreamWrapper.h" + +class TransformJsonToHttpStream : public TransformImpl { + 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, public SourceOf, public SourceOf > { +class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf, public SourceOf, public SourceOf > { public: typedef boost::shared_ptr XmlDocumentPtr; XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & contentType); -- cgit v1.2.3