diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f91889e --- /dev/null +++ b/.clang-format @@ -0,0 +1,209 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RequiresClausePosition: OwnLine +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never + diff --git a/8By8/8By8.ino b/8By8/8By8.ino index 1977ce8..bf584f7 100644 --- a/8By8/8By8.ino +++ b/8By8/8By8.ino @@ -1,64 +1,68 @@ +#include "ListE.h" #include "TimerOne.h" +#include #define TIME_PER_LAYER_IN_US 800 #define BUS_START_PIN 22 #define CLOCK_START_PIN 30 #define SW_START_PIN 38 +#define DEBUG false + class Cube { private: - static int layer_count; - static int brightness_count; + static int layer_count; + static int brightness_count; public: - // Every int represents a row of 8 LED status. - static int LED_status[8][8]; + // Every int represents a row of 8 LED status. + static int LED_status[8][8]; - static void display() { - // Serial.println("Here"); - if (brightness_count >= 2) { - digitalWrite(SW_START_PIN + layer_count, LOW); - layer_count = (layer_count + 1) % 8; + static void display() { + // Serial.println("Here"); + if (brightness_count >= 2) { + digitalWrite(SW_START_PIN + layer_count, LOW); + layer_count = (layer_count + 1) % 8; + } + + brightness_count = (brightness_count + 1) % 3; + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + // In LED_status: + // 0 = off + // 4 = brightest + digitalWrite(BUS_START_PIN + j, + ((LED_status[layer_count][i] >> (j * 2)) & 3) >= + (3 - brightness_count)); + } + digitalWrite(CLOCK_START_PIN + i, HIGH); + digitalWrite(CLOCK_START_PIN + i, LOW); + } + + digitalWrite(SW_START_PIN + layer_count, HIGH); } - brightness_count = (brightness_count + 1) % 3; - - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 8; j++) { - // In LED_status: - // 0 = off - // 4 = brightest - digitalWrite(BUS_START_PIN + j, - ((LED_status[layer_count][i] >> (j * 2)) & 3) >= - (3 - brightness_count)); - } - digitalWrite(CLOCK_START_PIN + i, HIGH); - digitalWrite(CLOCK_START_PIN + i, LOW); + static void set_status(int x, int y, int z, int brightness) { + if (x >= 8 || x < 0 || y >= 8 || y < 0 || z >= 8 || z < 0) { + return; + } + brightness %= 4; + LED_status[z][x] = + (LED_status[z][x] & (~(3 << (y * 2)))) | (brightness << (y * 2)); } - digitalWrite(SW_START_PIN + layer_count, HIGH); - } - - static void set_status(int x, int y, int z, int brightness) { - if (x >= 8 || x < 0 || y >= 8 || y < 0 || z >= 8 || z < 0) { - return; + static int get_status(int x, int y, int z) { + return LED_status[z][x] >> (y * 2) & 3; } - brightness %= 4; - LED_status[z][x] = - (LED_status[z][x] & (~(3 << (y * 2)))) | (brightness << (y * 2)); - } - static int get_status(int x, int y, int z) { - return LED_status[z][x] >> (y * 2) & 3; - } - - static void clear() { - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 8; j++) { - LED_status[i][j] = 0; - } + static void clear() { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + LED_status[i][j] = 0; + } + } } - } }; int Cube::layer_count = 0; @@ -66,25 +70,420 @@ int Cube::brightness_count = 0; int Cube::LED_status[8][8] = {0}; int bright = 3; -void setup() { - for (int i = 22; i < 46; i++) { - pinMode(i, OUTPUT); - } +enum Operators { + plus, + minus, + multiply, + divide, + power, + left_parenthesis, + right_parenthesis, +}; - Timer1.initialize(); - Timer1.setPeriod(TIME_PER_LAYER_IN_US); - Timer1.attachInterrupt(Cube::display); +enum CompareResult { + less, + equal, + greater, +}; - Serial.begin(115200); +class Symbol { +private: + bool is_symbol; + String name; + double value; - for (int x = 0; x < 8; x++) { - for (int y = 0; y < 8; y++) { - Cube::set_status(x, y, sqrt((x - 3) * (x - 3) + (y - 3) * (y - 3)), 3); +public: + static double *x_value_ptr, *y_value_ptr; + Symbol(String symbol_name) { + this->is_symbol = true; + this->name = symbol_name; } - } + Symbol(double new_value) { + this->is_symbol = false; + this->value = new_value; + } + + double get_value() const { + if (this->is_symbol) { + if (this->name == "x") { + return *x_value_ptr; + } + else if (this->name == "y") { + return *y_value_ptr; + } + } + + return this->value; + } +}; + +class Operator { +private: + Operators name; + +public: + Operator(const char op) { + if ('+' == op) { + this->name = plus; + } + else if ('-' == op) { + this->name = minus; + } + else if ('*' == op) { + this->name = multiply; + } + else if ('/' == op) { + this->name = divide; + } + else if ('^' == op) { + this->name = power; + } + else if ('(' == op) { + this->name = left_parenthesis; + } + else if (')' == op) { + this->name = right_parenthesis; + } + } + + CompareResult compare(const Operator &other_operator) { + int self_priority, other_priority; + if (this->name == plus || this->name == minus) { + self_priority = 2; + } + else if (this->name == multiply || this->name == divide) { + self_priority = 4; + } + else if (this->name == power) { + self_priority = 6; + } + else if (this->name == left_parenthesis) { + self_priority = 8; + } + else if (this->name == right_parenthesis) { + self_priority = 1; + } + + if (other_operator.name == plus || other_operator.name == minus) { + other_priority = 3; + } + else if (other_operator.name == multiply || + other_operator.name == divide) { + other_priority = 5; + } + else if (other_operator.name == power) { + other_priority = 7; + } + else if (other_operator.name == left_parenthesis) { + other_priority = 1; + } + else if (other_operator.name == right_parenthesis) { + other_priority = 9; + } + + if (self_priority < other_priority) { + return less; + } + else if (self_priority == other_priority) { + return equal; + } + else { + return greater; + } + } + + Symbol calc(const Symbol first_pop, const Symbol second_pop) { + if (this->name == plus) { + return Symbol(first_pop.get_value() + second_pop.get_value()); + } + else if (this->name == minus) { + return Symbol(second_pop.get_value() - first_pop.get_value()); + } + else if (this->name == multiply) { + return Symbol(first_pop.get_value() * second_pop.get_value()); + } + else if (this->name == divide) { + if (abs(first_pop.get_value()) <= 1e-5) { + return Symbol(atof("inf")); + } + return Symbol(second_pop.get_value() / first_pop.get_value()); + } + else if (this->name == power) { + return Symbol(pow(second_pop.get_value(), first_pop.get_value())); + } + + return 0.0; + } + + bool operator==(Operators op) { + return this->name == op; + } + + char display() { + switch (this->name) { + case plus: + return '+'; + case minus: + return '-'; + case multiply: + return '*'; + case divide: + return '/'; + case power: + return '^'; + case left_parenthesis: + return '('; + case right_parenthesis: + return ')'; + } + } +}; + +class Calculator { +private: + String expression; + List number_stack; + List operator_stack; + int left_parenthesis_count; + void calculate() { + Operator operation = this->operator_stack.pop(); + // this->operator_stack.pop(); + Symbol number1 = this->number_stack.pop(); + // this->number_stack.pop(); + Symbol number2 = this->number_stack.pop(); + // this->number_stack.pop(); + + this->number_stack.append(operation.calc(number1, number2)); + } + +public: + Calculator(const String expression) { + this->expression = expression + ')'; + } + + double evaluate() { + this->number_stack.clear(); + + this->operator_stack.clear(); + + this->operator_stack.append(Operator('(')); + this->left_parenthesis_count = 1; + + char operator_chars[] = "+-*/^()"; + int operator_pos = -1; + while (true) { + if (DEBUG) { + Serial.println("A"); + Serial.print("Operator pos: "); + Serial.println(operator_pos); + Serial.println("Number stack: "); + for (int i = 0; i < this->number_stack.length(); i++) { + Serial.println(this->number_stack[i].get_value()); + } + Serial.println("Operator stack: "); + for (int i = 0; i < this->operator_stack.length(); i++) { + Serial.println(this->operator_stack[i].display()); + } + } + + bool found_next_operator = false; + int first_char_of_num = operator_pos + 1; + // operator_pos = + // this->expression.indexOf(operator_chars, operator_pos + 1); + + operator_pos = this->expression.length(); + + for (int i = 0; i < sizeof(operator_chars); i++) { + int current_operator_pos = this->expression.indexOf( + operator_chars[i], first_char_of_num); + if (current_operator_pos < operator_pos && + current_operator_pos >= 0) { + found_next_operator = true; + operator_pos = current_operator_pos; + } + } + + if (!found_next_operator) { + break; + } + + // Find the operator position + if (DEBUG) { + Serial.println("B"); + Serial.print("Operator pos: "); + Serial.println(operator_pos); + Serial.println("Number stack: "); + for (int i = 0; i < this->number_stack.length(); i++) { + Serial.println(this->number_stack[i].get_value()); + } + Serial.println("Operator stack: "); + for (int i = 0; i < this->operator_stack.length(); i++) { + Serial.println(this->operator_stack[i].display()); + } + } + + if (operator_pos != first_char_of_num) { + String number = + this->expression.substring(first_char_of_num, operator_pos); + if (number == "x" || number == "y") { + this->number_stack.append(Symbol(number)); + } + else { + this->number_stack.append(Symbol(atof(number.c_str()))); + } + } + else if (this->expression[operator_pos] == '-' && + this->number_stack.length() == + this->operator_stack.length() - + this->left_parenthesis_count) { + this->number_stack.append(0.0); + } + + // Understand the number and push to stack + if (DEBUG) { + Serial.println("C"); + Serial.print("Operator pos: "); + Serial.println(operator_pos); + Serial.println("Number stack: "); + for (int i = 0; i < this->number_stack.length(); i++) { + Serial.println(this->number_stack[i].get_value()); + } + Serial.println("Operator stack: "); + for (int i = 0; i < this->operator_stack.length(); i++) { + Serial.println(this->operator_stack[i].display()); + } + } + + Operator current_operator(this->expression[operator_pos]); + if (current_operator == left_parenthesis) { + this->left_parenthesis_count += 1; + } + + // Understand the operator + if (DEBUG) { + Serial.println("D"); + Serial.print("Read operator: "); + Serial.println(current_operator.display()); + Serial.print("Operator pos: "); + Serial.println(operator_pos); + Serial.println("Number stack: "); + for (int i = 0; i < this->number_stack.length(); i++) { + Serial.println(this->number_stack[i].get_value()); + } + Serial.println("Operator stack: "); + for (int i = 0; i < this->operator_stack.length(); i++) { + Serial.println(this->operator_stack[i].display()); + } + } + + switch (current_operator.compare(this->operator_stack.peek())) { + case greater: + // Serial.println("Choose greater"); + this->operator_stack.append(current_operator); + break; + case equal: + // Serial.println("Choose equal"); + this->operator_stack.pop(); + this->left_parenthesis_count -= 1; + break; + case less: + // Serial.println("Choose less"); + if (this->number_stack.length() < 2) { + // Error + return atof("nan"); + } + // Serial.println("Into Calc"); + + this->calculate(); + + // Serial.println("Out Calc"); + // We only dealt with previous operators. Need to go through + // this operator again. + operator_pos--; + break; + } + + if (DEBUG) { + Serial.println("E"); + Serial.print("Operator pos: "); + Serial.println(operator_pos); + Serial.println("Number stack: "); + for (int i = 0; i < this->number_stack.length(); i++) { + Serial.println(this->number_stack[i].get_value()); + } + Serial.println("Operator stack: "); + for (int i = 0; i < this->operator_stack.length(); i++) { + Serial.println(this->operator_stack[i].display()); + } + } + } + + if (this->left_parenthesis_count != 0) { + return 0.0; + } + return this->number_stack.peek().get_value(); + } +}; + +double *Symbol::x_value_ptr, *Symbol::y_value_ptr; + +double x, y; + +void setup() { + for (int i = 22; i < 46; i++) { + pinMode(i, OUTPUT); + } + + Timer1.initialize(); + Timer1.setPeriod(TIME_PER_LAYER_IN_US); + Timer1.attachInterrupt(Cube::display); + + Serial.begin(9600); + Symbol::x_value_ptr = &x; + Symbol::y_value_ptr = &y; } - void loop() { + String input = ""; + String allowed_chars = "0123456789+-*/^()xy"; + while (true) { + if (Serial.available()) { + byte input_char = Serial.read(); + // Serial.print("Pos: "); + // Serial.println(allowed_chars.indexOf(input_char)); + if (allowed_chars.indexOf(input_char) != -1) { + input.concat((char)input_char); + // Serial.print("String: "); + // Serial.println(input); + continue; + } + if (input_char == 0x3) { + break; + } + } + } + Serial.print("Read: "); + Serial.println(input); + Calculator calculator(input); + + Cube::clear(); + for (x = 0; x < 8; x++) { + for (y = 0; y < 8; y++) { + double result = calculator.evaluate(); + int z; + if (!(isinf(result) || isnan(result))) { + z = round(result); + Cube::set_status(x, y, z, 3); + } + Serial.print(x); + Serial.print(" "); + Serial.print(y); + Serial.print(" "); + Serial.println(z); + } + } + // int z = round(calculator.evaluate()); + // Serial.println(z); + Serial.print("Here"); } \ No newline at end of file diff --git a/8By8/ListE.h b/8By8/ListE.h new file mode 100644 index 0000000..8482a4a --- /dev/null +++ b/8By8/ListE.h @@ -0,0 +1,148 @@ +#include "Node.h" + +template class List { +private: + Node *head; + int _length; + int getIndexInRange(int index) const; + +public: + List(); + List(const E &newItem); + List(const E *newItemList, const int itemCount); + List(const List &otherList); + ~List(); + // Append _newItem at last. Returns the List itself. + List &append(const E &_newItem); + // Throws IndexError if index is not in the range of [-_length, _length - + // 1]. Returns the List itself. + E pop(); + // Clear all nodes. + List &clear(); + const E &peek() const; + List &operator=(const List &otherList); + E &operator[](const int index); + const E &operator[](const int index) const; + + int length() const; + + bool empty() const; +}; + +template int List::getIndexInRange(int index) const { + if (index < 0) { + index += this->_length; + } + if (index < 0 || index >= _length) { + return -1; + } + return index; +} + +template List::List() : head(NULL), _length(0){}; + +template +List::List(const E &newItem) : head(new Node(newItem)), _length(1){}; + +template List::List(const E *newItemList, const int itemCount) { + for (int i = 0; i < itemCount; i++) { + this->append(newItemList[i]); + } +}; + +template List::List(const List &otherList) { + if (otherList.length() > 0) { + this->head = new Node(otherList[0]); + this->_length = 1; + Node *nextPtr = otherList.head->getNextPtr(); + while (nextPtr != NULL) { + this->append((*nextPtr).getContent()); + nextPtr = (*nextPtr).getNextPtr(); + } + } + else { + this->head = NULL; + this->_length = 0; + } +} + +template List::~List() { + if (this->head != NULL) { + this->head->destruct(); + } + head = NULL; +} + +template List &List::append(const E &_newItem) { + if (this->head == NULL) { + this->head = new Node(_newItem); + } + else { + this->head->getTail().setNext(new Node(_newItem)); + } + this->_length++; + return *this; +} + +template E List::pop() { + int index = this->_length - 1; + + Node removed = this->head->getByIndex(index); + + this->_length--; + if (index == 0) { + Node *newHead = this->head->getNextPtr(); + delete this->head; + this->head = newHead; + } + else { + Node &prev = this->head->getByIndex(index - 1); + delete prev.getNextPtr(); + prev.setNext(removed.getNextPtr()); + } + return removed.getContent(); +} + +template List &List::clear() { + if (this->_length == 0) { + return *this; + } + this->head->destruct(); + this->head = NULL; + this->_length = 0; + return *this; +} + +template const E&List::peek() const { + return this->head->getByIndex(this->_length - 1).getContent(); +} + +template List &List::operator=(const List &otherList) { + this->clear(); + if (otherList.length() > 0) { + this->head = new Node(otherList[0]); + this->_length = 1; + Node *nextPtr = otherList.head->getNextPtr(); + while (nextPtr != NULL) { + this->append((*nextPtr).getContent()); + nextPtr = (*nextPtr).getNextPtr(); + } + } + return *this; +} + +template E &List::operator[](const int index) { + return this->head->getByIndex(index).getContent(); +} + +template const E &List::operator[](const int index) const { + return this->head->getByIndex(index).getContent(); +} + +template int List::length() const { + return this->_length; +} + +template bool List::empty() const { + return this->_length == 0; +} diff --git a/8By8/Node.h b/8By8/Node.h new file mode 100644 index 0000000..7cbb3a0 --- /dev/null +++ b/8By8/Node.h @@ -0,0 +1,105 @@ +#pragma once + +template class Node { +private: + E content; + Node *nextNode; + +public: + Node(); + Node(E _content, Node *_nextNode = NULL); + ~Node(); + // Returns a reference to the content. + E &getContent(); + // Returns a reference to the next Node. May return NULL if this Node is the + // last one. + Node *getNextPtr(); + // Set the next Node _nextNode. Returns original pointer. + Node *setNext(Node *_nextNode); + // Returns a reference to the Tail. + Node &getTail(); + // Returns a reference to the Node of given index. + Node &getByIndex(const int index); + // Compare the content with the argument. + bool operator==(const E &other); + // Destructs the Node itself and all the node behind it. + void destruct(); +}; + +template class Iterator { +private: + Node *current; + +public: + Iterator(Node *pos); + bool hasNext(); + // Return the same as hasNext(); + operator bool(); + E &next(); +}; + +template Node::Node() : content(0), nextNode(NULL){}; + +template +Node::Node(E _content, Node *_nextNode) + : content(_content), nextNode(_nextNode){}; + +template Node::~Node(){}; + +template E &Node::getContent() { + return this->content; +} + +template Node *Node::getNextPtr() { + return this->nextNode; +} + +template Node *Node::setNext(Node *_nextNode) { + Node *temp = this->nextNode; + this->nextNode = _nextNode; + return temp; +} + +template Node &Node::getTail() { + if (this->nextNode == NULL) { + return *this; + } + return this->nextNode->getTail(); +} + +template Node &Node::getByIndex(const int index) { + if (index == 0) { + return *this; + } + return this->nextNode->getByIndex(index - 1); +} + +template bool Node::operator==(const E &other) { + return this->content == other; +} + +template void Node::destruct() { + if (this->nextNode != NULL) { + this->nextNode->destruct(); + } + delete this; +} + +template Iterator::Iterator(Node *start) : current(start){}; + +template bool Iterator::hasNext() { + return this->current != NULL; +} + +template Iterator::operator bool() { + return this->hasNext(); +} + +template E &Iterator::next() { + if (!this->hasNext()) { + throw(IndexError("Out of bound!")); + } + E &temp = this->current->getContent(); + this->current = this->current->getNextPtr(); + return temp; +} \ No newline at end of file