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; } +