summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2019-10-04 16:35:57 +0300
committerAleksey Veresov <aleksey@veresov.pro>2019-10-04 16:35:57 +0300
commit77f503bd6db90bd882e389ea977f02a2773e14f2 (patch)
treec6aa2a7410744c640c530016f4f65746a1ee5ac5
parent5dd4f05089608a66c435d6be36d4bc93dc425986 (diff)
downloadtexo-77f503bd6db90bd882e389ea977f02a2773e14f2.tar
texo-77f503bd6db90bd882e389ea977f02a2773e14f2.tar.xz
texo-77f503bd6db90bd882e389ea977f02a2773e14f2.zip
Semi-working html. =)
-rw-r--r--example/filter_html.cpp5
-rw-r--r--example/makefile2
-rw-r--r--src/file.hpp1
-rw-r--r--src/html.cpp298
-rw-r--r--src/html.hpp59
-rw-r--r--src/plain.hpp1
-rw-r--r--src/texo.cpp10
-rw-r--r--src/texo.hpp3
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(
- "<script>EVIL MAGIC</script>\n"
+ "<script>EVIL MAGIC</script></p>\n"
"<a href='#'>Some</a> br:<br/>\n"
"<p class='evil_too'>And paragraphs work well too...</p>\n"
- "<b>You</b> <i>can</i> <del>use</del> <ins>some</ins> witchcraft.\n"
+ "<b>You</b> <i>can</i> <del>use</del> <ins>some</ins> <p>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 <string.h>
+
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("</a>"); 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("&gt;"); 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("&lt;");
+ if (is_closing) {
+ producer.Put(Texo('/'));
+ }
+ producer.Put(Texo(' '));
+ break;
+ case '>':
+ st = text;
+ producer.PutStr("&lt;");
+ if (is_closing) {
+ producer.Put(Texo('/'));
+ }
+ producer.PutStr("&gt;");
+ 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;
};