From 7f7e6fe30ef4f9ba4507b89174676f57c42c0000 Mon Sep 17 00:00:00 2001
From: Nao Pross <naopross@thearcway.org>
Date: Sun, 26 Nov 2017 23:36:26 +0100
Subject: Implementation for Structogram iterator and Statement type

The interator is not (yet) aware of the scope in which it is iterating.
---
 src/diagram/Statement.cpp   |  15 +++++-
 src/diagram/Statement.hpp   |  44 +++++++++++++-----
 src/diagram/Structogram.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++--
 src/diagram/Structogram.hpp |  53 ++++++++++++++++++---
 src/main.cpp                |  26 +++++++++--
 src/ui/AsciiRenderer.cpp    |  23 +++++----
 src/ui/AsciiRenderer.h      |  33 -------------
 src/ui/AsciiRenderer.hpp    |  37 +++++++++++++++
 src/ui/Window.cpp           |  21 +++++++++
 src/ui/Window.hpp           |  27 +++++++++++
 10 files changed, 319 insertions(+), 71 deletions(-)
 delete mode 100644 src/ui/AsciiRenderer.h
 create mode 100644 src/ui/AsciiRenderer.hpp
 create mode 100644 src/ui/Window.cpp
 create mode 100644 src/ui/Window.hpp

(limited to 'src')

diff --git a/src/diagram/Statement.cpp b/src/diagram/Statement.cpp
index 75770db..60be094 100644
--- a/src/diagram/Statement.cpp
+++ b/src/diagram/Statement.cpp
@@ -5,8 +5,21 @@
  *      Author: naopross
  */
 
-#include "../diagram/Statement.h"
+#include "Statement.hpp"
 
 namespace samb {
 
+Statement::pointer Statement::makeStatement(Statement::Type t) {
+	return std::make_shared<Statement>(Statement(t, "", nullptr, nullptr));
+}
+
+bool Statement::operator==(const Statement& other) {
+	return (this->type == other.type) && (this->text == other.text) &&
+			(this->next == other.next) && (this->scope == other.scope);
+}
+
+
+Statement::Statement(Type t, std::string txt, Statement::pointer p, Statement::pointer s): type(t), text(txt), next(p), scope(s) {}
+Statement::~Statement() {}
+
 } /* namespace samb */
diff --git a/src/diagram/Statement.hpp b/src/diagram/Statement.hpp
index a90e88d..8c41714 100644
--- a/src/diagram/Statement.hpp
+++ b/src/diagram/Statement.hpp
@@ -9,6 +9,7 @@
 #define SRC_STATEMENT_H_
 
 #include <string>
