From d7f2452e20b04d1559b7bdd3aa49b6fbf7d0abaf Mon Sep 17 00:00:00 2001 From: Gert van Valkenhoef Date: Tue, 8 Nov 2011 22:18:05 +0000 Subject: [PATCH] Completely convert .odc to .txt using Visitor --- Makefile | 2 +- alien.cc | 18 +++++------ alien.h | 9 +++--- fold.cc | 13 +++++--- fold.h | 9 +++--- odcread.cc | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++- store.cc | 5 ++- store.h | 7 ++++- textmodel.cc | 36 ++++++++++++++-------- textmodel.h | 20 ++++++------ visitor.h | 45 +++++++++++++++++++++++++++ 11 files changed, 199 insertions(+), 51 deletions(-) create mode 100644 visitor.h diff --git a/Makefile b/Makefile index e3f74e5..4ad7260 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -HEADERS=oberon.h store.h reader.h domain.h alien.h typeregister.h textmodel.h fold.h +HEADERS=oberon.h store.h reader.h domain.h alien.h typeregister.h textmodel.h fold.h visitor.h odcread: odcread.o reader.o store.o util.o alien.o typeregister.o textmodel.o fold.o g++ -o $@ $^ diff --git a/alien.cc b/alien.cc index fddd202..dc4f509 100644 --- a/alien.cc +++ b/alien.cc @@ -8,8 +8,7 @@ std::string AlienPiece::toString() { return std::string("AlienPiece"); } -std::string AlienPiece::toPlainText() { - return std::string(); +void AlienPiece::accept(Visitor &visitor) const { } AlienPart::AlienPart(Store * const store): d_store(store) {} @@ -21,11 +20,10 @@ std::string AlienPart::toString() { return "NULL"; } -std::string AlienPart::toPlainText() { - if (d_store != 0) - return d_store->toPlainText(); - else - return std::string(); +void AlienPart::accept(Visitor &visitor) const { + if (d_store != 0) { + d_store->accept(visitor); + } } Alien::Alien(INTEGER id, const TypePath &path): Store(id), d_path(path), d_comps() {} @@ -42,12 +40,10 @@ std::string Alien::toString() { return sofar + "}"; } -std::string Alien::toPlainText() { - std::string sofar = std::string(); +void Alien::accept(Visitor &visitor) const { for (int i = 0; i < d_comps.size(); ++i) { - sofar += d_comps[i]->toPlainText(); + d_comps[i]->accept(visitor); } - return sofar; } } diff --git a/alien.h b/alien.h index 7447f95..9f061dc 100644 --- a/alien.h +++ b/alien.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,7 @@ namespace odc { */ struct AlienComponent { virtual std::string toString() = 0; - virtual std::string toPlainText() = 0; + virtual void accept(Visitor &visitor) const = 0; }; /** @@ -27,7 +28,7 @@ struct AlienPiece : public AlienComponent { AlienPiece(const char * const data, const size_t len); virtual std::string toString(); - virtual std::string toPlainText(); + virtual void accept(Visitor &visitor) const; }; /** @@ -39,7 +40,7 @@ struct AlienPart : public AlienComponent { AlienPart(Store * const store); virtual std::string toString(); - virtual std::string toPlainText(); + virtual void accept(Visitor &visitor) const; }; class Alien : public Store { @@ -57,7 +58,7 @@ class Alien : public Store { // comps-: AlienComp (** the constituent components of this alien store **) virtual std::string toString(); - virtual std::string toPlainText(); + virtual void accept(Visitor &visitor) const; }; } diff --git a/fold.cc b/fold.cc index ae4d016..37e0fd6 100644 --- a/fold.cc +++ b/fold.cc @@ -51,7 +51,8 @@ void Fold::internalize(Reader &reader) { // rd.ReadXInt(xint);fold.leftSide := xint = 0; reader.readSInt(); // rd.ReadXInt(xint); fold.collapsed := xint = 0; - reader.readSInt(); + SHORTINT c = reader.readSInt(); + d_collapsed = (c == 0); // rd.ReadXString(fold.label); d_label = new SHORTCHAR[32]; reader.readSString(d_label); // the label @@ -70,11 +71,13 @@ std::string Fold::toString() { return std::string("Fold(left) \"") + std::string(d_label) + std::string("\" { ") + d_hidden->toString() + std::string(" }"); } -std::string Fold::toPlainText() { - if (d_hidden == 0) { - return std::string(); +void Fold::accept(Visitor &visitor) const { + if (d_hidden == 0) { // right part + visitor.foldRight(); + } else { // left part + visitor.foldLeft(d_collapsed); + d_hidden->accept(visitor); } - return std::string(d_label) + std::string("\n") + d_hidden->toPlainText(); } } // namespace odc diff --git a/fold.h b/fold.h index e53e06d..589b76b 100644 --- a/fold.h +++ b/fold.h @@ -1,5 +1,5 @@ -#ifndef _TEXTMODEL_H_ -#define _TEXTMODEL_H_ +#ifndef _FOLD_H_ +#define _FOLD_H_ #include #include @@ -27,6 +27,7 @@ namespace odc { Store *d_hidden; SHORTCHAR *d_label; + bool d_collapsed; public: Fold(INTEGER id); @@ -36,9 +37,9 @@ namespace odc { virtual void internalize(Reader &reader); virtual std::string toString(); - virtual std::string toPlainText(); + virtual void accept(Visitor &visitor) const; }; } -#endif +#endif // _FOLD_H_ diff --git a/odcread.cc b/odcread.cc index 151c861..4ba3680 100644 --- a/odcread.cc +++ b/odcread.cc @@ -5,8 +5,90 @@ #include #include #include +#include +#include namespace odc { + class Context { + public: + virtual void addPiece(std::string &piece) = 0; + virtual std::string getPlainText() const = 0; + }; + class PartContext : public Context { + private: + std::string d_text; + public: + virtual void addPiece(std::string &piece) { + d_text += piece; + } + virtual std::string getPlainText() const { + return d_text; + } + }; + class FoldContext : public Context { + private: + bool d_collapsed; + bool d_haveFirst; // flag that first part has been set + std::string d_firstPart; + std::string d_remainder; + public: + FoldContext(bool collapsed) : d_collapsed(collapsed), d_haveFirst(false) {} + virtual void addPiece(std::string &piece) { + if (!d_haveFirst) { + d_haveFirst = true; + d_firstPart = piece; + } else { + d_remainder += piece; + } + } + virtual std::string getPlainText() const { + if (d_collapsed) { + return std::string("##=>") + d_remainder + "\n" + d_firstPart +"##<="; + } else { + return std::string("##=>") + d_firstPart + "\n" + d_remainder +"##<="; + } + } + }; + + class MyVisitor : public Visitor { + private: + std::vector d_context; + + void terminateContext() { + Context *c = *(d_context.end() - 1); + d_context.erase(d_context.end() - 1); + if (d_context.size() == 0) { + std::cout << c->getPlainText() << std::endl; + } else { + std::string text = c->getPlainText(); + (*(d_context.end() - 1))->addPiece(text); + } + delete c; + } + + public: + virtual void partStart() { + d_context.push_back(new PartContext()); + } + virtual void partEnd() { + terminateContext(); + } + virtual void foldLeft(bool collapsed) { + d_context.push_back(new FoldContext(collapsed)); + } + virtual void foldRight() { + terminateContext(); + } + virtual void textShortPiece(const ShortPiece *piece) { + std::string text = piece->getText(); + (*(d_context.end() - 1))->addPiece(text); + } + virtual void textLongPiece(const LongPiece *piece) { + std::string text = piece->getText(); + (*(d_context.end() - 1))->addPiece(text); + } + }; + Store* importDocument(std::istream &is) { const INTEGER docTag = 0x6F4F4443; const INTEGER docVersion = 0; @@ -33,7 +115,9 @@ int main(int argc, char *argv[]) { // std::cout << s->toPlainText() << std::endl; // std::cout << std::endl << std::endl; - std::cout << s->toString() << std::endl; + odc::MyVisitor visitor; + s->accept(visitor); +// std::cout << s->toString() << std::endl; // std::cout << in.tellg() << " " << in.eof() << std::endl; // odc::TypePath path; diff --git a/store.cc b/store.cc index d03467c..4bbabf8 100644 --- a/store.cc +++ b/store.cc @@ -1,5 +1,6 @@ #include #include +#include #include @@ -65,9 +66,7 @@ std::string Store::toString() { return getTypeName(); } -std::string Store::toPlainText() { - return std::string(); -} +void Store::accept(Visitor &visitor) const {} const std::string Elem::TYPENAME("Stores.Elem^"); const TypeProxy Elem::PROXY; diff --git a/store.h b/store.h index 66e58b0..4e7360e 100644 --- a/store.h +++ b/store.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -130,7 +131,11 @@ namespace odc { // FIXME virtual std::string toString(); - virtual std::string toPlainText(); + + /** + * Receiving end of the Visitor pattern. + */ + virtual void accept(Visitor &visitor) const; private: void calcTypePath(TypePath * out, const std::string &name) const; diff --git a/textmodel.cc b/textmodel.cc index 977bd44..f9dbae2 100644 --- a/textmodel.cc +++ b/textmodel.cc @@ -157,12 +157,12 @@ std::string StdTextModel::toString() { return sofar + "}"; } -std::string StdTextModel::toPlainText() { - std::string sofar = ""; +void StdTextModel::accept(Visitor &visitor) const { + visitor.partStart(); for (int i = 0; i < d_pieces.size(); ++i) { - sofar += d_pieces[i]->toPlainText(); + d_pieces[i]->accept(visitor); } - return sofar; + visitor.partEnd(); } TextPiece::TextPiece(size_t len): d_len(len) {} @@ -178,14 +178,18 @@ void LongPiece::read(Reader &reader) { reader.readLChar(d_buf, d_len); } -std::string LongPiece::toString() { +std::string LongPiece::toString() const { return std::string("LongPiece(FIXME)");// + std::wstring((wchar_t*)d_buf) + std::string(")"); } -std::string LongPiece::toPlainText() { +std::string LongPiece::getText() const { return std::string("FIXME");// + std::wstring((wchar_t*)d_buf) + std::string(")"); } +void LongPiece::accept(Visitor &visitor) const { + visitor.textLongPiece(this); +} + ShortPiece::ShortPiece(size_t len): TextPiece(len) {} ShortPiece::~ShortPiece() { @@ -205,12 +209,20 @@ void ShortPiece::read(Reader &reader) { // delete buf; } -std::string ShortPiece::toString() { +std::string ShortPiece::toString() const { return std::string("ShortPiece(") + std::string(d_buf) + std::string(")"); } -std::string ShortPiece::toPlainText() { - return std::string(d_buf); +std::string ShortPiece::getText() const { + std::string str(d_buf); + for (std::string::iterator it = str.begin(); it < str.end(); ++it) { + if (*it == '\r') *it = '\n'; + } + return str; +} + +void ShortPiece::accept(Visitor &visitor) const { + visitor.textShortPiece(this); } ViewPiece::ViewPiece(Store *view): TextPiece(0), d_view(view) {} @@ -219,12 +231,12 @@ void ViewPiece::read(Reader &reader) { reader.readByte(); } -std::string ViewPiece::toString() { +std::string ViewPiece::toString() const { return std::string("ViewPiece { ") + d_view->toString() + " }"; } -std::string ViewPiece::toPlainText() { - return d_view->toPlainText(); +void ViewPiece::accept(Visitor &visitor) const { + return d_view->accept(visitor); } } // namespace odc diff --git a/textmodel.h b/textmodel.h index 38eb7c5..92d387a 100644 --- a/textmodel.h +++ b/textmodel.h @@ -25,8 +25,8 @@ namespace odc { const size_t d_len; TextPiece(size_t len); virtual void read(Reader &reader) = 0; - virtual std::string toString() = 0; - virtual std::string toPlainText() = 0; + virtual std::string toString() const = 0; + virtual void accept(Visitor &visitor) const = 0; }; class LongPiece : public TextPiece { @@ -36,8 +36,9 @@ namespace odc { LongPiece(size_t len); ~LongPiece(); virtual void read(Reader &reader); - virtual std::string toString(); - virtual std::string toPlainText(); + virtual std::string toString() const; + virtual std::string getText() const; + virtual void accept(Visitor &visitor) const; }; class ShortPiece : public TextPiece { @@ -47,8 +48,9 @@ namespace odc { ShortPiece(size_t len); ~ShortPiece(); virtual void read(Reader &reader); - virtual std::string toString(); - virtual std::string toPlainText(); + virtual std::string toString() const; + virtual std::string getText() const; + virtual void accept(Visitor &visitor) const; }; class ViewPiece : public TextPiece { @@ -56,8 +58,8 @@ namespace odc { public: ViewPiece(Store *view); virtual void read(Reader &reader); - virtual std::string toString(); - virtual std::string toPlainText(); + virtual std::string toString() const; + virtual void accept(Visitor &visitor) const; }; class StdTextModel : public TextModel { @@ -74,7 +76,7 @@ namespace odc { virtual void internalize(Reader &reader); virtual std::string toString(); - virtual std::string toPlainText(); + virtual void accept(Visitor &visitor) const; }; } // namespace odc diff --git a/visitor.h b/visitor.h new file mode 100644 index 0000000..4b30261 --- /dev/null +++ b/visitor.h @@ -0,0 +1,45 @@ +#ifndef _VISITOR_H_ +#define _VISITOR_H_ + +namespace odc { + + class ShortPiece; + class LongPiece; + + /** + * Visitor role of the Visitor design pattern. + * Can be used to transform the document tree. + */ + class Visitor { + public: + /** + * A "part" that can contain other elements starts here. + * This can be an StdTextModel or a ViewPiece or another container. + */ + virtual void partStart() = 0; + /** + * A "part" ends here. + */ + virtual void partEnd() = 0; + /** + * A left fold has been found. + * If the fold is collapsed, the first part that follows is the + * "hidden" part, otherwise the first part that follows is the + * "alternative" text. The rest is the vice versa. + * This is the main reason we even need a visitor. + * @param collapsed true if the fold is in collapsed form. + */ + virtual void foldLeft(bool collapsed) = 0; + /** + * A right fold has been found. + */ + virtual void foldRight() = 0; + /** + * A text piece has been found. + */ + virtual void textShortPiece(const ShortPiece *piece) = 0; + virtual void textLongPiece(const LongPiece *piece) = 0; + }; +} + +#endif // _VISITOR_H_ -- 2.29.2