From f384fdc3a9e4acccac2e4d322676e34115a168f7 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 12:13:52 +0200 Subject: WIP meer nadenk --- docs/Parser.h | 16 ++++++++++++++++ docs/class-diag.puml | 20 ++++++++++++++++---- main.cpp | 48 +++++++++++++++++++++++++++++++++++------------- readme.md | 5 ++++- 4 files changed, 71 insertions(+), 18 deletions(-) create mode 100644 docs/Parser.h diff --git a/docs/Parser.h b/docs/Parser.h new file mode 100644 index 0000000..a7c90e9 --- /dev/null +++ b/docs/Parser.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +using std::ostream; + +class Parser { + + friend void operator >> (Parser& p, std::istream& filestream) { + // cout assigned to another object mycout + std::cout << "the file contains:\n" << filestream << std::endl; + mycout << "Value of dx and dy are \n"; + mycout << d.dx << " " << d.dy; + } +} diff --git a/docs/class-diag.puml b/docs/class-diag.puml index 85cb721..ea245cd 100644 --- a/docs/class-diag.puml +++ b/docs/class-diag.puml @@ -1,12 +1,13 @@ @startuml abstract class Node { /' (also ConcreteObserver) '/ - + label: string - + type: string - + addOutput(Net*) + + setOutput(Net*) + addInput(Net*) - inputs: Net*[] - - outputs: Net*[] + - output: Net* + - type: static constexpr const string + - minInputs: constexpr unsigned int + - maxInputs: constexpr int } class Net { /' (also ConcreteSubject) '/ - level: SignalLevel @@ -62,5 +63,16 @@ class CircuitFactory { + configure() } +class Circuit { + + createNode(string type, string label) + + createLink(string labelA, string labelB) + + - nets: Map + - nodes: Map +} + +CircuitFactory -[dashed]> Node +CircuitFactory <-[dashed]- Node + @enduml diff --git a/main.cpp b/main.cpp index 05ec033..01b78b2 100644 --- a/main.cpp +++ b/main.cpp @@ -1,17 +1,39 @@ -#include -// #include "Observer.h" -#include "Net.h" -#include "Gate.h" +#include +#include +#include + +#include "Parser.h" +#include "Circuit.h" + +using std::cout; +using std::endl; +using std::fstream; +using std::exception; int main(int argc, char** argv) { - // Observer ob(); - Net n; - Gate *g = new GateAnd; - g->addInput(&n); - n.setLevel(HIGH); - int level = 22; - level = n.getLevel(); - printf("hello world! %d\n", level); - return 0; + Parser main_parser; + Circuit circuit; + + main_parser.setCircuit(circuit); + + fstream file{"circuits/full-adder.txt", file.out}; + + try { + main_parser << file; + } catch (exception e) { + cout << "Parser error: " << e.what() << endl; + return EXIT_FAILURE; + } + + try { + circuit.run(); + } catch (exception e) { + cout << "Circuit error: " << e.what() << endl; + return EXIT_FAILURE; + } + + cout << "Circuit output: " << circuit.getOutput() << endl; + + return EXIT_SUCCESS; } diff --git a/readme.md b/readme.md index 218a2e0..1703a9f 100644 --- a/readme.md +++ b/readme.md @@ -9,7 +9,10 @@ make ## Applied design patters - Observer -- Factory +- Low binding factory +- Prototype +- Dependency injection +- vast meer! ## TODO -- cgit v1.2.3 From 6ceea7d142619020e6b18aad97e21572cb9dd314 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 14:00:40 +0200 Subject: fix magic incantation for istream reader --- Parser.cpp | 20 ++++++++++++++++++++ Parser.h | 18 ++++++++++++++++++ docs/Parser.h | 16 ---------------- main.cpp | 40 +++++++++++++++++++++------------------- 4 files changed, 59 insertions(+), 35 deletions(-) create mode 100644 Parser.cpp create mode 100644 Parser.h delete mode 100644 docs/Parser.h diff --git a/Parser.cpp b/Parser.cpp new file mode 100644 index 0000000..d76f11a --- /dev/null +++ b/Parser.cpp @@ -0,0 +1,20 @@ +#include "Parser.h" + +void Parser::parse(string input) const { + std::cout << input << std::endl; +} + +istream & Parser::parse(const Parser & parser, istream & s) const { + string temp(std::istreambuf_iterator(s), {}); + parse(temp); + return s; +} + +istream & operator >> (istream & s, const Parser & parser) { + return parser.parse(parser, s); +} + +istream & operator << (const Parser & parser, istream & s) { + return parser.parse(parser, s); +} + diff --git a/Parser.h b/Parser.h new file mode 100644 index 0000000..58d062f --- /dev/null +++ b/Parser.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +using std::istream; +using std::string; + +class Parser { +public: + void parse(string input) const; + +private: + istream & parse(const Parser & parser, istream & s) const; + friend istream & operator << (const Parser & parser, istream & s); + friend istream & operator >> (istream & s, const Parser & parser); +}; + diff --git a/docs/Parser.h b/docs/Parser.h deleted file mode 100644 index a7c90e9..0000000 --- a/docs/Parser.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include - -using std::ostream; - -class Parser { - - friend void operator >> (Parser& p, std::istream& filestream) { - // cout assigned to another object mycout - std::cout << "the file contains:\n" << filestream << std::endl; - mycout << "Value of dx and dy are \n"; - mycout << d.dx << " " << d.dy; - } -} diff --git a/main.cpp b/main.cpp index 01b78b2..cca0636 100644 --- a/main.cpp +++ b/main.cpp @@ -1,38 +1,40 @@ +#include #include #include #include #include "Parser.h" -#include "Circuit.h" +// #include "Circuit.h" using std::cout; using std::endl; -using std::fstream; using std::exception; +using std::ifstream; +using std::istream; int main(int argc, char** argv) { - Parser main_parser; - Circuit circuit; + Parser main_parser; + // Circuit circuit; - main_parser.setCircuit(circuit); + // main_parser.setCircuit(circuit); - fstream file{"circuits/full-adder.txt", file.out}; + ifstream file("circuits/full-adder.txt"); - try { - main_parser << file; - } catch (exception e) { - cout << "Parser error: " << e.what() << endl; - return EXIT_FAILURE; - } + try { + file >> main_parser; + } catch (exception e) { + cout << "Parser error: " << e.what() << endl; + return EXIT_FAILURE; + } - try { - circuit.run(); - } catch (exception e) { - cout << "Circuit error: " << e.what() << endl; - return EXIT_FAILURE; - } + // try { + // circuit.run(); + // } catch (exception e) { + // cout << "Circuit error: " << e.what() << endl; + // return EXIT_FAILURE; + // } - cout << "Circuit output: " << circuit.getOutput() << endl; + // cout << "Circuit output: " << circuit.getOutput() << endl; return EXIT_SUCCESS; } -- cgit v1.2.3 From 6bf48a8fc00d76f712797a8f578445893de62791 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 14:02:13 +0200 Subject: add editorconfig + indent code --- .editorconfig | 11 +++++++++++ Net.cpp | 10 ++++++---- Net.h | 14 +++++++------- Node.cpp | 56 +++++++++++++++++++++++++++----------------------------- Node.h | 35 +++++++++++++++++------------------ Observer.cpp | 15 +++++++-------- Observer.h | 40 ++++++++++++++++++---------------------- 7 files changed, 93 insertions(+), 88 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a3793d2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = tab +end_of_line = lf +insert_final_newline = true + +[*.md] +indent_style = space +indent_size = 2 + diff --git a/Net.cpp b/Net.cpp index be01152..5b3f5e3 100644 --- a/Net.cpp +++ b/Net.cpp @@ -6,10 +6,12 @@ Net::Net(){} Net::~Net(){} void Net::setLevel(SignalLevel level){ - this->level = level; - std::cout << this->size() << std::endl; - this->notify(); + this->level = level; + std::cout << this->size() << std::endl; + this->notify(); } + SignalLevel Net::getLevel(){ - return this->level; + return this->level; } + diff --git a/Net.h b/Net.h index 81c8034..150c9b6 100644 --- a/Net.h +++ b/Net.h @@ -5,13 +5,13 @@ enum SignalLevel {LOW, HIGH, UNDEFINED}; class Net: public Subject { - private: - SignalLevel level = UNDEFINED; - public: - Net(/* args */); - ~Net(); - virtual void setLevel(SignalLevel); - virtual SignalLevel getLevel(); +private: + SignalLevel level = UNDEFINED; +public: + Net(/* args */); + ~Net(); + virtual void setLevel(SignalLevel); + virtual SignalLevel getLevel(); }; diff --git a/Node.cpp b/Node.cpp index d351af1..05ac5d6 100644 --- a/Node.cpp +++ b/Node.cpp @@ -5,43 +5,41 @@ Node::Node(){} Node::~Node(){} void Node::addInput(Net* net){ - net->attach(this); + net->attach(this); } void Node::setOutput(Net* net){ - this->output = net; + this->output = net; } void Node::update(){ - std::cout << "updated" << std::endl; - this->compare(); + std::cout << "updated" << std::endl; + this->compare(); } /*/ Concrete Nodes: /*/ void GateAnd::compare(){ - SignalLevel new_out = HIGH; - - // TODO fix segfault somewhere below - // for (int i = 0; i < this->inputs.size(); i++){ - // switch (this->inputs[i]->getLevel()){ - // case LOW: - // new_out = LOW; - // break; - // case HIGH: - // continue; - // break; - // case UNDEFINED: - // default: - // new_out = UNDEFINED; - // exit; - // break; - // } - // } - - // if (this->output->getLevel() == new_out){ - // /* do nothing */ - // } else { - // this->output->setLevel(new_out); - // } - + SignalLevel new_out = HIGH; +// TODO fix segfault somewhere below +// for (int i = 0; i < this->inputs.size(); i++){ +// switch (this->inputs[i]->getLevel()){ +// case LOW: +// new_out = LOW; +// break; +// case HIGH: +// continue; +// break; +// case UNDEFINED: +// default: +// new_out = UNDEFINED; +// exit; +// break; +// } +// } + +// if (this->output->getLevel() == new_out){ +// /* do nothing */ +// } else { +// this->output->setLevel(new_out); +// } } diff --git a/Node.h b/Node.h index f1845a9..8db9fe9 100644 --- a/Node.h +++ b/Node.h @@ -1,32 +1,31 @@ #pragma once + #include #include #include "Observer.h" #include "Net.h" - - class Node: Observer { - protected: - std::string label; - std::string type; +protected: + std::string label; + std::string type; - std::vector inputs; - Net* output; + std::vector inputs; + Net* output; - public: - Node(/* args */); - virtual ~Node(); - void update(); - virtual void addInput(Net*); - virtual void setOutput(Net*); - virtual void compare() = 0; +public: + Node(/* args */); + virtual ~Node(); + void update(); + virtual void addInput(Net*); + virtual void setOutput(Net*); + virtual void compare() = 0; }; class GateAnd: public Node { - public: - GateAnd(){}; - ~GateAnd(){}; - void compare(); +public: + GateAnd(){}; + ~GateAnd(){}; + void compare(); }; diff --git a/Observer.cpp b/Observer.cpp index 1e9c9bb..1d96ed4 100644 --- a/Observer.cpp +++ b/Observer.cpp @@ -2,22 +2,21 @@ #include void Observer::update(){ - std::cout << 'a' << std::endl; + std::cout << 'a' << std::endl; } - - void Subject::attach(Observer* obs){ - std::cout << "added" << std::endl; - this->observers.push_back(obs); + std::cout << "added" << std::endl; + this->observers.push_back(obs); } void Subject::detach(Observer*){ } - + // TODO possibly add foo input as update value? void Subject::notify() { - for (int i = 0; i < this->observers.size(); i++) - this->observers[i]->update(); + for (int i = 0; i < this->observers.size(); i++) + this->observers[i]->update(); } + diff --git a/Observer.h b/Observer.h index 6ff8f3b..7b2db7e 100644 --- a/Observer.h +++ b/Observer.h @@ -1,32 +1,28 @@ #pragma once #include - class Observer { - private: +private: + +public: + virtual void update(); - public: - virtual void update(); - }; class Subject { - private: - std::vector observers; - public: - // virtual void attach(Observer* obs) { observers.push_back(obs);} - virtual void attach(Observer* obs); - virtual void detach(Observer*); - virtual int size() { return this->observers.size(); } - - // TODO possibly add foo input as update value? - virtual void notify(); - // virtual void notify() { - // for (int i = 0; i < observers.size(); i++) - // observers.at(i)->update(); - // } +private: + std::vector observers; +public: + // virtual void attach(Observer* obs) { observers.push_back(obs);} + virtual void attach(Observer* obs); + virtual void detach(Observer*); + virtual int size() { return this->observers.size(); } + + // TODO possibly add foo input as update value? + virtual void notify(); + // virtual void notify() { + // for (int i = 0; i < observers.size(); i++) + // observers.at(i)->update(); + // } }; - - - -- cgit v1.2.3 From bde4c3fe7885b66c0bb59b8407c74b350fc6b44d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Tue, 4 Jun 2024 15:33:44 +0200 Subject: WIP parser --- Parser.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++++---- Parser.h | 24 +++++++++++- circuits/full-adder.txt | 12 +++--- main.cpp | 4 +- 4 files changed, 124 insertions(+), 17 deletions(-) diff --git a/Parser.cpp b/Parser.cpp index d76f11a..5774a0e 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -1,20 +1,105 @@ +#include +#include +#include + #include "Parser.h" -void Parser::parse(string input) const { - std::cout << input << std::endl; +using std::getline; + +ParserException::ParserException(const char * fmt, ...) { + va_list args; + va_start(args, fmt); + size_t sz = vsnprintf(NULL, 0, fmt, args) + 1; + if (error != NULL) free(error); + error = (char *) malloc(sz); + vsnprintf(error, sz, fmt, args); + va_end(args); } -istream & Parser::parse(const Parser & parser, istream & s) const { - string temp(std::istreambuf_iterator(s), {}); - parse(temp); - return s; +ParserException::~ParserException() { + if (error != NULL) + free(error); +} + +const char * ParserException::what() { + return error; +} + +size_t Parser::filter(char * input) { + size_t + len = strlen(input), + offset = 0, + i = 0; + + while (i < len) { + if(input[i] == '#') { + offset += len - i; + break; + } + + size_t skip = strspn(input + i, " \t\n"); + if (skip > 0) { + offset += skip; + i += skip; + continue; + } + + input[i - offset] = input[i]; + i++; + } + + input[len - offset] = '\0'; + return len - offset; +} + +void Parser::parse(istream & input) const { + unsigned linenum = 0; + string line_str; + while (getline(input, line_str)) { + linenum++; + char* line = line_str.data(); + size_t len = Parser::filter(line); + + if (len == 0) continue; // ignore empty lines + + char* label = strtok(line, ":"); + if (label == NULL) throw ParserException("syntax error on line %u", linenum); + + char* content = strtok(NULL, ";"); + if (content == NULL) throw ParserException("syntax error on line %u", linenum); + + vector nodes; + while ((content = strtok(content, ",")) != NULL) { + nodes.push_back(content); + content = NULL; + } + + handle_line(label, nodes); + } +} + +void Parser::handle_line(string label, vector nodes) const { + if (nodes.size() == 1) { + printf("node or net "); + } else { + printf("net "); + } + + printf("[%s]\n", label.c_str()); } istream & operator >> (istream & s, const Parser & parser) { - return parser.parse(parser, s); + parser.parse(s); + return s; } istream & operator << (const Parser & parser, istream & s) { - return parser.parse(parser, s); + parser.parse(s); + return s; +} + +void Parser::parse(string input) const { + std::istringstream s(input); + parse(s); } diff --git a/Parser.h b/Parser.h index 58d062f..2124eab 100644 --- a/Parser.h +++ b/Parser.h @@ -2,16 +2,38 @@ #include #include +#include +#include using std::istream; using std::string; +using std::vector; + +class ParserException : public std::exception { +public: + ParserException(const char * fmt, ...); + ~ParserException(); + const char * what(); + +private: + char * error = NULL; +}; class Parser { public: void parse(string input) const; + void parse(istream & input) const; + + /** + * \brief preprocess (filter) line of input + * + * normalize whitespace and remove comments + */ + static size_t filter(char * input); + + void handle_line(string label, vector nodes) const; private: - istream & parse(const Parser & parser, istream & s) const; friend istream & operator << (const Parser & parser, istream & s); friend istream & operator >> (istream & s, const Parser & parser); }; diff --git a/circuits/full-adder.txt b/circuits/full-adder.txt index d0c3854..9b85bc7 100644 --- a/circuits/full-adder.txt +++ b/circuits/full-adder.txt @@ -17,14 +17,14 @@ NODE9: AND; NODE10: AND; NODE11: OR; -Cin: NODE3,NODE7,NODE10; -A: NODE1,NODE2; -B: NODE1,NODE2; -NODE1: NODE3,NODE5; -NODE2: NODE4,NODE6; +Cin: NODE3, NODE7, NODE10; +A: NODE1, NODE2; +B: NODE1, NODE2; +NODE1: NODE3, NODE5; +NODE2: NODE4, NODE6; NODE3: NODE6; NODE4: NODE5; -NODE5: NODE8,NODE9; +NODE5: NODE8, NODE9; NODE6: Cout; NODE7: NODE9; NODE8: NODE10; diff --git a/main.cpp b/main.cpp index cca0636..2a15a39 100644 --- a/main.cpp +++ b/main.cpp @@ -22,14 +22,14 @@ int main(int argc, char** argv) { try { file >> main_parser; - } catch (exception e) { + } catch (ParserException & e) { cout << "Parser error: " << e.what() << endl; return EXIT_FAILURE; } // try { // circuit.run(); - // } catch (exception e) { + // } catch (exception& e) { // cout << "Circuit error: " << e.what() << endl; // return EXIT_FAILURE; // } -- cgit v1.2.3 From 9e1b22e12bb0915081c94e6266b9725251500dcd Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 7 Jun 2024 15:22:00 +0200 Subject: WIP begin writing factory --- .gitignore | 2 ++ Circuit.cpp | 19 +++++++++++++++++++ Circuit.h | 19 +++++++++++++++++++ GateAnd.cpp | 39 +++++++++++++++++++++++++++++++++++++++ GateAnd.h | 15 +++++++++++++++ Node.cpp | 36 ++++++------------------------------ Node.h | 30 +++++++++++++----------------- NodeFactory.cpp | 24 ++++++++++++++++++++++++ NodeFactory.h | 21 +++++++++++++++++++++ Parser.cpp | 24 ++++++++++-------------- Parser.h | 23 ++++++++++++++--------- docs/class-diag.puml | 2 +- main.cpp | 11 ++++------- makefile | 4 ++-- 14 files changed, 189 insertions(+), 80 deletions(-) create mode 100644 Circuit.cpp create mode 100644 Circuit.h create mode 100644 GateAnd.cpp create mode 100644 GateAnd.h create mode 100644 NodeFactory.cpp create mode 100644 NodeFactory.h diff --git a/.gitignore b/.gitignore index 4ce588c..1707139 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ main *.o .vscode +.cache +compile_commands.json diff --git a/Circuit.cpp b/Circuit.cpp new file mode 100644 index 0000000..f6229f1 --- /dev/null +++ b/Circuit.cpp @@ -0,0 +1,19 @@ +#include "Circuit.h" +#include "NodeFactory.h" + +void Circuit::create(string label, vector nodes) { + if (nodes.size() == 1 && NodeFactory::has_type(nodes[0])) + return new_node(label, nodes[0]); + + for (string node : nodes) + new_net(label, node); +} + +void Circuit::new_node(string label, string type) { + printf("[%s] (%s)\n", label.c_str(), type.c_str()); +} + +void Circuit::new_net(string label, string connection) { + printf("[%s] -> %s\n", label.c_str(), connection.c_str()); +} + diff --git a/Circuit.h b/Circuit.h new file mode 100644 index 0000000..249301d --- /dev/null +++ b/Circuit.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +using std::string; +using std::vector; + +class Circuit { +public: + Circuit() = default; + virtual ~Circuit() = default; + +public: + void create(string label, vector nodes); + void new_node(string label, string type); + void new_net(string label, string node); +}; + diff --git a/GateAnd.cpp b/GateAnd.cpp new file mode 100644 index 0000000..e48b21c --- /dev/null +++ b/GateAnd.cpp @@ -0,0 +1,39 @@ +#include + +#include "GateAnd.h" + +using std::cout; +using std::endl; + +GateAnd GateAnd::instance(GateAnd::type); + +GateAnd::GateAnd(const char * type) : Node(type) { + cout << __PRETTY_FUNCTION__ << endl; +} + +// Concrete Nodes: +void GateAnd::compare() { + SignalLevel new_out = HIGH; +// TODO fix segfault somewhere below +// for (int i = 0; i < this->inputs.size(); i++){ +// switch (this->inputs[i]->getLevel()){ +// case LOW: +// new_out = LOW; +// break; +// case HIGH: +// continue; +// break; +// case UNDEFINED: +// default: +// new_out = UNDEFINED; +// exit; +// break; +// } +// } + +// if (this->output->getLevel() == new_out){ +// /* do nothing */ +// } else { +// this->output->setLevel(new_out); +// } +} diff --git a/GateAnd.h b/GateAnd.h new file mode 100644 index 0000000..40e3927 --- /dev/null +++ b/GateAnd.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Node.h" + +class GateAnd : public Node { +public: + GateAnd(const char * type); + virtual ~GateAnd() = default; + virtual void compare(); + +private: + constexpr static const char * type = "and"; + static GateAnd instance; +}; + diff --git a/Node.cpp b/Node.cpp index 05ac5d6..5deaf03 100644 --- a/Node.cpp +++ b/Node.cpp @@ -2,11 +2,14 @@ #include -Node::Node(){} -Node::~Node(){} -void Node::addInput(Net* net){ +Node::Node(const char * type) { + +} + +void Node::addInput(Net* net) { net->attach(this); } + void Node::setOutput(Net* net){ this->output = net; } @@ -16,30 +19,3 @@ void Node::update(){ this->compare(); } -/*/ Concrete Nodes: /*/ - -void GateAnd::compare(){ - SignalLevel new_out = HIGH; -// TODO fix segfault somewhere below -// for (int i = 0; i < this->inputs.size(); i++){ -// switch (this->inputs[i]->getLevel()){ -// case LOW: -// new_out = LOW; -// break; -// case HIGH: -// continue; -// break; -// case UNDEFINED: -// default: -// new_out = UNDEFINED; -// exit; -// break; -// } -// } - -// if (this->output->getLevel() == new_out){ -// /* do nothing */ -// } else { -// this->output->setLevel(new_out); -// } -} diff --git a/Node.h b/Node.h index 8db9fe9..7f2d03d 100644 --- a/Node.h +++ b/Node.h @@ -6,26 +6,22 @@ #include "Observer.h" #include "Net.h" -class Node: Observer { -protected: - std::string label; - std::string type; - - std::vector inputs; - Net* output; +using std::string; +using std::vector; +class Node : Observer { public: - Node(/* args */); - virtual ~Node(); + Node(const char * type); + virtual ~Node() = default; void update(); - virtual void addInput(Net*); - virtual void setOutput(Net*); + virtual void addInput(Net *); + virtual void setOutput(Net *); virtual void compare() = 0; -}; -class GateAnd: public Node { -public: - GateAnd(){}; - ~GateAnd(){}; - void compare(); +protected: + string label; + + vector inputs; + Net * output; }; + diff --git a/NodeFactory.cpp b/NodeFactory.cpp new file mode 100644 index 0000000..da4cc72 --- /dev/null +++ b/NodeFactory.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +#include "NodeFactory.h" + +bool NodeFactory::has_type(const char * type) { + return has_type(string(type)); +} + +bool NodeFactory::has_type(string type) { + std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); + + // TODO: query the map instead + if (type == "and") return true; + if (type == "not") return true; + if (type == "or") return true; + if (type == "input_high") return true; + if (type == "input_low") return true; + if (type == "probe") return true; + + return false; +} + diff --git a/NodeFactory.h b/NodeFactory.h new file mode 100644 index 0000000..b5757d4 --- /dev/null +++ b/NodeFactory.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "Node.h" + +using std::string; + +class NodeFactory { +public: + NodeFactory() = default; + virtual ~NodeFactory() = default; + +public: + static bool has_type(const char * type); + static bool has_type(string type); + +private: + friend Node; +}; + diff --git a/Parser.cpp b/Parser.cpp index 5774a0e..84c3217 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -52,7 +52,11 @@ size_t Parser::filter(char * input) { return len - offset; } -void Parser::parse(istream & input) const { +void Parser::set_circuit(Circuit & circuit) { + this->circuit = &circuit; +} + +void Parser::parse(istream & input) { unsigned linenum = 0; string line_str; while (getline(input, line_str)) { @@ -74,31 +78,23 @@ void Parser::parse(istream & input) const { content = NULL; } - handle_line(label, nodes); + if (circuit == nullptr) throw ParserException("circuit is not initialized!"); + circuit->create(label, nodes); } } -void Parser::handle_line(string label, vector nodes) const { - if (nodes.size() == 1) { - printf("node or net "); - } else { - printf("net "); - } - - printf("[%s]\n", label.c_str()); -} -istream & operator >> (istream & s, const Parser & parser) { +istream & operator >> (istream & s, Parser & parser) { parser.parse(s); return s; } -istream & operator << (const Parser & parser, istream & s) { +istream & operator << (Parser & parser, istream & s) { parser.parse(s); return s; } -void Parser::parse(string input) const { +void Parser::parse(string input) { std::istringstream s(input); parse(s); } diff --git a/Parser.h b/Parser.h index 2124eab..3a86eec 100644 --- a/Parser.h +++ b/Parser.h @@ -3,17 +3,17 @@ #include #include #include -#include + +#include "Circuit.h" using std::istream; using std::string; -using std::vector; class ParserException : public std::exception { public: ParserException(const char * fmt, ...); - ~ParserException(); - const char * what(); + virtual ~ParserException(); + virtual const char * what(); private: char * error = NULL; @@ -21,8 +21,11 @@ private: class Parser { public: - void parse(string input) const; - void parse(istream & input) const; + Parser() = default; + virtual ~Parser() = default; + + void parse(string input); + void parse(istream & input); /** * \brief preprocess (filter) line of input @@ -31,10 +34,12 @@ public: */ static size_t filter(char * input); - void handle_line(string label, vector nodes) const; + void set_circuit(Circuit & circuit); private: - friend istream & operator << (const Parser & parser, istream & s); - friend istream & operator >> (istream & s, const Parser & parser); + friend istream & operator << (Parser & parser, istream & s); + friend istream & operator >> (istream & s, Parser & parser); + + Circuit * circuit; }; diff --git a/docs/class-diag.puml b/docs/class-diag.puml index ea245cd..5efda1b 100644 --- a/docs/class-diag.puml +++ b/docs/class-diag.puml @@ -5,7 +5,7 @@ abstract class Node { /' (also ConcreteObserver) '/ + addInput(Net*) - inputs: Net*[] - output: Net* - - type: static constexpr const string + - type: static const char * string - minInputs: constexpr unsigned int - maxInputs: constexpr int } diff --git a/main.cpp b/main.cpp index 2a15a39..01ddeb7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,27 +1,24 @@ -#include #include -#include #include #include "Parser.h" -// #include "Circuit.h" +#include "Circuit.h" using std::cout; using std::endl; -using std::exception; using std::ifstream; -using std::istream; int main(int argc, char** argv) { Parser main_parser; - // Circuit circuit; + Circuit circuit; - // main_parser.setCircuit(circuit); + main_parser.set_circuit(circuit); ifstream file("circuits/full-adder.txt"); try { file >> main_parser; + // main_parser << file; } catch (ParserException & e) { cout << "Parser error: " << e.what() << endl; return EXIT_FAILURE; diff --git a/makefile b/makefile index 31bee7c..509e1e8 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ CC = g++ LD = g++ RM = rm -f -CFLAGS = -g -std=c++17 +CFLAGS = -g -std=c++20 LFLAGS = TARGET = main SRCS := $(wildcard *.cpp) @@ -18,5 +18,5 @@ $(TARGET): $(OBJS) clean: $(RM) $(TARGET) $(OBJS) -compile_commands: clean +compile_commands.json: compiledb make -Bn -- cgit v1.2.3 From 9413d81efb2279fc136deee874a8560dd4bb4a7e Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 8 Jun 2024 13:10:37 +0200 Subject: use factory map to look up node types --- Node.cpp | 3 ++- NodeFactory.cpp | 28 +++++++++++++++++++--------- NodeFactory.h | 7 +++++++ 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Node.cpp b/Node.cpp index 5deaf03..a0fc27b 100644 --- a/Node.cpp +++ b/Node.cpp @@ -1,9 +1,10 @@ #include "Node.h" +#include "NodeFactory.h" #include Node::Node(const char * type) { - + NodeFactory::assign(type, this); } void Node::addInput(Net* net) { diff --git a/NodeFactory.cpp b/NodeFactory.cpp index da4cc72..4824734 100644 --- a/NodeFactory.cpp +++ b/NodeFactory.cpp @@ -11,14 +11,24 @@ bool NodeFactory::has_type(const char * type) { bool NodeFactory::has_type(string type) { std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); - // TODO: query the map instead - if (type == "and") return true; - if (type == "not") return true; - if (type == "or") return true; - if (type == "input_high") return true; - if (type == "input_low") return true; - if (type == "probe") return true; - - return false; + static NodeFactoryMap & map = get_map(); + + return map.find(type) != map.end(); +} + +void NodeFactory::assign(const char * _type, const Node * node) { + static NodeFactoryMap & map = get_map(); + string type = _type; + + std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); + + if (has_type(type)) return; + + map[type] = node; +} + +NodeFactoryMap & NodeFactory::get_map() { + static NodeFactoryMap map; + return map; } diff --git a/NodeFactory.h b/NodeFactory.h index b5757d4..7790b4a 100644 --- a/NodeFactory.h +++ b/NodeFactory.h @@ -1,11 +1,14 @@ #pragma once #include +#include #include "Node.h" using std::string; +using NodeFactoryMap = std::map; + class NodeFactory { public: NodeFactory() = default; @@ -15,6 +18,10 @@ public: static bool has_type(const char * type); static bool has_type(string type); +private: + static void assign(const char * type, const Node * node); + static NodeFactoryMap & get_map(); + private: friend Node; }; -- cgit v1.2.3 From 2acd9a0097bb89e4b10ff77848d314e60f27be54 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 8 Jun 2024 14:10:50 +0200 Subject: instance Nodes using copy constructor in NodeFactory --- Circuit.cpp | 16 ++++++++++++++++ Circuit.h | 10 +++++++++- GateAnd.cpp | 16 ++++++++-------- GateAnd.h | 4 +++- Node.h | 7 ++++++- NodeFactory.cpp | 30 ++++++++++++++++++++++-------- NodeFactory.h | 3 +++ 7 files changed, 67 insertions(+), 19 deletions(-) diff --git a/Circuit.cpp b/Circuit.cpp index f6229f1..cf6312e 100644 --- a/Circuit.cpp +++ b/Circuit.cpp @@ -10,10 +10,26 @@ void Circuit::create(string label, vector nodes) { } void Circuit::new_node(string label, string type) { + if (nodes.find(label) != nodes.end()) return; // TODO: exception! + + Node * node = NodeFactory::create(type); + if (node == nullptr) return; // TODO: exception? + + nodes[label] = node; + printf("[%s] (%s)\n", label.c_str(), type.c_str()); } void Circuit::new_net(string label, string connection) { + // TODO: instance Net + // TODO: connect Net to connection printf("[%s] -> %s\n", label.c_str(), connection.c_str()); } +Circuit::~Circuit() { + for (auto const & n : nodes) + delete n.second; + for (auto const & n : nets) + delete n.second; +} + diff --git a/Circuit.h b/Circuit.h index 249301d..5fd8d23 100644 --- a/Circuit.h +++ b/Circuit.h @@ -2,6 +2,10 @@ #include #include +#include + +#include "Node.h" +#include "Net.h" using std::string; using std::vector; @@ -9,11 +13,15 @@ using std::vector; class Circuit { public: Circuit() = default; - virtual ~Circuit() = default; + virtual ~Circuit(); public: void create(string label, vector nodes); void new_node(string label, string type); void new_net(string label, string node); + +private: + std::map nodes = {}; + std::map nets = {}; }; diff --git a/GateAnd.cpp b/GateAnd.cpp index e48b21c..dc65353 100644 --- a/GateAnd.cpp +++ b/GateAnd.cpp @@ -1,15 +1,8 @@ -#include - #include "GateAnd.h" -using std::cout; -using std::endl; - GateAnd GateAnd::instance(GateAnd::type); -GateAnd::GateAnd(const char * type) : Node(type) { - cout << __PRETTY_FUNCTION__ << endl; -} +GateAnd::GateAnd(const char * type) : Node(type) { } // Concrete Nodes: void GateAnd::compare() { @@ -37,3 +30,10 @@ void GateAnd::compare() { // this->output->setLevel(new_out); // } } + +GateAnd::GateAnd(const GateAnd * prototype) : Node() { } + +GateAnd * GateAnd::clone() const { + return new GateAnd(this); +} + diff --git a/GateAnd.h b/GateAnd.h index 40e3927..5eedc07 100644 --- a/GateAnd.h +++ b/GateAnd.h @@ -4,11 +4,13 @@ class GateAnd : public Node { public: - GateAnd(const char * type); + GateAnd(const GateAnd * prototype); virtual ~GateAnd() = default; virtual void compare(); + virtual GateAnd * clone() const; private: + GateAnd(const char * type); constexpr static const char * type = "and"; static GateAnd instance; }; diff --git a/Node.h b/Node.h index 7f2d03d..43cfc6c 100644 --- a/Node.h +++ b/Node.h @@ -11,14 +11,19 @@ using std::vector; class Node : Observer { public: - Node(const char * type); + Node() = default; virtual ~Node() = default; + virtual Node * clone() const = 0; + +public: void update(); virtual void addInput(Net *); virtual void setOutput(Net *); virtual void compare() = 0; protected: + Node(const char * type); + string label; vector inputs; diff --git a/NodeFactory.cpp b/NodeFactory.cpp index 4824734..c9d4f20 100644 --- a/NodeFactory.cpp +++ b/NodeFactory.cpp @@ -4,26 +4,27 @@ #include "NodeFactory.h" +string NodeFactory::normalize_type(string type) { + std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); + return type; +} + bool NodeFactory::has_type(const char * type) { return has_type(string(type)); } bool NodeFactory::has_type(string type) { - std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); - - static NodeFactoryMap & map = get_map(); - - return map.find(type) != map.end(); + return find_type(type) != nullptr; } void NodeFactory::assign(const char * _type, const Node * node) { static NodeFactoryMap & map = get_map(); string type = _type; + type = normalize_type(type); - std::ranges::transform(type, type.begin(), [] (unsigned char c) { return std::tolower(c); }); - - if (has_type(type)) return; + if (has_type(type)) return; // TODO: exception? + // printf("map[\"%s\"] = %p\n", type.c_str(), node); map[type] = node; } @@ -32,3 +33,16 @@ NodeFactoryMap & NodeFactory::get_map() { return map; } +const Node * NodeFactory::find_type(string type) { + static NodeFactoryMap & map = get_map(); + type = normalize_type(type); + if (!map.contains(type)) return nullptr; + return map.find(type)->second; +} + +Node * NodeFactory::create(string type) { + const Node * prototype = find_type(type); + if (prototype == nullptr) return nullptr; + return prototype->clone(); +} + diff --git a/NodeFactory.h b/NodeFactory.h index 7790b4a..3c8c4f4 100644 --- a/NodeFactory.h +++ b/NodeFactory.h @@ -17,10 +17,13 @@ public: public: static bool has_type(const char * type); static bool has_type(string type); + static Node * create(string type); private: static void assign(const char * type, const Node * node); static NodeFactoryMap & get_map(); + static string normalize_type(string type); + static const Node * find_type(string type); private: friend Node; -- cgit v1.2.3 From 8e0a865dd375baa71357ce817847ea8a9144434c Mon Sep 17 00:00:00 2001 From: UnavailableDev <69792062+UnavailableDev@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:04:35 +0200 Subject: Added design pattern to readme list --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 1703a9f..3ae509d 100644 --- a/readme.md +++ b/readme.md @@ -11,6 +11,7 @@ make - Observer - Low binding factory - Prototype +- Strategy - Dependency injection - vast meer! -- cgit v1.2.3