+#include <memory>
 
 namespace samb {
 
@@ -24,24 +25,23 @@ namespace samb {
  * PARALLEL,
  */
 
-/* this class should behave like a std::list,  or a std::map storing the data
- * with a tree structure, BUT it is not a tree because allows 2 notes to point
+/* this struct is a link for linked list that stores the data in a tree-like
+ * structure, BUT it is not a tree because it allows 2 or more nodes to point
  * at a single node
  *
- * Normal Tree:          Statements:
+ * Tree:                 Statements:
  * A - B - C - D         A - B - C - D - G
  *     \                     \      /
  *      E - F                 E - F
  *
- * Because a statement contains branching elmeents. (if / switch)
+ * Because a statements can be branching elements. (if / switch)
+ *
+ * This class is also a *Factory* to make statements.
  */
-class Statement {
-private:
-	Statement *next;
-	Statement *prev;
+struct Statement {
+	using pointer = std::shared_ptr<Statement>;
 
-public:
-	const enum Type {
+	enum Type {
 		PROCESS,
 		DECISION,
 		SWITCH,
@@ -49,10 +49,30 @@ public:
 		UNTIL,
 		SCOPE,
 		PARALLEL,
-	} m_type;
 
-	Statement(Type type, Statement *prev): m_type(type), m_prev(prev);
+		/* this type of statement indicates the end of the program
+		 * and it is used only internally
+		 *
+		 * TODO: think of something more elegant to solve this
+		 */
+		END
+	} type;
+
+	std::string text;
+
+	pointer next;
+	pointer scope; // TODO: make iterator look for this
+
+	static Statement::pointer makeStatement(Type t);
+//	static Statement::pointer makeProcess();
+//	static Statement::pointer makeLoop(Type t, std::string condition);
+//	static Statement::pointer makeBranching(Type t, std::string condition);
+
 	virtual ~Statement();
+	bool operator==(const Statement& other);
+
+private:
+	Statement(Type type, std::string txt, pointer next, pointer scope);
 };
 
 } /* namespace samb */
diff --git a/src/diagram/Structogram.cpp b/src/diagram/Structogram.cpp
index dae9028..a21c62d 100644
--- a/src/diagram/Structogram.cpp
+++ b/src/diagram/Structogram.cpp
@@ -5,23 +5,126 @@
  *      Author: naopross
  */
 
-#include "../diagram/Structogram.h"
+#include "../diagram/Structogram.hpp"
 #include <memory>
+#include <exception>
 
 
 namespace samb {
 
-Structogram::Structogram(std::string title): m_title(title) {
+/* iterator nested class */
+Structogram::iterator::iterator(Statement::pointer first) {
+	m_current = first;
+}
+
+Structogram::iterator::~iterator() {}
+
+Structogram::iterator& Structogram::iterator::operator++() {
+	if (m_current->next != nullptr) {
+		m_current = m_current->next;
+	}
+
+	return *this;
+}
+
+Structogram::iterator& Structogram::iterator::operator++(int) {
+	static iterator old(*this);
+	old = *this;
+
+	operator++();
+	return old;
+}
+
+bool Structogram::iterator::operator==(const iterator& other) const {
+	if (*this->m_current == *other.m_current) {
+		return true;
+	}
+
+	return false;
+}
+
+bool Structogram::iterator::operator!=(const iterator& other) const {
+	return !(other == *this);
+}
+
+Statement& Structogram::iterator::operator*() const {
+	if (m_current == nullptr) {
+		throw std::logic_error("structogram iterator: m_current is nullptr");
+	}
+
+	return *m_current;
+}
+
+Statement::pointer Structogram::iterator::operator->() const {
+	return m_current;
+}
+
 
+/**
+ *  Structogram class methods
+ */
+Structogram::Structogram(std::string title) {
+
+	m_size = 0;
+	m_title = title;
+
+	m_head = Statement::makeStatement(Statement::Type::SCOPE);
+	m_tail = Statement::makeStatement(Statement::Type::END);
+
+	m_head->next = m_tail;
+	m_head->text = m_title;
 }
 
 Structogram::~Structogram() {
+	/* no need to destroy anything because of smart pointers */
+}
 
+std::size_t Structogram::size() const {
+	return m_size;
 }
 
-const std::list<Statement>& Structogram::getStatements() const {
-	return m_statements;
+Structogram::iterator Structogram::insert_after(Structogram::iterator it, Statement::pointer statement) {
+
+	if (statement == nullptr) {
+		throw std::invalid_argument("structogram: attempt to insert a null statement");
+	}
+
+	statement->next = it->next;
+	it->next = statement;
+	m_size++;
+
+	return ++it;
 }
 
+//Structogram::iterator Structogram::insert_after(Structogram::iterator it, Statement::pointer statement) {
+//	return insert(++it, statement);
+//}
+
+Structogram::iterator Structogram::erase_after(iterator it) {
+
+	// TODO: error handling IE return a std::pair<iterator, bool>
+
+	/* the first statement (scope of the program) cannot be deleted */
+	if ((*it) == *m_head) {
+		return it;
+	}
+
+	if (it->next == nullptr) {
+		return it;
+	}
+
+	it->next = it->next->next;
+
+	return it;
+}
+
+/* iterator related methods */
+Structogram::iterator Structogram::begin() const {
+	return iterator(m_head);
+}
+
+const Structogram::iterator Structogram::end() const {
+	return iterator(m_tail);
+}
 
 } /* namespace structograms */
diff --git a/src/diagram/Structogram.hpp b/src/diagram/Structogram.hpp
index 2234142..9318ee4 100644
--- a/src/diagram/Structogram.hpp
+++ b/src/diagram/Structogram.hpp
@@ -10,21 +10,60 @@
 
 #include <iostream>
 #include <list>
-#include "../diagram/Statement.h"
+
+#include "Statement.hpp"
 
 namespace samb {
 
-/* object that holds statements */
+/* A Structogram is a Nassi-Schneiderman diagram, in this implementation it is
+ * simply and iterable object that holds statements.
+ *
+ * The first statement inside a structogram (m_head) is a SCOPE
+ * statement that holds the entire program inside it.
+ */
 class Structogram {
-private:
-	std::list<Statement> m_statements;
-	std::string m_title;
-
 public:
+	/* forward only iterator */
+	class iterator {
+	public:
+		iterator(Statement::pointer first);
+		~iterator();
+
+		iterator& operator++();
+		iterator& operator++(int);
+
+		bool operator==(const iterator& other) const;
+		bool operator!=(const iterator& other) const;
+		Statement& operator*() const;
+		Statement::pointer operator->() const;
+
+	private:
+		Statement::pointer m_current;
+	};
+
 	Structogram(std::string title);
 	virtual ~Structogram();
 
-	const std::list<Statement>& getStatements() const;
+	std::size_t size() const;
+
+	// cannot be implemented because iter is forward only
+//	iterator insert(iterator it, Statement::pointer statement);
+//	iterator erase(iterator it);
+
+	iterator insert_after(iterator it, Statement::pointer statement);
+	iterator erase_after(iterator it);
+
+	/* iterator */
+	iterator begin() const;
+	const iterator end() const;
+	const Statement& operator[](const Statement& it) = delete;
+
+private:
+	std::size_t m_size;
+	std::string m_title;
+
+	Statement::pointer m_head;
+	Statement::pointer m_tail;
 };
 
 } /* namespace structograms */
diff --git a/src/main.cpp b/src/main.cpp
index 5ea2172..7f70de6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,10 +1,28 @@
-#include "diagram/Structogram.h"
+#include "diagram/Structogram.hpp"
+#include "diagram/Statement.hpp"
+#include "ui/AsciiRenderer.hpp"
+
 #include <iostream>
-#include "ui/AsciiRenderer.h"
+#include <memory>
+
+using namespace samb;
 
 int main(int argc, char *argv[]) {
-	samb::Structogram st("Demo");
-	samb::AsciiRenderer renderer(st, 60);
+	Structogram st("Demo");
+	AsciiRenderer renderer(st, 60);
+
+	Structogram::iterator it = st.begin();
+
+	auto first = Statement::makeStatement(Statement::Type::PROCESS);
+	first->text = "Hello World";
+
+	auto second = Statement::makeStatement(Statement::Type::PROCESS);
+	second->text = "Hello World Again!";
+
+	st.insert_after(it, first);
+	++it;
+
+	st.insert_after(it, second);
 
 	renderer.render();
 
diff --git a/src/ui/AsciiRenderer.cpp b/src/ui/AsciiRenderer.cpp
index 0f17d85..d06dadb 100644
--- a/src/ui/AsciiRenderer.cpp
+++ b/src/ui/AsciiRenderer.cpp
@@ -5,7 +5,7 @@
  *      Author: naopross
  */
 
-#include "AsciiRenderer.h"
+#include "AsciiRenderer.hpp"
 
 #include <memory>
 
@@ -38,10 +38,9 @@ void AsciiRenderer::drawText(std::string text, unsigned int width, std::string b
 
 	unsigned int textWidth = width - before.length() - after.length();
 
-
 	std::cout << before;
-	for (unsigned int i = 0; i < text.length(); i++) {
-		if (i % textWidth == 0) {
+	for (std::size_t i = 0; i < text.length(); i++) {
+		if (i % textWidth == 0 && i != 0) {
 			std::cout << after <<  "\n" << before;
 		}
 
@@ -62,24 +61,24 @@ void AsciiRenderer::drawDecision(std::string condition, std::string trueText, st
 }
 
 void AsciiRenderer::render() {
-	const std::list<Statement>& statements = m_structogram.getStatements();
 
-	for (std::list<Statement>::const_iterator it = statements.begin(); it != statements.end(); it++) {
-		Statement st = *it;
-		switch (st.type) {
+	for (Structogram::iterator it = m_structogram.begin(); it != m_structogram.end(); ++it) {
+
+		switch (it->type) {
 		case Statement::Type::PROCESS:
 			drawLine();
-			drawText(st.text);
+			drawText(it->text);
+			drawLine();
 			break;
 
 		case Statement::Type::DECISION:
-			drawLine();
 			break;
 
 		case Statement::Type::SWITCH:
 			break;
 
 		case Statement::Type::SCOPE:
+			std::cout << "Title: " << it->text << std::endl;
 			break;
 
 		case Statement::Type::WHILE:
@@ -90,6 +89,10 @@ void AsciiRenderer::render() {
 
 		case Statement::Type::PARALLEL:
 			break;
+
+		case Statement::END:
+			// do nothing
+			break;
 		}
 	}
 }
diff --git a/src/ui/AsciiRenderer.h b/src/ui/AsciiRenderer.h
deleted file mode 100644
index 4f9020a..0000000
--- a/src/ui/AsciiRenderer.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Renderer.h
- *
- *  Created on: Nov 23, 2017
- *      Author: naopross
- */
-
-#ifndef SRC_UI_ASCIIRENDERER_H_
-#define SRC_UI_ASCIIRENDERER_H_
-
-#include "../diagram/Structogram.h"
-
-namespace samb {
-
-class AsciiRenderer {
-private:
-	Structogram m_structogram;
-	const unsigned int m_width;
-
-	void drawPadding(unsigned int amt);
-	void drawLine() const;
-	void drawText(std::string text, unsigned int width = 0, std::string before = "|", std::string after = "|") const;
-	void drawDecision(std::string condition, std::string trueText, std::string falseText, unsigned int width = 0) const;
-public:
-	AsciiRenderer(Structogram& structogram, unsigned int width);
-	~AsciiRenderer();
-
-	void render();
-};
-
-} /* namespace samb */
-
-#endif /* SRC_UI_ASCIIRENDERER_H_ */
diff --git a/src/ui/AsciiRenderer.hpp b/src/ui/AsciiRenderer.hpp
new file mode 100644
index 0000000..76d6ff5
--- /dev/null
+++ b/src/ui/AsciiRenderer.hpp
@@ -0,0 +1,37 @@
+/*
+ * Renderer.h
+ *
+ *  Created on: Nov 23, 2017
+ *      Author: naopross
+ */
+
+#ifndef SRC_UI_ASCIIRENDERER_HPP_
+#define SRC_UI_ASCIIRENDERER_HPP_
+
+#include "../diagram/Structogram.hpp"
+
+namespace samb {
+
+/* Sample renderer for debug,
+ *
+ * TODO: implement PdfRenderer, UiRenderer with a common interface
+ */
+class AsciiRenderer {
+private:
+	Structogram m_structogram;
+	const unsigned int m_width;
+
+	void drawPadding(unsigned int amt);
+	void drawLine() const;
+	void drawText(std::string text, unsigned int width = 0, std::string before = "|", std::string after = "|") const;
+	void drawDecision(std::string condition, std::string trueText, std::string falseText, unsigned int width = 0) const;
+public:
+	AsciiRenderer(Structogram& structogram, unsigned int width);
+	~AsciiRenderer();
+
+	void render();
+};
+
+} /* namespace samb */
+
+#endif /* SRC_UI_ASCIIRENDERER_HPP_ */
diff --git a/src/ui/Window.cpp b/src/ui/Window.cpp
new file mode 100644
index 0000000..4572766
--- /dev/null
+++ b/src/ui/Window.cpp
@@ -0,0 +1,21 @@
+/*
+ * Window.cpp
+ *
+ *  Created on: Nov 26, 2017
+ *      Author: naopross
+ */
+
+#include "Window.hpp"
+
+namespace samb {
+
+Window::Window() {
+	// TODO Auto-generated constructor stub
+
+}
+
+Window::~Window() {
+	// TODO Auto-generated destructor stub
+}
+
+} /* namespace samb */
diff --git a/src/ui/Window.hpp b/src/ui/Window.hpp
new file mode 100644
index 0000000..5afad8c
--- /dev/null
+++ b/src/ui/Window.hpp
@@ -0,0 +1,27 @@
+/*
+ * Window.hpp
+ *
+ *  Created on: Nov 26, 2017
+ *      Author: naopross
+ */
+
+#ifndef SRC_UI_WINDOW_HPP_
+#define SRC_UI_WINDOW_HPP_
+
+#include <QWidget>
+
+namespace samb {
+
+class Window : public QWidget {
+Q_OBJECT
+public:
+	Window();
+	virtual ~Window();
+
+signals:
+public slots:
+};
+
+} /* namespace samb */
+
+#endif /* SRC_UI_WINDOW_HPP_ */
-- 
cgit v1.2.1