From 77f503bd6db90bd882e389ea977f02a2773e14f2 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Fri, 4 Oct 2019 16:35:57 +0300 Subject: Semi-working html. =) --- example/filter_html.cpp | 5 +- example/makefile | 2 +- src/file.hpp | 1 + src/html.cpp | 298 +++++++++++++++++++++++++++++++++++++++++++++++- src/html.hpp | 59 +++++++++- src/plain.hpp | 1 + src/texo.cpp | 10 ++ src/texo.hpp | 3 + 8 files changed, 369 insertions(+), 10 deletions(-) diff --git a/example/filter_html.cpp b/example/filter_html.cpp index ced8f5f..a1957c3 100644 --- a/example/filter_html.cpp +++ b/example/filter_html.cpp @@ -8,11 +8,10 @@ int main() TexoHTMLProducer producer(exporter); TexoHTMLImporter importer(producer); importer.PutStr( - "\n" + "

\n" "Some br:
\n" "

And paragraphs work well too...

\n" - "You can use some witchcraft.\n" + "You can use some

witchcraft.\n" ); return 0; - return 0; } diff --git a/example/makefile b/example/makefile index 5255f5b..39d4db7 100644 --- a/example/makefile +++ b/example/makefile @@ -2,7 +2,7 @@ # DEBUG = yes CC = g++ -EXAMPLES = plain_to_html +EXAMPLES = plain_to_html filter_html CFLAGS = -Wall ifeq '$(DEBUG)' 'yes' diff --git a/src/file.hpp b/src/file.hpp index 68e31cd..c867bcc 100644 --- a/src/file.hpp +++ b/src/file.hpp @@ -8,6 +8,7 @@ class TexoFileExporter: public TexoExporter { public: TexoFileExporter(FILE *file); void Put(const char c); + private: FILE *file; }; diff --git a/src/html.cpp b/src/html.cpp index c9e3cde..76e9fb9 100644 --- a/src/html.cpp +++ b/src/html.cpp @@ -1,5 +1,7 @@ #include "html.hpp" +#include + TexoHTMLProducer::TexoHTMLProducer(TexoExporter &exporter): TexoProducer(exporter) @@ -23,7 +25,7 @@ void TexoHTMLProducer::Put(const Texo &piece) case Texo::link_begin: BeginLink(piece); break; case Texo::link_end: exporter.PutStr(""); break; case Texo::image: Image(piece); break; - default: break; + default: break; } } @@ -55,11 +57,297 @@ void TexoHTMLProducer::Image(const Texo &piece) } -TexoHTMLImporter::TexoHTMLImporter(TexoProducer &producer): - TexoImporter(producer) +TexoHTMLStack::TexoHTMLStack(): next(0) +{} + +TexoHTMLStack::~TexoHTMLStack() +{ + if (next) { + while (next != this) { + Pop(); + } + } +} + +void TexoHTMLStack::Push(Texo::Type tag) +{ + if (next) { + TexoHTMLStack *buf = next; + next = new TexoHTMLStack; + next->next = buf; + next->tag = this->tag; + } else { + next = this; + } + this->tag = tag; +} + +Texo::Type TexoHTMLStack::Pop() +{ + if (next) { + Texo::Type res = tag; + if (next != this) { + TexoHTMLStack *buf = next; + tag = next->tag; + next = next->next; + delete buf; + } else { + next = 0; + } + return res; + } else { + return Texo::character; + } +} + + +TexoHTMLImporter::TexoHTMLImporter(TexoProducer &producer, bool is_autoclose): + TexoImporter(producer), state(text), is_closing(0), tag(Texo::character), + readed(0), readed_len(0), readed_size(0), is_autoclose(is_autoclose) {} +TexoHTMLImporter::~TexoHTMLImporter() +{ + ReadedClear(); +} + void TexoHTMLImporter::Put(const char c) -{ // TODO by automata - producer.Put(Texo(c)); +{ + if (c) { + switch (state) { + case text: state = Text(c); break; + case tag_open: state = TagOpen(c); break; + case tag_name: state = TagName(c); break; + case tag_param_skip: state = TagParamSkip(c); break; + case tag_param_pre: state = TagParamPre(c); break; + case tag_param: state = TagParam(c); break; + case tag_param_post: state = TagParamPost(c); break; + case tag_param_value_pre: state = TagParamValuePre(c); break; + case tag_param_value: state = TagParamValue(c); break; + case tag_param_value_quoted: state = TagParamValueQuoted(c); break; + default: break; + } + } else { + tag = Texo::character; + Close(); + } +} + +TexoHTMLImporter::State TexoHTMLImporter::Text(const char c) +{ + State st = text; + switch (c) { + case '<': st = tag_open; break; + case '>': producer.PutStr(">"); break; + default: producer.Put(Texo(c)); break; + } + return st; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagOpen(const char c) +{ + State st = tag_open; + switch (c) { + case '/': + is_closing = 1; + break; + case ' ': + st = text; + producer.PutStr("<"); + if (is_closing) { + producer.Put(Texo('/')); + } + producer.Put(Texo(' ')); + break; + case '>': + st = text; + producer.PutStr("<"); + if (is_closing) { + producer.Put(Texo('/')); + } + producer.PutStr(">"); + break; + default: + st = tag_name; + ReadedAdd(c); + break; + } + return st; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagName(const char c) +{ + State st = tag_name; + switch (c) { + case ' ': + st = tag_param_skip; + SetTag(); + break; + case '/': + st = tag_param_skip; + SetTag(); + break; + case '>': + st = text; + SetTag(); + if (tag) { + if (is_closing) { + Close(); + } else { + producer.Put(Texo(tag)); + } + } + is_closing = false; + break; + default: + ReadedAdd(c); + break; + } + return st; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParamSkip(const char c) +{ + State st = tag_param_skip; + switch (c) { + case '>': + st = text; + if (tag) { + if (is_closing) { + Close(); + } else { + producer.Put(Texo(tag)); + } + } + is_closing = false; + break; + default: + break; + } + return st; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParamPre(const char c) +{ + return text; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParam(const char c) +{ + return text; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParamPost(const char c) +{ + return text; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParamValuePre(const char c) +{ + return text; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParamValue(const char c) +{ + return text; +} + +TexoHTMLImporter::State TexoHTMLImporter::TagParamValueQuoted(const char c) +{ + return text; +} + +void TexoHTMLImporter::Close() +{ + Texo::Type current = opened.Pop(); + while ((current != tag) && current) { + producer.Put(Texo(current)); + current = opened.Pop(); + } + if (current) { + producer.Put(Texo(current)); + } +} + +void TexoHTMLImporter::SetTag() +{ + if (!strcmp(readed, "a")) { + if (is_closing) { + tag = Texo::link_end; + } else { + tag = Texo::link_begin; + opened.Push(Texo::link_end); + } + } else if (!strcmp(readed, "img")) { + tag = Texo::image; + } else if (!strcmp(readed, "b")) { + if (is_closing) { + tag = Texo::bold_end; + } else { + tag = Texo::bold_begin; + opened.Push(Texo::bold_end); + } + } else if (!strcmp(readed, "i")) { + if (is_closing) { + tag = Texo::italic_end; + } else { + tag = Texo::italic_begin; + opened.Push(Texo::italic_end); + } + } else if (!strcmp(readed, "del")) { + if (is_closing) { + tag = Texo::strike_end; + } else { + tag = Texo::strike_begin; + opened.Push(Texo::strike_end); + } + } else if (!strcmp(readed, "ins")) { + if (is_closing) { + tag = Texo::underline_end; + } else { + tag = Texo::underline_begin; + opened.Push(Texo::underline_end); + } + } else if (!strcmp(readed, "p")) { + if (is_closing) { + tag = Texo::paragraph_end; + } else { + tag = Texo::paragraph_begin; + opened.Push(Texo::paragraph_end); + } + } else if (!strcmp(readed, "br")) { + tag = Texo::newline; + } else { + tag = Texo::character; + } + ReadedClear(); +} + +void TexoHTMLImporter::ReadedAdd(const char c) +{ + if (readed_size == 0) { + readed_size = 2; + readed = new char[readed_size]; + } else if (readed_size - 1 == readed_len) { + char *buf = readed; + readed_size = readed_size << 1; + readed = new char[readed_size]; + for (int i = 0; i < readed_len; ++i) { + readed[i] = buf[i]; + } + delete buf; + } + ++readed_len; + readed[readed_len - 1] = c; + readed[readed_len] = 0; +} + +void TexoHTMLImporter::ReadedClear() +{ + readed_len = 0; + readed_size = 0; + if (readed) { + delete readed; + readed = 0; + } } diff --git a/src/html.hpp b/src/html.hpp index 265ee39..7a5a511 100644 --- a/src/html.hpp +++ b/src/html.hpp @@ -8,16 +8,73 @@ class TexoHTMLProducer: public TexoProducer { public: TexoHTMLProducer(TexoExporter &exporter); void Put(const Texo &piece); + private: void BeginLink(const Texo &piece); void Image(const Texo &piece); }; +class TexoHTMLStack { +public: + TexoHTMLStack(); + ~TexoHTMLStack(); + void Push(Texo::Type tag); + Texo::Type Pop(); + +private: + TexoHTMLStack *next; + Texo::Type tag; +}; + class TexoHTMLImporter: public TexoImporter { public: - TexoHTMLImporter(TexoProducer &producer); + TexoHTMLImporter(TexoProducer &producer, bool is_autoclose = true); + ~TexoHTMLImporter(); void Put(const char c); + +private: + bool is_autoclose; + + enum State { + text = 0, + tag_open, + tag_name, + tag_param_skip, + tag_param_pre, + tag_param, + tag_param_post, + tag_param_value_pre, + tag_param_value, + tag_param_value_quoted + } state; + + State Text(const char c); + State TagOpen(const char c); + State TagName(const char c); + State TagParamSkip(const char c); + State TagParamPre(const char c); + State TagParam(const char c); + State TagParamPost(const char c); + State TagParamValuePre(const char c); + State TagParamValue(const char c); + State TagParamValueQuoted(const char c); + + TexoHTMLStack opened; + + void Close(); + + bool is_closing; + Texo::Type tag; + + void SetTag(); + + char *readed; + int readed_len; + int readed_size; + + void ReadedAdd(const char c); + void ReadedClear(); }; diff --git a/src/plain.hpp b/src/plain.hpp index 8c74bce..c88f8ef 100644 --- a/src/plain.hpp +++ b/src/plain.hpp @@ -8,6 +8,7 @@ class TexoPlainImporter: public TexoImporter { public: TexoPlainImporter(TexoProducer &producer); void Put(const char c); + private: int space; int newline; diff --git a/src/texo.cpp b/src/texo.cpp index 03b31e7..3610184 100644 --- a/src/texo.cpp +++ b/src/texo.cpp @@ -23,6 +23,16 @@ void TexoExporter::PutStr(const char *str) TexoProducer::TexoProducer(TexoExporter &exporter): exporter(exporter) {} +void TexoProducer::PutStr(const char *str) +{ + if (str) { + while (*str) { + Put(Texo(*str)); + ++str; + } + } +} + TexoImporter::TexoImporter(TexoProducer &producer): producer(producer) {} diff --git a/src/texo.hpp b/src/texo.hpp index 2129f61..bfea181 100644 --- a/src/texo.hpp +++ b/src/texo.hpp @@ -43,6 +43,8 @@ class TexoProducer { public: TexoProducer(TexoExporter &exporter); virtual void Put(const Texo &piece) = 0; + virtual void PutStr(const char *str); + protected: TexoExporter &exporter; }; @@ -54,6 +56,7 @@ public: virtual void Put(const char c) = 0; virtual void PutStr(const char *str); virtual void PutFile(FILE *file); + protected: TexoProducer &producer; }; -- cgit v1.2.3