Summary Files Commits Branches @commit @diff @stats
path: root / Year 1 / Object-oriented Programming / Project 2 / src / Generic / ConsoleInterface
diff options
context:
space:
mode:
Commitc5431e4d321dbf0152e6826841c1ef5c1291ba5b (patch)
Author
 Syndamia <kamen@syndamia.com>
2022-06-14 15:38:50 +0300
Committer
 Syndamia <kamen@syndamia.com>
2022-06-14 15:38:50 +0300
Filesbe7dbd4b6188924bb3a1a9398169526f236b09b9 /Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface
uni-projects-c5431e4d321dbf0152e6826841c1ef5c1291ba5b.tar
uni-projects-c5431e4d321dbf0152e6826841c1ef5c1291ba5b.tar.gz
uni-projects-c5431e4d321dbf0152e6826841c1ef5c1291ba5b.zip
Parentccedf6f5d89f375580ff6af40296aab953f9cd09 (diff)
Added files from project 2 (mirror)
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Command.cpp b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Command.cpp
new file mode 100644
index 0000000..d05dc8d
--- /dev/null
+++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Command.cpp
@@ -0,0 +1,24 @@
+#include "Command.h"
+#include <cstring>
+
+Command::Command() : Command("", nullptr) {}
+
+/*! \param name C-style string, class stores at most 255 characters (last character is always terminating zero)
+ * \param exec Function pointer that will be executed when run() is called. Can be nullptr.
+ */
+Command::Command(const char* name, void (*exec)(const char* params)) {
+ strncpy(this->name, name, 255);
+ this->name[255] = '\0';
+ this->exec = exec;
+}
+
+/*! Executes the stored function pointer, when it's not nullptr. Otherwise does nothing.
+ */
+void Command::run(const char* params) const {
+ if (exec != nullptr)
+ exec(params);
+}
+
+const char* Command::get_name() const {
+ return name;
+}
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Command.h b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Command.h
new file mode 100644
index 0000000..393d705
--- /dev/null
+++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Command.h
@@ -0,0 +1,27 @@
+#ifndef HEADER_CONSOLEINTERFACE_COMMAND
+#define HEADER_CONSOLEINTERFACE_COMMAND
+
+/*! \file Command.h
+ * \brief Stores the declaration of class Command
+ */
+
+/*! \brief Stores a 256 character name and a function pointer to be executed when calling run()
+ *
+ * Menu uses this class for a more generic implementation of it's navigate function.
+ */
+class Command {
+ char name[256];
+ void (*exec)(const char* params);
+
+public:
+ //! Leaves name empty and exec function pointer to nullptr
+ Command();
+ //! Copies contents of nameInMenu and stores exec
+ Command(const char* name, void (*exec)(const char* params));
+ //! Executes the stored function pointer
+ void run(const char* params) const;
+
+ const char* get_name() const;
+};
+
+#endif
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Menu.cpp b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Menu.cpp
new file mode 100644
index 0000000..9c2fca5
--- /dev/null
+++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Menu.cpp
@@ -0,0 +1,72 @@
+#include "Menu.h"
+#include "Toolbox.hpp"
+#include <cstring>
+
+Menu::Menu() : menuOptions() {}
+
+unsigned indexOfCommandEnd(char* str) {
+ unsigned ind = 0;
+ std::cout << str[ind] << std::endl;
+
+ return ind;
+}
+
+void Menu::addCommand(const Command& command) {
+ menuOptions.add(command);
+}
+
+/*!
+ * Prints the title, then an Error/Warning/Sucess message (if set),
+ * prints all command names as an ordered list (starting from 1),
+ * waits for user input to select one of those commands (by list number)
+ * and finally executes the appropriate command's run() function.
+ *
+ * After the run() function exists, everything is reprinted.
+ * The 0 list index is always "Go Back"/"Exit" and it always stops the reprinting loop.
+ *
+ * If there are no commands, prints "Menu is empty!".
+ * If user input doesn't correspond to any command, registers an error message and reprints.
+ */
+void Menu::navigate() const {
+ if (menuOptions.get_count() == 0) {
+ printLine("Menu is empty!");
+ return;
+ }
+
+ char buffer[MAX_LINE_WIDTH];
+
+ unsigned startIndex, commandEnd, paramsStart, index;
+ bool hasThrown = false;
+ while (!hasThrown) {
+ startIndex = 0;
+ inputLineBox(buffer, MAX_LINE_WIDTH, false);
+
+ while (buffer[startIndex] == ' ') startIndex++;
+
+ commandEnd = startIndex;
+ while (buffer[commandEnd] != ' ' && buffer[commandEnd] != '\n' && buffer[commandEnd] != '\0')
+ commandEnd++;
+
+ index = menuOptions.get_count();
+ for (unsigned i = 0; i < menuOptions.get_count() && index == menuOptions.get_count(); i++) {
+ if (strncmp(buffer + startIndex, menuOptions[i].get_name(), commandEnd - startIndex) == 0)
+ index = i;
+ }
+
+ paramsStart = startIndex + commandEnd;
+ while (buffer[paramsStart] == ' ') paramsStart++;
+
+ if (index == menuOptions.get_count()) {
+ printLine("Invalid menu option!");
+ continue;
+ }
+
+ try {
+ menuOptions[index].run(buffer + paramsStart);
+ }
+ catch (std::logic_error err) {
+ hasThrown = true;
+ printLine(err.what());
+ }
+ }
+}
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Menu.h b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Menu.h
new file mode 100644
index 0000000..faadba9
--- /dev/null
+++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Menu.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CONSOLEINTERFACE_MENU
+#define HEADER_CONSOLEINTERFACE_MENU
+
+/*! \file Menu.h
+ * \brief Stores the declaration of class Menu
+ */
+
+#include "Command.h"
+#include "../List/List.hpp"
+
+/*! \brief Handles navigation between multiple commands
+ *
+ * Shows the title, then below it an Error/Warning/Success message if set,
+ * lists all command options as an enumerated list, takes command index
+ * and calls the chosen command's run() function.
+ */
+class Menu {
+ List<Command> menuOptions;
+
+public:
+ //! Sets name as "Menu", leaves all flags to false and creates an empty Command list
+ Menu();
+ //! Copies commands
+ Menu(const Command* commands, unsigned commandCount);
+
+ //! Adds a command to the internal Command list
+ void addCommand(const Command& command);
+
+ //! Lists commands and after user input executes an appropriate command run() function
+ void navigate() const;
+};
+
+#endif
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Toolbox.cpp b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Toolbox.cpp
new file mode 100644
index 0000000..ca739f0
--- /dev/null
+++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Toolbox.cpp
@@ -0,0 +1,88 @@
+#include "Toolbox.hpp"
+
+/* Input line boxes */
+
+void __inputLineBoxGetInput(char* output, unsigned maxWidth, bool ignore) {
+ if (ignore)
+ std::cin.ignore();
+ std::cin.getline(output, maxWidth);
+}
+
+/*! \param label C-style string, there are no size check so it could wrap
+ * \param output Pointer to a char array
+ * \param maxWidth Maximum count of characters to read from user input. output MUST be able to hold that many characters!
+ * \param ignore Whether or not to ignore the first new-line delimiter.
+ * true by default, should be set to false only when an inputLineBox/SubBox has been issued directly prior or when it's the very first issued box command.
+ *
+ * Prints "(+)" before the label.
+ */
+void inputLineBox(char* output, unsigned maxWidth, bool ignore) {
+ print("> ");
+ __inputLineBoxGetInput(output, maxWidth, ignore);
+}
+
+/* Table */
+
+void __printTableHeaderNumber(unsigned number) {
+ std::cout << ":" << ((number < 100) ? " " : "") << number << ((number < 10) ? " " : "");
+}
+
+void __printTableColumnHeader(unsigned count, unsigned start = 1) {
+ std::cout << ": ";
+ for (unsigned i = 0; i < count; i++)
+ __printTableHeaderNumber(start++);
+ std::cout << ":" << std::endl;
+
+ for (unsigned i = 0; i <= count; i++)
+ std::cout << "====";
+ std::cout << "=" << std::endl;
+}
+
+void __printTableLine(unsigned columns) {
+ std::cout << ":===";
+ for (unsigned i = 0; i < columns; i++)
+ std::cout << "+---";
+ std::cout << ":" << std::endl;
+}
+
+void __printPadded(const String& str, unsigned width) {
+ while (width - str.get_length() > 0) {
+ width--;
+ print(" ");
+ }
+ print(str.get_cstr());
+}
+
+/*! \param startNumber The number by which column and row enumeration begins
+ * \param columns How many columns the table should have
+ * \param items C-style string, each cell is a single character from the string
+ *
+ * Prints a string as a grid/table of characters from top to bottom, left to right.
+ * The first character is on the top left, the last one is on the bottom right.
+ *
+ * Table is printed until a terminating zero is encountered.
+ * The rows are "calculated" from the columns count and the items length.
+ */
+void printTable(const List<String>& items, unsigned columns) {
+ unsigned *colWidths = new unsigned[columns];
+ for (unsigned i = 0; i < columns; i++)
+ colWidths[i] = 0;
+
+ for (unsigned i = 0; i < items.get_count(); i++) {
+ if (colWidths[i % columns] < items[i].get_length())
+ colWidths[i % columns] = items[i].get_length();
+ }
+
+ // __printTableColumnHeader(columns);
+
+ for (unsigned i = 0; i < items.get_count(); i++) {
+ __printPadded(items[i], colWidths[i % columns]);
+ if (i % columns == columns - 1)
+ printLine("");
+ else
+ print("|");
+ }
+
+ delete[] colWidths;
+}
+
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Toolbox.hpp b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Toolbox.hpp
new file mode 100644
index 0000000..4b59626
--- /dev/null
+++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/ConsoleInterface/Toolbox.hpp
@@ -0,0 +1,60 @@
+#ifndef HEADER_CONSOLEINTERFACE_TOOLBOX
+#define HEADER_CONSOLEINTERFACE_TOOLBOX
+
+#include <iostream>
+#include "../List/List.hpp"
+#include "../String/String.h"
+
+/*! \file Toolbox.hpp
+ * \brief Stores a wide range of functions for simpler/more automated printing.
+ *
+ * Adds a lot of functions for printing.
+ *
+ * \remark iostream is included by necessity (templated functions), you should only use the provided functions, if you can.
+ */
+
+#define MAX_LINE_WIDTH 1024
+
+//! Prints label, gets a whole line of input and stores it to output
+void inputLineBox(char* output, unsigned maxWidth, bool ignore = true);
+
+//! Prints a string list as a table
+void printTable(const List<String>& items, unsigned columns);
+
+//! Reads user input and stores it
+template <typename T>
+void read(T* storage) {
+ std::cin >> storage;
+}
+
+//! Reads user input and stores it
+template <typename T>
+void read(T& storage) {
+ std::cin >> storage;
+}
+
+//! Prints given item
+template <typename T>
+void print(const T* item) {
+ std::cout << item;
+}
+
+//! Prints given item
+template <typename T>
+void print(const T& item) {
+ std::cout << item;
+}
+
+//! Prints given item and an endline character
+template <typename T>
+void printLine(const T* item) {
+ std::cout << item << std::endl;
+}
+
+//! Prints given item and an endline character
+template <typename T>
+void printLine(const T& item) {
+ std::cout << item << std::endl;
+}
+
+#endif