diff --git a/3m.h b/3m.h new file mode 100644 index 0000000..908ed16 --- /dev/null +++ b/3m.h @@ -0,0 +1,38 @@ +#ifndef _3M_H +#define _3M_H +#include +#include "ConfigFile.h" +#include "3mExceptions.h" +#include "LocalModDescription.h" +#include "ModDescription.h" +#include "ModInfoDescription.h" +#include "ModListDescription.h" +#include "ModListList.h" +#include "RepositoryModDescription.h" +#include "LocalModList.h" +/// \file 3m.h +/// \brief A common header for 3m and definitions of helper functions. +/// \author Phitherek_ +/// \date 2013 +/// \version 0.1 + +/// \namespace mmm +/// \brief A global namespace for 3m. +namespace mmm { +/// \fn std::string strip_endl(std::string s) +/// \brief A function that strips endline signs from the string. +/// \param s A string to strip endline signs from. +/// \return Stripped string. +std::string strip_endl(std::string s) { + int len = s.length(); + for(int i = 0; i < len; i++) { + if(s[i] == '\n') { + s.erase(i,1); + len = s.length(); + i--; + } + } + return s; +} +} +#endif diff --git a/LocalModDescription.cpp b/LocalModDescription.cpp index 9781574..886e05a 100644 --- a/LocalModDescription.cpp +++ b/LocalModDescription.cpp @@ -16,3 +16,15 @@ std::string LocalModDescription::getRemoteModlistName() { void LocalModDescription::setRemoteModlistName(std::string remoteModlist) { _remoteModlist = remoteModlist; } + +void LocalModDescription::clear() { + _name = ""; + _description = ""; + _release = 0; + _depsIterator = -1; + _depsAtEnd = true; + _repotype = ""; + _repoaddr = ""; + _deps.clear(); + _remoteModlist = ""; +} diff --git a/LocalModDescription.h b/LocalModDescription.h index fdc82ff..4e99bcc 100644 --- a/LocalModDescription.h +++ b/LocalModDescription.h @@ -22,6 +22,7 @@ std::string getRemoteModlistName(); ///< \brief A function returning remote modl ///< \return Remote modlist name. void setRemoteModlistName(std::string remoteModlist); ///< \brief A function setting remote modlist name. ///< \param remoteModlist Remote modlist name +void clear(); ///< A function that clears the object. }; } #endif diff --git a/LocalModList.cpp b/LocalModList.cpp new file mode 100644 index 0000000..7f4eca0 --- /dev/null +++ b/LocalModList.cpp @@ -0,0 +1,260 @@ +#include "3m.h" +#include +#include +using namespace mmm; + +LocalModList::LocalModList() { + ConfigFile emptycf; + _conf = emptycf; + _modlistIterator = -1; + _modlistAtEnd = true; + _modlist.clear(); +} + +LocalModList::LocalModList(ConfigFile conf) { + _conf = conf; + _modlist.clear(); + std::ifstream lmfile(_conf.getModList().c_str()); + if(!lmfile) { + throw FileException(_conf.getModList(), "reading", "Could not open file!"); + } + std::string action = "detect"; +LocalModDescription lmld; +while(!lmfile.eof()) { + std::string line = ""; + char c; + do { + lmfile.get(c); + if(c != '\n'); + line += c; + } while(c != '\n'); + line = strip_endl(line); + if(lmfile) { + if(action == "detect") { + if(line[0] == '{') { + std::string name = ""; + for(unsigned int i = 1; line[i] != '}' && i < line.length(); i++) { + name += line[i]; + } + lmld.setName(name); + action = "parse"; + } else { + std::string msg = ""; + msg = "Found "; + msg += line[0]; + msg += " although { was expected."; + lmfile.close(); + throw ParseException(_conf.getModList(), msg); + } + } else if(action == "parse") { + if(line[0] == '{') { + if(line[1] == 'e' && line[2] == 'n' && line[3] == 'd' && line[4] == '}') { + if(lmld.getName() != "" && lmld.getRemoteModlistName() != "" && lmld.getDescription() != "" && !lmld.dependenciesEmpty() && lmld.getRepositoryType() != "" && lmld.getRepositoryAddress() != "") { + _modlist.push_back(lmld); + if(_modlistAtEnd) { + _modlistAtEnd = false; + } + lmld.clear(); + action = "detect"; + } else { + lmfile.close(); + throw ParseException(_conf.getModList(),"Data error."); + } + action = "detect"; + } else { + lmfile.close(); + std::string msg; + msg = "Found "; + msg += line; + msg += " although {end} or action in [] was expected."; + throw ParseException(_conf.getModList(), msg); + } + } else if(line[0] == '[') { + std::string tmpact = ""; + for(unsigned int i = 1; line[i] != ']' && i < line.length(); i++) { + tmpact += line[i]; + } + if(tmpact == "rmodlist" || tmpact == "description" || tmpact == "release" || tmpact == "deps" || tmpact == "repotype" || tmpact == "repoaddr") { + action = tmpact; + } else { + std::string msg; + msg = "Found "; + msg += tmpact; + msg += " although rmodlist/description/release/deps/repotype/repoaddr was expected."; + lmfile.close(); + throw ParseException(_conf.getModList(), msg); + } + } else { + std::string msg; + msg = "Found "; + msg += line; + msg += " although {end} or action in [] was expected."; + lmfile.close(); + throw ParseException(_conf.getModList(), msg); + } + } else if(action == "rmodlist") { + if(line[0] == '[' || line[0] == '{') { + std::string msg; + msg = "Found "; + msg += line[0]; + msg += " although string was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } else { + lmld.setRemoteModlistName(line); + action = "parse"; + } + } else if(action == "description") { + if(line[0] == '[' || line[0] == '{') { + std::string msg; + msg = "Found "; + msg += line[0]; + msg += " although string was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } else { + lmld.setDescription(line); + action = "parse"; + } + } else if(action == "release") { + if(line[0] == '[' || line[0] == '{') { + std::string msg; + msg = "Found "; + msg += line[0]; + msg += " although string was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } else { + lmld.setReleaseNr(atoi(line.c_str())); + action = "parse"; + } + } else if(action == "deps") { + if(line[0] == '{') { + std::string msg; + msg = "Found "; + msg += line[0]; + msg += " although string or [ was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } else if(line[0] == '[') { + if(line[1] == 'd' && line[2] == 'e' && line[3] == 'p' && line[4] == 's' && line[5] == 'e' && line[6] == 'n' && line[7] == 'd' && line[8] == ']') { + if(lmld.dependenciesEmpty()) { + lmld.insertDependency("none"); + } + action = "parse"; + } else { + std::string msg; + msg = "Found "; + msg += line; + msg += " although string or [depsend] was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } + } else { + lmld.insertDependency(line); + } + } else if(action == "repotype") { + if(line[0] == '[' || line[0] == '{') { + std::string msg; + msg = "Found "; + msg += line[0]; + msg += " although string was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } else { + lmld.setRepositoryType(line); + action = "parse"; + } + } else if(action == "repoaddr") { + if(line[0] == '[' || line[0] == '{') { + std::string msg; + msg = "Found "; + msg += line[0]; + msg += " although string was expected."; + lmfile.close(); + throw(_conf.getModList(), msg); + } else { + lmld.setRepositoryAddress(line); + action = "parse"; + } + } else { + lmfile.close(); + throw ParseException(_conf.getModList(), "The program should not reach this place!"); + } +} +} +lmfile.close(); +_modlistIterator = -1; +_modlistAtEnd = true; +} + +LocalModList::~LocalModList() { + ConfigFile emptycf; + _conf = emptycf; + _modlist.clear(); + _modlistIterator = -1; + _modlistAtEnd = true; +} + +void LocalModList::addModDescription(LocalModDescription lmd) { + _modlist.push_back(lmd); + if(_modlistAtEnd) { + _modlistAtEnd = false; + } +} + +LocalModDescription LocalModList::getNextModDescription() { + if(_modlistIterator+1 < _modlist.size()) { + _modlistIterator++; + return _modlist[_modlistIterator]; + } else { + _modlistAtEnd = true; + LocalModDescription emptylmd; + return emptylmd; + } +} + +LocalModDescription LocalModList::getModDescriptionByName(std::string name) { + for(unsigned int i = 0; i < _modlist.size(); i++) { + if(_modlist[i].getName() == name) { + return _modlist[i]; + } + } + LocalModDescription emptylmd; + return emptylmd; +} + +void LocalModList::resetModDescriptionIterator() { + if(_modlistAtEnd) { + _modlistAtEnd = false; + } + _modlistIterator = -1; +} + +bool LocalModList::modDescriptionsAtEnd() { + return _modlistAtEnd; +} + +void LocalModList::setConfigFile(ConfigFile conf) { + _conf = conf; +} + +void LocalModList::write() { + std::ofstream lmfile(_conf.getModList().c_str()); + if(!lmfile) { + lmfile.close(); + throw FileException(_conf.getModList(), "writing", "Could not open file!"); + } + for(unsigned int i = 0; i < _modlist.size(); i++) { + lmfile << "{" << _modlist[i].getName() << "}" << std::endl << "[rmodlist]" << std::endl << _modlist[i].getRemoteModlistName() << std::endl << "[description]" << std::endl << _modlist[i].getDescription() << std::endl << "[release]" << std::endl << _modlist[i].getReleaseNr() << std::endl << "[deps]" << std::endl; + _modlist[i].resetDependencyIterator(); + while(!_modlist[i].dependenciesEnd()) { + std::string dep = _modlist[i].getNextDependency(); + if(dep != "") { + lmfile << dep << std::endl; + } + } + lmfile << "[depsend]" << std::endl << "[repotype]" << std::endl << _modlist[i].getRepositoryType() << std::endl << "[repoaddr]" << std::endl << _modlist[i].getRepositoryAddress() << std::endl << "{end}" << std::endl; + } + lmfile.close(); +} diff --git a/LocalModList.h b/LocalModList.h new file mode 100644 index 0000000..eba5a23 --- /dev/null +++ b/LocalModList.h @@ -0,0 +1,46 @@ +#ifndef _LOCALMODLIST_H +#define _LOCALMODLIST_H +#include +#include +#include "LocalModDescription.h" +#include "ConfigFile.h" +/// \file LocalModList.h +/// \brief A class representing a local modlist. +/// \author Phitherek_ +/// \date 2013 +/// \version 0.1-pre + +/// \namespace mmm +/// \brief A global namespace for 3m. +namespace mmm { +/// \class LocalModList +/// \brief A class representing a local modlist. +class LocalModList { +private: + ConfigFile _conf; + std::vector _modlist; + int _modlistIterator; + bool _modlistAtEnd; +public: + LocalModList(); ///< A constructor. + LocalModList(ConfigFile conf); ///< \brief A constructor with parameter. + ///< This constructor tries to parse the modlist in the path given by the ConfigFile object. + ///< \param conf A ConfigFile object. + ~LocalModList(); ///< A destructor. + void addModDescription(LocalModDescription lmd); ///< \brief A function that adds a mod description to the modlist. + /// \param lmd A mod description to be added. + LocalModDescription getNextModDescription(); ///< \brief A function that returns next mod description from the modlist. + ///< \return Next mod description from the modlist. + LocalModDescription getModDescriptionByName(std::string name); ///< \brief A function, that searches a mod name and returns its description. + ///< \param name A mod name. + ///< \return Description of the mod. + void resetModDescriptionIterator(); ///< A function that resets iterator of the modlist. + bool modDescriptionsAtEnd(); ///< \brief A function that returns if the modlist iterator has reached its end. + ///< \return True if modlist iterator is at end, false otherwise. + void setConfigFile(ConfigFile conf); ///< \brief A function that sets the used config file. + ///< \param conf A ConfigFile object. + void write(); ///< A function that writes the changes to the modlist file. +}; +} + +#endif diff --git a/Makefile b/Makefile index f35a40e..cb97ecb 100644 --- a/Makefile +++ b/Makefile @@ -23,4 +23,4 @@ tests: testsdebug: make -C tests debug testsclean: - make -C testsclean + make -C tests clean diff --git a/ModDescription.cpp b/ModDescription.cpp index 515ded0..e5d0317 100644 --- a/ModDescription.cpp +++ b/ModDescription.cpp @@ -9,6 +9,7 @@ ModDescription::ModDescription() { _depsAtEnd = true; _repotype = ""; _repoaddr = ""; + _deps.clear(); } ModDescription::~ModDescription() { @@ -20,6 +21,7 @@ ModDescription::~ModDescription() { _depsAtEnd = true; _repotype = ""; _repoaddr = ""; + _deps.clear(); } std::string ModDescription::getName() { @@ -89,3 +91,18 @@ void ModDescription::resetDependencyIterator() { bool ModDescription::dependenciesEnd() { return _depsAtEnd; } + +bool ModDescription::dependenciesEmpty() { + return _deps.empty(); +} + +void ModDescription::clear() { + _name = ""; + _description = ""; + _release = 0; + _depsIterator = -1; + _depsAtEnd = true; + _repotype = ""; + _repoaddr = ""; + _deps.clear(); +} diff --git a/ModDescription.h b/ModDescription.h index d41bfe4..71a76ad 100644 --- a/ModDescription.h +++ b/ModDescription.h @@ -53,6 +53,9 @@ public: void resetDependencyIterator(); ///< A function resetting the iterator of the dependency list. bool dependenciesEnd(); ///< \brief A function returning if dependency list is at its end. ///< \return True if dependency list iterator reached its end, false otherwise. + bool dependenciesEmpty(); ///< \brief A function returning if dependency list is empty. + ///< \return True if dependency list is empty, false otherwise. + void clear(); ///< A function that clears the object. }; } #endif diff --git a/ModInfoDescription.h b/ModInfoDescription.h index c62b120..9659450 100644 --- a/ModInfoDescription.h +++ b/ModInfoDescription.h @@ -37,3 +37,4 @@ public: ///< \param path Modinfo path on server. }; } +#endif diff --git a/OBJECTS b/OBJECTS index f7237ea..72ecfc7 100644 --- a/OBJECTS +++ b/OBJECTS @@ -1,6 +1,6 @@ ModDescription: name, description, release, deps, repotype, repoaddr x ModList: ModListDescription, vector -ModListList: vector +ModListList: vector x LocalModDescription: ModDescription + remoteModlist (inheritance) x LocalModList: vector, ConfigFile RepositoryModDescription: ModDescription + path (inheritance) x diff --git a/tests/LocalModListTest.cpp b/tests/LocalModListTest.cpp new file mode 100644 index 0000000..39f44dc --- /dev/null +++ b/tests/LocalModListTest.cpp @@ -0,0 +1,67 @@ +#include +#include +#include "../LocalModList.h" +#include "../3mExceptions.h" +using namespace std; + +int main() { +string home = getenv("HOME"); +string conffn = home + "/.3m/config"; +try { +mmm::ConfigFile conf(conffn); +mmm::LocalModList lml(conf); +char action; +do { + cout << "Select action: (l)ist modlist, (f)ind and list mod by name, (s)ave and exit, (q)uit without saving: "; + cin >> action; + if(action == 'l') { + lml.resetModDescriptionIterator(); + while(!lml.modDescriptionsAtEnd()) { + mmm::LocalModDescription temp; + temp = lml.getNextModDescription(); + if(temp.getName() != "" && temp.getRemoteModlistName() != "" && temp.getDescription() != "" && !temp.dependenciesEmpty() && temp.getRepositoryType() != "" && temp.getRepositoryAddress() != "") { + cout << "name: " << temp.getName() << endl << "remote modlist name: " << temp.getRemoteModlistName() << endl << "description: " << temp.getDescription() << endl << "release: " << temp.getReleaseNr() << endl << "dependencies: " << endl; + temp.resetDependencyIterator(); + while(!temp.dependenciesEnd()) { + string dep = temp.getNextDependency(); + if(dep != "") { + cout << dep << endl; + } + } + cout << "repository type: " << temp.getRepositoryType() << endl << "repository address: " << temp.getRepositoryAddress() << endl; + } + } + cout << endl; + } else if(action == 'f') { + cout << "Enter name: "; + string name; + cin >> name; + mmm::LocalModDescription temp; + temp = lml.getModDescriptionByName(name); + if(temp.getName() != "" && temp.getRemoteModlistName() != "" && temp.getDescription() != "" && !temp.dependenciesEmpty() && temp.getRepositoryType() != "" && temp.getRepositoryAddress() != "") { + cout << "name: " << temp.getName() << endl << "remote modlist name: " << temp.getRemoteModlistName() << endl << "description: " << temp.getDescription() << endl << "release: " << temp.getReleaseNr() << endl << "dependencies: " << endl; + temp.resetDependencyIterator(); + while(!temp.dependenciesEnd()) { + string dep = temp.getNextDependency(); + if(dep != "") { + cout << dep << endl; + } + } + cout << "repository type: " << temp.getRepositoryType() << endl << "repository address: " << temp.getRepositoryAddress() << endl; + } else { + cout << name << " not found!" << endl; + } + } +} while(action != 'q' && action != 's'); +if(action == 's') { + lml.write(); +} +} catch(mmm::FileException &exc) { + cerr << "FileException occured: " << exc.what() << endl; + return EXIT_FAILURE; +} catch(mmm::ParseException &exc) { + cerr << "ParseException occured: " << exc.what() << endl; + return EXIT_FAILURE; +} +return EXIT_SUCCESS; +} diff --git a/tests/Makefile b/tests/Makefile index 84b6119..3f9e5c1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,10 +4,12 @@ all: ${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 + ${CXX} ${CXXFLAGS} -o LocalModListTest LocalModListTest.cpp ../LocalModList.cpp ../LocalModDescription.cpp ../ModDescription.cpp ../3mExceptions.cpp ../ConfigFile.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 + ${CXX} ${CXXFLAGS} -o LocalModListTest LocalModListTest.cpp ../LocalModList.cpp ../LocalModDescription.cpp ../ModDescription.cpp ../3mExceptions.cpp ../ConfigFile.cpp -g clean: - rm -rf ConfigFileTest ModDescriptionTest LocalModDescriptionTest ModListListTest + rm -rf ConfigFileTest ModDescriptionTest LocalModDescriptionTest ModListListTest LocalModListTest