aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig11
-rw-r--r--.gitignore2
-rw-r--r--Circuit.cpp35
-rw-r--r--Circuit.h27
-rw-r--r--GateAnd.cpp39
-rw-r--r--GateAnd.h17
-rw-r--r--Net.cpp10
-rw-r--r--Net.h14
-rw-r--r--Node.cpp47
-rw-r--r--Node.h38
-rw-r--r--NodeFactory.cpp48
-rw-r--r--NodeFactory.h31
-rw-r--r--Observer.cpp15
-rw-r--r--Observer.h40
-rw-r--r--Parser.cpp101
-rw-r--r--Parser.h45
-rw-r--r--circuits/full-adder.txt12
-rw-r--r--docs/class-diag.puml20
-rw-r--r--main.cpp47
-rw-r--r--makefile4
-rw-r--r--readme.md6
21 files changed, 487 insertions, 122 deletions
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/.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..cf6312e
--- /dev/null
+++ b/Circuit.cpp
@@ -0,0 +1,35 @@
+#include "Circuit.h"
+#include "NodeFactory.h"
+
+void Circuit::create(string label, vector<string> 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) {
+ 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
new file mode 100644
index 0000000..5fd8d23
--- /dev/null
+++ b/Circuit.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "Node.h"
+#include "Net.h"
+
+using std::string;
+using std::vector;
+
+class Circuit {
+public:
+ Circuit() = default;
+ virtual ~Circuit();
+
+public:
+ void create(string label, vector<string> nodes);
+ void new_node(string label, string type);
+ void new_net(string label, string node);
+
+private:
+ std::map<string, Node *> nodes = {};
+ std::map<string, Net *> nets = {};
+};
+
diff --git a/GateAnd.cpp b/GateAnd.cpp
new file mode 100644
index 0000000..dc65353
--- /dev/null
+++ b/GateAnd.cpp
@@ -0,0 +1,39 @@
+#include "GateAnd.h"
+
+GateAnd GateAnd::instance(GateAnd::type);
+
+GateAnd::GateAnd(const char * type) : Node(type) { }
+
+// 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);
+// }
+}
+
+GateAnd::GateAnd(const GateAnd * prototype) : Node() { }
+
+GateAnd * GateAnd::clone() const {
+ return new GateAnd(this);
+}
+
diff --git a/GateAnd.h b/GateAnd.h
new file mode 100644
index 0000000..5eedc07
--- /dev/null
+++ b/GateAnd.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "Node.h"
+
+class GateAnd : public Node {
+public:
+ 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/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..a0fc27b 100644
--- a/Node.cpp
+++ b/Node.cpp
@@ -1,47 +1,22 @@
#include "Node.h"
+#include "NodeFactory.h"
#include <iostream>
-Node::Node(){}
-Node::~Node(){}
-void Node::addInput(Net* net){
- net->attach(this);
+Node::Node(const char * type) {
+ NodeFactory::assign(type, this);
}
+
+void Node::addInput(Net* net) {
+ 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);
- // }
-
-}
diff --git a/Node.h b/Node.h
index f1845a9..43cfc6c 100644
--- a/Node.h
+++ b/Node.h
@@ -1,32 +1,32 @@
#pragma once
+
#include <string>
#include <vector>
#include "Observer.h"
#include "Net.h"
+using std::string;
+using std::vector;
+class Node : Observer {
+public:
+ Node() = default;
+ virtual ~Node() = default;
+ virtual Node * clone() const = 0;
-class Node: Observer {
- protected:
- std::string label;
- std::string type;
+public:
+ void update();
+ virtual void addInput(Net *);
+ virtual void setOutput(Net *);
+ virtual void compare() = 0;
- std::vector<Net*> inputs;
- Net* output;
+protected:
+ Node(const char * type);
- public:
- Node(/* args */);
- virtual ~Node();
- void update();
- virtual void addInput(Net*);
- virtual void setOutput(Net*);
- virtual void compare() = 0;
-};
+ string label;
-class GateAnd: public Node {
- public:
- GateAnd(){};
- ~GateAnd(){};
- void compare();
+ vector<Net *> inputs;
+ Net * output;
};
+
diff --git a/NodeFactory.cpp b/NodeFactory.cpp
new file mode 100644
index 0000000..c9d4f20
--- /dev/null
+++ b/NodeFactory.cpp
@@ -0,0 +1,48 @@
+#include <locale>
+#include <ranges>
+#include <algorithm>
+
+#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) {
+ 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);
+
+ if (has_type(type)) return; // TODO: exception?
+
+ // printf("map[\"%s\"] = %p\n", type.c_str(), node);
+ map[type] = node;
+}
+
+NodeFactoryMap & NodeFactory::get_map() {
+ static NodeFactoryMap 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
new file mode 100644
index 0000000..3c8c4f4
--- /dev/null
+++ b/NodeFactory.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <string>
+#include <map>
+
+#include "Node.h"
+
+using std::string;
+
+using NodeFactoryMap = std::map<string, const Node *>;
+
+class NodeFactory {
+public:
+ NodeFactory() = default;
+ virtual ~NodeFactory() = default;
+
+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;
+};
+
diff --git a/Observer.cpp b/Observer.cpp
index 1e9c9bb..1d96ed4 100644
--- a/Observer.cpp
+++ b/Observer.cpp
@@ -2,22 +2,21 @@
#include <iostream>
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 <vector>
-
class Observer {
- private:
+private:
+
+public:
+ virtual void update();
- public:
- virtual void update();
-
};
class Subject {
- private:
- std::vector<Observer*> 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<Observer*> 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();
+ // }
};
-
-
-
diff --git a/Parser.cpp b/Parser.cpp
new file mode 100644
index 0000000..84c3217
--- /dev/null
+++ b/Parser.cpp
@@ -0,0 +1,101 @@
+#include <cstring>
+#include <sstream>
+#include <cstdarg>
+
+#include "Parser.h"
+
+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);
+}
+
+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::set_circuit(Circuit & circuit) {
+ this->circuit = &circuit;
+}
+
+void Parser::parse(istream & input) {
+ 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<string> nodes;
+ while ((content = strtok(content, ",")) != NULL) {
+ nodes.push_back(content);
+ content = NULL;
+ }
+
+ if (circuit == nullptr) throw ParserException("circuit is not initialized!");
+ circuit->create(label, nodes);
+ }
+}
+
+
+istream & operator >> (istream & s, Parser & parser) {
+ parser.parse(s);
+ return s;
+}
+
+istream & operator << (Parser & parser, istream & s) {
+ parser.parse(s);
+ return s;
+}
+
+void Parser::parse(string input) {
+ std::istringstream s(input);
+ parse(s);
+}
+
diff --git a/Parser.h b/Parser.h
new file mode 100644
index 0000000..3a86eec
--- /dev/null
+++ b/Parser.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <iostream>
+#include <istream>
+#include <exception>
+
+#include "Circuit.h"
+
+using std::istream;
+using std::string;
+
+class ParserException : public std::exception {
+public:
+ ParserException(const char * fmt, ...);
+ virtual ~ParserException();
+ virtual const char * what();
+
+private:
+ char * error = NULL;
+};
+
+class Parser {
+public:
+ Parser() = default;
+ virtual ~Parser() = default;
+
+ void parse(string input);
+ void parse(istream & input);
+
+ /**
+ * \brief preprocess (filter) line of input
+ *
+ * normalize whitespace and remove comments
+ */
+ static size_t filter(char * input);
+
+ void set_circuit(Circuit & circuit);
+
+private:
+ friend istream & operator << (Parser & parser, istream & s);
+ friend istream & operator >> (istream & s, Parser & parser);
+
+ Circuit * circuit;
+};
+
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/docs/class-diag.puml b/docs/class-diag.puml
index 85cb721..5efda1b 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 const char * 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<string label, Net*>
+ - nodes: Map<string label, Node*>
+}
+
+CircuitFactory -[dashed]> Node
+CircuitFactory <-[dashed]- Node
+
@enduml
diff --git a/main.cpp b/main.cpp
index 05ec033..01ddeb7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,17 +1,38 @@
-#include <cstdio>
-// #include "Observer.h"
-#include "Net.h"
-#include "Gate.h"
+#include <iostream>
+#include <fstream>
+
+#include "Parser.h"
+#include "Circuit.h"
+
+using std::cout;
+using std::endl;
+using std::ifstream;
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.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;
+ }
+
+ // 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/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
diff --git a/readme.md b/readme.md
index 218a2e0..3ae509d 100644
--- a/readme.md
+++ b/readme.md
@@ -9,7 +9,11 @@ make
## Applied design patters
- Observer
-- Factory
+- Low binding factory
+- Prototype
+- Strategy
+- Dependency injection
+- vast meer!
## TODO