From 757a5c123fd83e790c138a76546a974bbfaf79a8 Mon Sep 17 00:00:00 2001 From: moonleay Date: Sun, 9 Feb 2025 12:34:07 +0100 Subject: [PATCH] feat: got loading working, implemented saving --- Assignment.cpp | 40 +++++++++++++++++ Assignment.h | 27 ++++++++++++ DataType.h | 15 +++++++ FileError.h | 20 +++++++++ FormatError.h | 20 +++++++++ Manager.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++++ Manager.h | 36 ++++++++++++++++ Model.cpp | 15 ------- Model.h | 16 ------- Task.cpp | 31 +++++++++++++- Task.h | 42 ++++++++++++++++-- User.cpp | 43 ++++++++++++++++--- User.h | 22 ++++++++-- UserTaskIndex.cpp | 5 --- UserTaskIndex.h | 19 -------- Util.cpp | 68 +++++++++++++++++++++++++++++ Util.h | 14 ++++++ main.cpp | 36 ++++++++++++---- 18 files changed, 498 insertions(+), 78 deletions(-) create mode 100644 Assignment.cpp create mode 100644 Assignment.h create mode 100644 DataType.h create mode 100644 FileError.h create mode 100644 FormatError.h create mode 100644 Manager.cpp create mode 100644 Manager.h delete mode 100644 Model.cpp delete mode 100644 Model.h delete mode 100644 UserTaskIndex.cpp delete mode 100644 UserTaskIndex.h create mode 100644 Util.cpp create mode 100644 Util.h diff --git a/Assignment.cpp b/Assignment.cpp new file mode 100644 index 0000000..990a80a --- /dev/null +++ b/Assignment.cpp @@ -0,0 +1,40 @@ +#include "Assignment.h" +#include "FormatError.h" + +using err::FormatError; + +namespace models { + Assignment::Assignment(const int& user_id, const int& task_id) : user_id(user_id), task_id(task_id) {} + Assignment::Assignment(): user_id(0), task_id(0) {} + + ostream& Assignment::write(ostream& stream) { + stream << this; + return stream; + } + + int Assignment::get_task_id() const { + return this->task_id; + } + + int Assignment::get_user_id() const { + return this->user_id; + } + + ostream& operator<<(ostream& os, const Assignment& t) { + os << t.get_user_id() << " " << t.get_task_id(); + return os; + } + + istream& operator>>(istream& is, Assignment& t) { + int user_id; + is >> user_id; + if (!is) + throw FormatError("Userid Nan"); + int task_id; + is >> task_id; + if (!is) + throw FormatError("Taskid Nan"); + t = {user_id, task_id}; + return is; + } +} diff --git a/Assignment.h b/Assignment.h new file mode 100644 index 0000000..69f0f76 --- /dev/null +++ b/Assignment.h @@ -0,0 +1,27 @@ +#include "std_lib_inc.h" +#ifndef ASSIGNMENT_H +#define ASSIGNMENT_H + +namespace models { + class Assignment { + private: + int user_id; + int task_id; + public: + Assignment(const int& user_id, const int& task_id); + Assignment(); + ostream& write(ostream& stream); + + int get_user_id() const; + int get_task_id() const; + + friend ostream& operator<<(ostream& os, const Assignment& t); + friend istream& operator>>(istream& is, Assignment& t); + }; + + ostream& operator<<(ostream& os, const Assignment& t); + istream& operator>>(istream& is, Assignment& t); +} + +#endif // ASSIGNMENT_H + diff --git a/DataType.h b/DataType.h new file mode 100644 index 0000000..40b8667 --- /dev/null +++ b/DataType.h @@ -0,0 +1,15 @@ +#include "std_lib_inc.h" +#ifndef READINSTATUS_H +#define READINSTATUS_H + +namespace util { + enum class DataType { + INIT, + USER, + TASK, + USERTASKINDEX + }; +} + +#endif // READINSTATUS_H + diff --git a/FileError.h b/FileError.h new file mode 100644 index 0000000..4505ff9 --- /dev/null +++ b/FileError.h @@ -0,0 +1,20 @@ +#include "std_lib_inc.h" +#include +#ifndef FILEERROR_H +#define FILEERROR_H + +namespace err { + class FileError : public exception { + private: + string what; + + public: + FileError(const string& msg) : exception(), what(msg) {} + string why() { + return this->what; + } + }; +} + +#endif // FILEERROR_H + diff --git a/FormatError.h b/FormatError.h new file mode 100644 index 0000000..95078cc --- /dev/null +++ b/FormatError.h @@ -0,0 +1,20 @@ +#include "std_lib_inc.h" +#include +#ifndef FORMATERROR_H +#define FORMATERROR_H + +namespace err { + class FormatError : public exception { + private: + string what; + + public: + FormatError(const string& msg) : exception(), what(msg) {} + string why() { + return this->what; + } + }; +} + +#endif // FORMATERROR_H + diff --git a/Manager.cpp b/Manager.cpp new file mode 100644 index 0000000..458a3ed --- /dev/null +++ b/Manager.cpp @@ -0,0 +1,107 @@ +#include "Manager.h" +#include "FileError.h" +#include + +using err::FileError; +using util::DataType; + +namespace util { + Manager::Manager(): users({}), tasks({}), user_task_index({}), filename("tasks") { + ifstream in (this->filename); + if (!in) + { + // throw FileError("Could not open file input stream!"); + this->save(); + in.clear(); + in.open(this->filename); + if (!in) + throw FileError("Could not open file input stream!"); + } + DataType current_type = DataType::INIT; + string d; + char c; + while(true) { + in >> c; + if (in.eof() || c == EOF) + break; + if (c == '\n') + { + in >> d; + continue; + } + if (c == '['){ + switch (current_type) + { + case DataType::INIT: + current_type = DataType::TASK; + break; + case DataType::TASK: + current_type = DataType::USER; + break; + case DataType::USER: + current_type = DataType::USERTASKINDEX; + break; + case DataType::USERTASKINDEX: + break; // This should not happen. There is nothing after [assignments] + } + in >> d; + continue; + } + in.putback(c); + switch (current_type) { + case DataType::INIT: + break; + case DataType::TASK: + { + Task t; + in >> t; + this->tasks.push_back(t); + } + break; + case DataType::USER: + { + User u; + in >> u; + this->users.push_back(u); + } + break; + case DataType::USERTASKINDEX: + { + Assignment a; + in >> a; + this->user_task_index.push_back(a); + } + break; + } + } + in.close(); + } + + void Manager::save() { + ofstream out = ofstream(this->filename); + if (!out) + throw FileError("Could not open file output stream!"); + out << "[tasks]\n"; + for (Task& t : this->tasks) + t.write(out); + out << "\n[users]\n"; + for (User& u : this->users) + u.write(out); + out << "\n[assignments]\n"; + for (Assignment& uti: this->user_task_index) + uti.write(out); + out.close(); + } + + vector Manager::get_users() const { + return this->users; + } + + vector Manager::get_task() const { + return this->tasks; + } + + vector Manager::get_user_task_index() const { + return this->user_task_index; + } +} diff --git a/Manager.h b/Manager.h new file mode 100644 index 0000000..98e9eb9 --- /dev/null +++ b/Manager.h @@ -0,0 +1,36 @@ +#include "std_lib_inc.h" +#include "User.h" +#include "Task.h" +#include "Assignment.h" +#include "DataType.h" +#ifndef ENVIRONMENT_H +#define ENVIRONMENT_H + +using models::User; +using models::Task; +using models::Assignment; + +namespace util { + class Manager { + private: + vector users; + vector tasks; + vector user_task_index; + string filename; + + public: + Manager(); + + void save(); + + vector get_users() const; + vector get_task() const; + vector get_user_task_index() const; + }; + + + inline DataType operator++(DataType& status); +} + +#endif // ENVIRONMENT_H + diff --git a/Model.cpp b/Model.cpp deleted file mode 100644 index 4c82500..0000000 --- a/Model.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "Model.h" - -namespace models { - Model::Model() {} - - Model* Model::operator>>(stringstream& stream) { - cout << "Default << operator was not overwritten!\n"; - return new Model(); - } - - string Model::operator<<(Model* model) { - cout << "Default >> operator was not overwritten!\n"; - return ""; - } -} diff --git a/Model.h b/Model.h deleted file mode 100644 index af38b3f..0000000 --- a/Model.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "std_lib_inc.h" -#ifndef MODEL_H -#define MODEL_H - -namespace models { - class Model { - public: - Model(); - - virtual Model* operator>>(stringstream& stream); - virtual string operator<<(Model* model); - }; -} - -#endif // MODEL_H - diff --git a/Task.cpp b/Task.cpp index 2a6c509..4c03f8e 100644 --- a/Task.cpp +++ b/Task.cpp @@ -1,5 +1,34 @@ #include "Task.h" +#include "Util.h" +#include "FormatError.h" + +using err::FormatError; +using util::Util; namespace models { - Task::Task(const int& id, const string& name, const string& description, const vector& children): Model(), id(id), name(name), description(description), children(children){} + Task::Task(const int& id, const string& name, const string& description, const vector& children): id(id), name(name), description(description), children(children) {} + + Task::Task(): id(0), name(""), description(""), children({}) {} + + ostream& Task::write(ostream& stream) { + stream << this; + return stream; + } + + int Task::get_id() const { + return this->id; + } + + string Task::get_name() const { + return this->name; + } + + string Task::get_description() const { + return this->description; + } + + vector Task::get_children() const { + return this->children; + } + } diff --git a/Task.h b/Task.h index a976256..8d5cfad 100644 --- a/Task.h +++ b/Task.h @@ -1,10 +1,14 @@ #include "std_lib_inc.h" -#include "Model.h" +#include "FormatError.h" +#include "Util.h" #ifndef TASK_H #define TASK_H +using err::FormatError; +using util::Util; + namespace models { - class Task : public Model { + class Task { private: int id; string name; @@ -12,9 +16,39 @@ namespace models { vector children; public: Task(const int& id, const string& name, const string& description, const vector& children); - Model* operator>>(stringstream& stream) override; - string operator<<(Model& model) override; + + Task(); + + ostream& write(ostream& stream); + istream& read(istream&); + + int get_id() const; + string get_name() const; + string get_description() const; + vector get_children() const; + + + friend ostream& operator<<(ostream& os, const Task& t); + friend istream& operator>>(istream& is, Task& t); }; + + inline ostream& operator<<(ostream& os, const Task& t) { + os << t.get_id() << " " << t.get_name() << " " << t.get_description(); + return os; + } + inline istream& operator>>(istream& is, Task& t) { + int id; + is >> id; + if (!is) + throw FormatError("Id NaN."); + + string name = Util::read_string_between_percent(is); + string description = Util::read_string_between_percent(is); + vector children = Util::read_numbers(is); + + t = {id, name, description, children}; + return is; + } } #endif // TASK_H diff --git a/User.cpp b/User.cpp index bbe66b9..649180b 100644 --- a/User.cpp +++ b/User.cpp @@ -1,11 +1,44 @@ #include "User.h" -#include namespace models { - User::User(const int& id, const string& name, const string& surname): Model(), id(id), name(name), surname(surname) {} - Model* User::operator>>(stringstream& stream) { - cout << "Custom impl."; - return new User(0, "", ""); + User::User(const int& id, const string& name, const string& surname): id(id), name(name), surname(surname) {} + + User::User(): id(0), name(""), surname("") {} + + ostream& User::write(ostream& stream) { + stream << this; + return stream; } + int User::get_id() const { + return this->id; + } + + string User::get_name() const { + return this->name; + } + + string User::get_surname() const { + return this->surname; + } + + ostream& operator<<(ostream& os, const User& u) + { + os << u.get_id() << " " << u.get_name() << " " << u.get_surname(); + return os; + } + + istream& operator>>(istream& is, User& u) + { + int id; + is >> id; + if (!is) + throw FormatError("User id NaN."); + string name, surname; + is >> name >> surname; + if (!is) + throw FormatError("Could not read user name and surname"); + u = {id, name, surname}; + return is; + } } diff --git a/User.h b/User.h index 3e2afec..c69203a 100644 --- a/User.h +++ b/User.h @@ -1,10 +1,14 @@ #include "std_lib_inc.h" -#include "Model.h" +#include "FormatError.h" +#include "Util.h" #ifndef USER_H #define USER_H +using err::FormatError; +using util::Util; + namespace models { - class User : public Model { + class User { private: int id; string name; @@ -12,9 +16,19 @@ namespace models { public: User(const int& id, const string& name, const string& surname); - Model* operator>>(stringstream& stream) override; - string operator<<(Model* model) override; + User(); + ostream& write(ostream& stream); + + int get_id() const; + string get_name() const; + string get_surname() const; + + friend ostream& operator<<(ostream& os, const User& u); + friend istream& operator>>(istream& is, User& u); }; + + ostream& operator<<(ostream& os, const User& u); + istream& operator>>(istream& is, User& u); } #endif // USER_H diff --git a/UserTaskIndex.cpp b/UserTaskIndex.cpp deleted file mode 100644 index ed7e0f5..0000000 --- a/UserTaskIndex.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "UserTaskIndex.h" - -namespace models { - UserTaskIndex::UserTaskIndex(const int& user_id, const int& task_id) : Model(), user_id(user_id), task_id(task_id) {} -} diff --git a/UserTaskIndex.h b/UserTaskIndex.h deleted file mode 100644 index 2bffb2d..0000000 --- a/UserTaskIndex.h +++ /dev/null @@ -1,19 +0,0 @@ -#include "std_lib_inc.h" -#include "Model.h" -#ifndef USERTASKINDEX_H -#define USERTASKINDEX_H - -namespace models { - class UserTaskIndex : public Model{ - private: - int user_id; - int task_id; - public: - UserTaskIndex(const int& user_id, const int& task_id); - Model* operator>>(stringstream& stream) override; - string operator<<(Model& model) override; - }; -} - -#endif // USERTASKINDEX_H - diff --git a/Util.cpp b/Util.cpp new file mode 100644 index 0000000..b7c97e6 --- /dev/null +++ b/Util.cpp @@ -0,0 +1,68 @@ +#include "Util.h" +#include "FormatError.h" +#include +#include +#include + +using err::FormatError; + +namespace util { + string Util::read_string_between_percent(istream& is) { + char c; + string s = ""; + bool read = false; + + for(int i = 0; i < 2; ++i) { + while (true) { + is >> c; + if (!is) + throw FormatError("Could not read char!"); + if (c == '%') { + read = !read; + break; + } + if (!read) + continue; + s += c; + } + } + + return s; + } + + vector Util::read_numbers(istream &is) { + int i; + string until_eol; + getline(is, until_eol); + + vector numbers_as_string = Util::split(until_eol); + vector nums; + + try { + for(string s : numbers_as_string) + nums.push_back(stoi(s)); + } catch (exception& _) { + throw FormatError("Could not convert string to int"); + } + + return nums; + } + + vector Util::split(const string& s) { + vector strs; + string result = ""; + + for(char c : s) { + if (c == ' ') { + if (result != "") { + strs.push_back(result); + result = ""; + } + break; + } + result += c; + } + + return strs; + } +} diff --git a/Util.h b/Util.h new file mode 100644 index 0000000..7806cc4 --- /dev/null +++ b/Util.h @@ -0,0 +1,14 @@ +#include "std_lib_inc.h" +#ifndef UTIL_H +#define UTIL_H + +namespace util { + class Util { + public: + static string read_string_between_percent(istream& is); + static vector read_numbers(istream& is); + static vector split(const string& s); + }; +} + +#endif // UTIL_H diff --git a/main.cpp b/main.cpp index a2e63d6..feee681 100644 --- a/main.cpp +++ b/main.cpp @@ -3,33 +3,51 @@ #include "SubCommand.h" #include "HelpCommand.h" #include "AddCommand.h" +#include "User.h" +#include "Manager.h" +#include + +#include "FileError.h" using commands::SubCommand; using commands::HelpCommand; using commands::AddCommand; +using util::Manager; +using err::FileError; +using err::FormatError; const vector handlers = { new HelpCommand(), new AddCommand() }; -// Mein Leben auf IMDB, nur 7/10. - int main(int argc, char** argv) { if (argc < 2) { cout << "There are not enough args!\n"; return 0; } + stringstream parameter = make_string_stream(argc, argv); string command; parameter >> command; - for (SubCommand* sc : handlers) { - if (sc->get_name() == command) { - sc->run(argc, parameter); - return 0; + try { + for (SubCommand* sc : handlers) { + if (sc->get_name() == command) { + sc->run(argc, parameter); + return sc->get_value(); + } } } - - cout << "I don't know this command!\n"; - return 0; + catch (FormatError& e) { + cout << e.why() << "\n"; + } + catch (FileError& e) + { + cout << e.why() << "\n"; + } + catch (exception& e) { + cout << e.what() << "\n"; + } + return 101; } +