diff --git a/3mExceptions.cpp b/3mExceptions.cpp index 2df0538..696bc19 100644 --- a/3mExceptions.cpp +++ b/3mExceptions.cpp @@ -40,3 +40,15 @@ const char* ParseException::what() const throw() { msg += _err; return msg.c_str(); } + +OutOfBoundsException::OutOfBoundsException(std::string what) { + _what = what; +} + +OutOfBoundsException::~OutOfBoundsException() throw() { + _what = ""; +} + +const char* OutOfBoundsException::what() const throw() { + return _what.c_str(); +} diff --git a/3mExceptions.h b/3mExceptions.h index e7eea1b..974f929 100644 --- a/3mExceptions.h +++ b/3mExceptions.h @@ -28,8 +28,8 @@ public: ///< \return Whole error message. }; /// \class ParseException -/// \brief An exception to be throw when parse error occurs. -class ParseException { +/// \brief An exception to be thrown when parse error occurs. +class ParseException: public std::exception { private: std::string _filename; std::string _err; @@ -41,5 +41,17 @@ public: const char* what() const throw(); ///< \brief A function, that returns the whole error. ///< \return Whole error message. }; +/// \class OutOfBoundsException +/// \brief An exception to be thrown when the iterator gets out of container bounds. +class OutOfBoundsException: public std::exception { +private: + std::string _what; +public: + OutOfBoundsException(std::string what); ///< \brief A constructor with parameters. + ///< \param what Error message. + ~OutOfBoundsException() throw(); ///< A destructor, as needed by std::exception. + const char* what() const throw(); ///< \brief A function returning error message. + /// \return Error message. +}; } #endif diff --git a/ModListDescription.cpp b/ModListDescription.cpp index b9e2570..b4f520d 100644 --- a/ModListDescription.cpp +++ b/ModListDescription.cpp @@ -7,6 +7,12 @@ _server = ""; _path = ""; } +ModListDescription::~ModListDescription() { +_name = ""; +_server = ""; +_path = ""; +} + ModListDescription::ModListDescription(std::string name, std::string server, std::string path) { _name = name; _server = server; @@ -36,3 +42,9 @@ _server = server; void ModListDescription::setPath(std::string path) { _path = path; } + +void ModListDescription::clear() { + _name = ""; + _server = ""; + _path = ""; +} diff --git a/ModListDescription.h b/ModListDescription.h index 0d86c8c..abdeced 100644 --- a/ModListDescription.h +++ b/ModListDescription.h @@ -36,6 +36,7 @@ public: ///< \param server Server with remote modlist. void setPath(std::string path); ///< \brief A function setting remote modlist path on server. ///< \param path Remote modlist path on server. + void clear(); ///< A function that clears the object. }; } #endif diff --git a/ModListList.cpp b/ModListList.cpp new file mode 100644 index 0000000..9bbcead --- /dev/null +++ b/ModListList.cpp @@ -0,0 +1,169 @@ +#include "ModListList.h" +#include "3mExceptions.h" +#include +#include +#include +using namespace mmm; + +ModListList::ModListList() { + std::string home = getenv("HOME"); + _rmfn = home + "/.3m/remote_modlists"; + try { + std::ifstream rmfile(_rmfn.c_str()); + if(!rmfile) { + throw FileException(_rmfn, "reading", "Could not open file!"); + } + std::string action = "detect"; + ModListDescription mld; + while(!rmfile.eof()) { + std::string line; + rmfile >> line; + if(rmfile) { + if(action == "detect") { + if(line[0] == '{') { + std::string name = ""; + for(unsigned int i = 1; line[i] != '}' && i < line.length(); i++) { + name += line[i]; + } + mld.setName(name); + action = "parse"; + } else { + rmfile.close(); + std::string msg; + msg += "Found "; + msg += line[0]; + msg += " although { was expected."; + throw ParseException(_rmfn, msg); + } + } else if(action == "parse") { + if(line[0] == '{') { + if(line[1] == 'e' && line[2] == 'n' && line[3] == 'd' && line[4] == '}') { + if(mld.getName() != "" && mld.getServer() != "" && mld.getPath() != "") { + addModlistDescription(mld); + mld.clear(); + } else { + rmfile.close(); + throw ParseException(_rmfn, "Data error."); + } + action = "detect"; + } else { + rmfile.close(); + throw ParseException(_rmfn, "Found " + line + " although {end} or action in [] was expected."); + } + } else if(line[0] == '[') { + std::string tmpact = ""; + for(unsigned int i = 1; line[i] != ']' && i < line.length(); i++) { + tmpact += line[i]; + } + if(tmpact == "server" || tmpact == "path") { + action = tmpact; + } else { + rmfile.close(); + throw ParseException(_rmfn, "Found " + tmpact + " although server/path was expected."); + } + } else { + rmfile.close(); + throw ParseException(_rmfn, "Found " + line + " although {end} or action in [] was expected."); + } + } else if(action == "server") { + if(line[0] == '[' || line[0] == '{') { + rmfile.close(); + std::string msg; + msg += "Found "; + msg += line[0]; + msg += " although string was expected."; + throw ParseException(_rmfn, msg); + } else { + mld.setServer(line); + action = "parse"; + } + } else if(action == "path") { + if(line[0] == '[' || line[0] == '{') { + rmfile.close(); + std::string msg; + msg += "Found "; + msg += line[0]; + msg += " although string was expected."; + throw ParseException(_rmfn, msg); + } else { + mld.setPath(line); + action = "parse"; + } + } else { + rmfile.close(); + throw ParseException(_rmfn, "The program should not reach this place!"); + } +} + } + _modlistsIterator = -1; + _modlistsAtEnd = false; +} catch(FileException& exc) { + std::cerr << "File exception occured: " << exc.what() << std::endl; + _modlistsIterator = -1; + _modlistsAtEnd = true; +} catch(ParseException& exc) { + std::cerr << "Parse exception occured: " << exc.what() << std::endl; + _modlistsIterator = -1; + _modlistsAtEnd = true; +} +} + +ModListList::~ModListList() { + _modlists.clear(); +} + +ModListDescription ModListList::getNextModlistDescription() { + if(_modlistsIterator+1 < _modlists.size()) { + _modlistsIterator++; + return _modlists[_modlistsIterator]; + } else { + _modlistsAtEnd = true; + ModListDescription mld; + return mld; + } +} + +ModListDescription& ModListList::getModlistDescriptionByName(std::string name) { + for(unsigned int i = 0; i < _modlists.size(); i++) { + if(_modlists[i].getName() == name) { + return _modlists[i]; + } + } + static ModListDescription mld; + return mld; +} + +void ModListList::addModlistDescription(ModListDescription mld) { + _modlists.push_back(mld); + _modlistsAtEnd = false; +} + +void ModListList::deleteModlistDescription(std::string name) { + for(std::vector::iterator i = _modlists.begin(); i < _modlists.end(); i++) { + if(i -> getName() == name) { + _modlists.erase(i); + } + } +} + +void ModListList::resetModlistDescriptionIterator() { + _modlistsIterator = -1; + _modlistsAtEnd = false; +} + +void ModListList::write() { + std::string home = getenv("HOME"); + _rmfn = home + "/.3m/remote_modlists"; + std::ofstream rmfile(_rmfn.c_str()); + if(!rmfile) { + throw FileException(_rmfn, "writing", "Could not open file!"); + } + for(unsigned int i = 0; i < _modlists.size(); i++) { + rmfile << "{" << _modlists[i].getName() << "}" << std::endl << "[server]" << std::endl << _modlists[i].getServer() << std::endl << "[path]" << std::endl << _modlists[i].getPath() << std::endl << "{end}" << std::endl; + } + rmfile.close(); +} + +bool ModListList::modlistDescriptionsAtEnd() { + return _modlistsAtEnd; +} diff --git a/ModListList.h b/ModListList.h new file mode 100644 index 0000000..e73e56d --- /dev/null +++ b/ModListList.h @@ -0,0 +1,40 @@ +#ifndef _MODLISTLIST_H +#define _MODLISTLIST_H +#include "ModListDescription.h" +#include +/// \file ModListList.h +/// \brief A class representing a modlist list. +/// \author Phitherek_ +/// \date 2013 +/// \version 0.1 + +/// \namespace mmm +/// \brief A global namespace for 3m. +namespace mmm { +/// \class ModListList +/// \brief A class representing a modlist list. +class ModListList { +private: + std::string _rmfn; + std::vector _modlists; + int _modlistsIterator; + bool _modlistsAtEnd; +public: + ModListList(); ///< A constructor. + ~ModListList(); ///< A destructor. + ModListDescription getNextModlistDescription(); ///< \brief A function returning next modlist description from the list. + ///< \return Next modlist description from the list as the ModListDescription object. + ModListDescription& getModlistDescriptionByName(std::string name); ///< \brief A function returning a modlist description by modlist name. + ///< \param name Name of the modlist. + ///< \return A reference to ModListDescription object. + void addModlistDescription(ModListDescription mld); ///< \brief A function adding new modlist description to the end of the list. + ///< \param mld A ModListDescription object. + void deleteModlistDescription(std::string name); ///< \brief A function removing modlist description from the list. + ///< \param name Name of the modlist. + void resetModlistDescriptionIterator(); ///< A function resetting modlist list iterator. + void write(); ///< A function that writes back the changes to the file. + bool modlistDescriptionsAtEnd(); ///< \brief A function returning if the modlist list iterator reached its end. + ///< \return True if the modlist list iterator reached its end, false otherwise. +}; +} +#endif diff --git a/OBJECTS b/OBJECTS index e06c0db..f7237ea 100644 --- a/OBJECTS +++ b/OBJECTS @@ -1,10 +1,11 @@ ModDescription: name, description, release, deps, repotype, repoaddr x ModList: ModListDescription, vector +ModListList: vector LocalModDescription: ModDescription + remoteModlist (inheritance) x -LocalModList: vector -RepositoryModDescription: ModDescription + path (inheritance) -RepositoryInfo: vector -ModListDescription: name, server, modlistPath +LocalModList: vector, ConfigFile +RepositoryModDescription: ModDescription + path (inheritance) x +RepositoryInfo: vector, ConfigFile +ModListDescription: name, server, modlistPath x ModInfoDescription: name, server, modinfoPath x ModInfo: ModInfoDescription, vector ParameterParser: actionList, argc, argv diff --git a/RepositoryModDescription.cpp b/RepositoryModDescription.cpp new file mode 100644 index 0000000..5ca9788 --- /dev/null +++ b/RepositoryModDescription.cpp @@ -0,0 +1,18 @@ +#include "RepositoryModDescription.h" +using namespace mmm; + +RepositoryModDescription::RepositoryModDescription() { + _path = ""; +} + +RepositoryModDescription::~RepositoryModDescription() { + _path = ""; +} + +std::string RepositoryModDescription::getPath() { + return _path; +} + +void RepositoryModDescription::setPath(std::string path) { + _path = path; +} diff --git a/RepositoryModDescription.h b/RepositoryModDescription.h new file mode 100644 index 0000000..4f1fbe7 --- /dev/null +++ b/RepositoryModDescription.h @@ -0,0 +1,27 @@ +#ifndef _REPOSITORYMODDESCRIPTION_H +#define _REPOSITORYMODDESCRIPTION_H +#include "ModDescription.h" +/// \file RepositoryModDescription.h +/// \brief A class describing a mod in the local repository. +/// \author Phitherek_ +/// \date 2013 +/// \version 0.1-pre + +/// \namespace mmm +/// \brief A global namespace for 3m. +namespace mmm { +/// \class RepositoryModDescription +/// \brief A class describing a mod in the local repository. +class RepositoryModDescription: public ModDescription { +private: + std::string _path; +public: + RepositoryModDescription(); ///< A constructor. + ~RepositoryModDescription(); ///< A destructor. + std::string getPath(); ///< \brief A function returning installation path of the mod. + ///< \return Installation path of the mod. + void setPath(std::string path); ///< \brief A function that sets installation path of the mod. + ///< \param path Installation path of the mod. +}; +} +#endif diff --git a/tests/Makefile b/tests/Makefile index 08900e5..84b6119 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,9 +3,11 @@ all: ${CXX} ${CXXFLAGS} -o ConfigFileTest ConfigFileTest.cpp ../ConfigFile.cpp ../3mExceptions.cpp ${CXX} ${CXXFLAGS} -o ModDescriptionTest ModDescriptionTest.cpp ../ModDescription.cpp ${CXX} ${CXXFLAGS} -o LocalModDescriptionTest LocalModDescriptionTest.cpp ../LocalModDescription.cpp ../ModDescription.cpp + ${CXX} ${CXXFLAGS} -o ModListListTest ModListListTest.cpp ../ModListList.cpp ../ModListDescription.cpp ../3mExceptions.cpp debug: ${CXX} ${CXXFLAGS} -o ConfigFileTest ConfigFileTest.cpp ../ConfigFile.cpp ../3mExceptions.cpp -g ${CXX} ${CXXFLAGS} -o ModDescriptionTest ModDescriptionTest.cpp ../ModDescription.cpp -g ${CXX} ${CXXFLAGS} -o LocalModDescriptionTest LocalModDescriptionTest.cpp ../LocalModDescription.cpp ../ModDescription.cpp + ${CXX} ${CXXFLAGS} -o ModListListTest ModListListTest.cpp ../ModListList.cpp ../ModListDescription.cpp ../3mExceptions.cpp -g clean: - rm -rf ConfigFileTest ModDescriptionTest LocalModDescriptionTest + rm -rf ConfigFileTest ModDescriptionTest LocalModDescriptionTest ModListListTest diff --git a/tests/ModListListTest.cpp b/tests/ModListListTest.cpp new file mode 100644 index 0000000..03885c2 --- /dev/null +++ b/tests/ModListListTest.cpp @@ -0,0 +1,67 @@ +#include +#include +#include "../ModListList.h" +#include "../3mExceptions.h" +using namespace std; + +int main() { +mmm::ModListList mll; +char act; +do { +cout << "Choose action: (l)ist all modlists, (f)ind by name and list, (d)elete by name, (a)dd new modlist, (s)ave and quit, (q)uit without saving: "; +cin >> act; +if(act == 'l') { +mll.resetModlistDescriptionIterator(); +while(!mll.modlistDescriptionsAtEnd()) { + mmm::ModListDescription mld = mll.getNextModlistDescription(); + if(mld.getName() != "" && mld.getServer() != "" && mld.getPath() != "") { + cout << "name: " << mld.getName() << endl << "server: " << mld.getServer() << endl << "path: " << mld.getPath() << endl << endl; + } +} +} else if(act == 'f') { + cout << "Enter name: "; + string name; + cin >> name; + mmm::ModListDescription mld = mll.getModlistDescriptionByName(name); + if(mld.getName() != "" && mld.getServer() != "" && mld.getPath() != "") { + cout << "name: " << mld.getName() << endl << "server: " << mld.getServer() << endl << "path: " << mld.getPath() << endl; + } else { + cout << name << " not found!" << endl; + } +} else if(act == 'd') { + cout << "Enter name: "; + string name; + cin >> name; + mll.deleteModlistDescription(name); +} else if(act == 'a') { + mmm::ModListDescription mld; + cout << "Enter name: "; + string name; + cin >> name; + cout << "Enter server: "; + string server; + cin >> server; + cout << "Enter path: "; + string path; + cin >> path; + mld.setName(name); + mld.setPath(path); + mld.setServer(server); + if(mld.getName() != "" && mld.getPath() != "" && mld.getServer() != "") { + mll.addModlistDescription(mld); + } else { + cerr << "You must fill all fields!" << endl; + } +} +} while(act != 'q' && act != 's'); +if(act == 's') { +try { +mll.write(); +} catch(mmm::FileException& exc) { +cerr << "File exception occured: " << exc.what() << endl; +return EXIT_FAILURE; +} +} +cout << "All done! Thank you for testing!" << endl; +return EXIT_SUCCESS; +}