From f3ab790912783d64ea399b8c1afb76c73c75e72c Mon Sep 17 00:00:00 2001 From: Thraix Date: Sun, 13 Oct 2019 19:59:43 +0200 Subject: [PATCH] Read and write config as xml --- Makefile | 35 +-- makegen.conf | 19 -- makegen.xml | 14 ++ src/Common.h | 2 +- src/ConfigFile.cpp | 307 ++++++++++++--------------- src/ConfigFile.h | 8 +- src/compatibility/ConfigFileConf.cpp | 164 ++++++++++++++ src/compatibility/ConfigFileConf.h | 34 +++ src/xml/XMLObject.cpp | 68 +++++- src/xml/XMLObject.h | 21 +- 10 files changed, 452 insertions(+), 220 deletions(-) delete mode 100644 makegen.conf create mode 100644 makegen.xml create mode 100644 src/compatibility/ConfigFileConf.cpp create mode 100644 src/compatibility/ConfigFileConf.h diff --git a/Makefile b/Makefile index a63c9fc..af90f28 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ MKDIR_P=mkdir -p BIN=bin/ OBJPATH=$(BIN)intermediates INCLUDES= -OBJECTS=$(OBJPATH)/ConfigCLI.o $(OBJPATH)/ConfigFile.o $(OBJPATH)/HFileGen.o $(OBJPATH)/IncludeDeps.o $(OBJPATH)/Makefile.o $(OBJPATH)/Utils.o $(OBJPATH)/main.o $(OBJPATH)/XML.o $(OBJPATH)/XMLObject.o +OBJECTS=$(OBJPATH)/ConfigCLI.o $(OBJPATH)/ConfigFile.o $(OBJPATH)/HFileGen.o $(OBJPATH)/IncludeDeps.o $(OBJPATH)/Makefile.o $(OBJPATH)/Utils.o $(OBJPATH)/ConfigFileConf.o $(OBJPATH)/main.o $(OBJPATH)/XML.o $(OBJPATH)/XMLObject.o CFLAGS=$(INCLUDES) -std=c++17 -c -w -g3 -D_DEBUG LIBDIR= LDFLAGS= @@ -33,29 +33,32 @@ $(OUTPUT): $(OBJECTS) install: all $(info Installing MakeGen to /usr/bin/) @cp $(OUTPUT) /usr/bin/makegen -$(OBJPATH)/ConfigCLI.o : src/ConfigCLI.cpp src/Common.h src/ConfigCLI.h src/ConfigFile.h - $(info -[11%]- $<) +$(OBJPATH)/ConfigCLI.o : src/ConfigCLI.cpp src/Common.h src/ConfigCLI.h src/ConfigFile.h src/xml/XMLObject.h + $(info -[10%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/ConfigFile.o : src/ConfigFile.cpp src/ConfigFile.h src/FileUtils.h src/Common.h src/Utils.h - $(info -[22%]- $<) +$(OBJPATH)/ConfigFile.o : src/ConfigFile.cpp src/ConfigFile.h src/xml/XMLObject.h src/FileUtils.h src/Common.h src/Utils.h src/compatibility/ConfigFileConf.h src/xml/XML.h + $(info -[20%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/HFileGen.o : src/HFileGen.cpp src/FileUtils.h src/Common.h src/Utils.h src/ConfigFile.h src/HFileGen.h - $(info -[33%]- $<) +$(OBJPATH)/HFileGen.o : src/HFileGen.cpp src/FileUtils.h src/Common.h src/Utils.h src/ConfigFile.h src/xml/XMLObject.h src/HFileGen.h + $(info -[30%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/IncludeDeps.o : src/IncludeDeps.cpp src/Common.h src/IncludeDeps.h src/ConfigFile.h src/FileUtils.h src/Utils.h - $(info -[44%]- $<) +$(OBJPATH)/IncludeDeps.o : src/IncludeDeps.cpp src/Common.h src/IncludeDeps.h src/ConfigFile.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h + $(info -[40%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/Makefile.o : src/Makefile.cpp src/IncludeDeps.h src/ConfigFile.h src/FileUtils.h src/Common.h src/Utils.h src/Makefile.h - $(info -[55%]- $<) +$(OBJPATH)/Makefile.o : src/Makefile.cpp src/IncludeDeps.h src/ConfigFile.h src/xml/XMLObject.h src/FileUtils.h src/Common.h src/Utils.h src/Makefile.h + $(info -[50%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/Utils.o : src/Utils.cpp src/FileUtils.h src/Common.h src/Utils.h src/ConfigFile.h - $(info -[66%]- $<) +$(OBJPATH)/Utils.o : src/Utils.cpp src/FileUtils.h src/Common.h src/Utils.h src/ConfigFile.h src/xml/XMLObject.h + $(info -[60%]- $<) $(CC) $(CFLAGS) -o $@ $< -$(OBJPATH)/main.o : src/main.cpp src/Common.h src/ConfigCLI.h src/ConfigFile.h src/FileUtils.h src/Utils.h src/HFileGen.h src/Makefile.h src/Timer.h - $(info -[77%]- $<) +$(OBJPATH)/ConfigFileConf.o : src/compatibility/ConfigFileConf.cpp src/compatibility/ConfigFileConf.h + $(info -[70%]- $<) + $(CC) $(CFLAGS) -o $@ $< +$(OBJPATH)/main.o : src/main.cpp src/Common.h src/ConfigCLI.h src/ConfigFile.h src/xml/XMLObject.h src/FileUtils.h src/Utils.h src/HFileGen.h src/Makefile.h src/Timer.h + $(info -[80%]- $<) $(CC) $(CFLAGS) -o $@ $< $(OBJPATH)/XML.o : src/xml/XML.cpp src/xml/XML.h src/xml/XMLObject.h src/xml/XMLException.h - $(info -[88%]- $<) + $(info -[90%]- $<) $(CC) $(CFLAGS) -o $@ $< $(OBJPATH)/XMLObject.o : src/xml/XMLObject.cpp src/xml/XMLException.h src/xml/XMLObject.h $(info -[100%]- $<) diff --git a/makegen.conf b/makegen.conf deleted file mode 100644 index e445d05..0000000 --- a/makegen.conf +++ /dev/null @@ -1,19 +0,0 @@ -#libs -#libdirs -#includedirs -#defines -_DEBUG -#compileflags -#dependencies -#srcdir -src/ -#outputdir -bin/ -#projectname -MakeGen -#outputname -makegen -#executable -true -#generatehfile -false diff --git a/makegen.xml b/makegen.xml new file mode 100644 index 0000000..9cb4cbf --- /dev/null +++ b/makegen.xml @@ -0,0 +1,14 @@ + + + _DEBUG + false + MakeGen.h + bin/ + makegen + executable + MakeGen + src/ + + Release + v1.3.0 + \ No newline at end of file diff --git a/src/Common.h b/src/Common.h index 6dea76f..2790775 100755 --- a/src/Common.h +++ b/src/Common.h @@ -10,7 +10,7 @@ // Major changes, probably not be backwards compatible #define MAKEGEN_VERSION_MAJOR 1 // Release, should be backwards compatible with any minor version -#define MAKEGEN_VERSION_RELEASE 2 +#define MAKEGEN_VERSION_RELEASE 3 // Minor changes, should be compatible with any other minor version with same major and release. #define MAKEGEN_VERSION_MINOR 0 #define MAKEGEN_VERSION ("v" STR(MAKEGEN_VERSION_MAJOR) "." STR(MAKEGEN_VERSION_RELEASE) "." STR(MAKEGEN_VERSION_MINOR)) diff --git a/src/ConfigFile.cpp b/src/ConfigFile.cpp index 5347bee..be7b7a1 100755 --- a/src/ConfigFile.cpp +++ b/src/ConfigFile.cpp @@ -1,17 +1,14 @@ #include "ConfigFile.h" #include "FileUtils.h" +#include "compatibility/ConfigFileConf.h" +#include "xml/XML.h" #include #include -#define FLAG_NONE 0 -#define FLAG_VECTOR 1 -#define FLAG_STRING 2 -#define FLAG_BOOL 3 - ConfigFile::ConfigFile() - : outputdir("bin/"), srcdir("src/"), outputname(""), projectname(FileUtils::GetCurrentDirectory()), hFile(""), executable(true), shared(true), generateHFile(false) + : outputdir("bin/"), srcdir("src/"), outputname(""), projectname(FileUtils::GetCurrentDirectory()), hFile(projectname+".h"), executable(true), shared(true), generateHFile(false) { // Converts project name (current directory) to lowercase // and replace whitespace with underscore @@ -54,27 +51,42 @@ std::optional ConfigFile::GetConfigFile(const std::string& filepath, return {}; } + bool oldFile = false; std::ifstream f(filepath + CONFIG_FILENAME); + if(!f.good()) + { + // try to read an old config file + f.close(); + f = std::ifstream(filepath + "makegen.conf"); + oldFile = true; + } + // Check if the file exists if(f.good()) { f.close(); - ConfigFile conf = ConfigFile::Load(realPath); - loadedConfigs.emplace(realPath, conf); + std::optional conf; + if(oldFile) + conf = ConfigFileConf::Load(realPath); + else + conf = ConfigFile::Load(realPath); + if(!conf) + return {}; + loadedConfigs.emplace(realPath, *conf); // Create dependency config files. - for(size_t i = 0; i < conf.dependencies.size();++i) + for(size_t i = 0; i < conf->dependencies.size();++i) { - std::optional dep = GetConfigFile(conf.configPath + conf.dependencies[i], loadedConfigs); + std::optional dep = GetConfigFile(conf->configPath + conf->dependencies[i], loadedConfigs); if(dep) { - conf.dependencyConfigs.push_back(*dep); - conf.dependencies[i] = dep->configPath; + conf->dependencyConfigs.push_back(*dep); + conf->dependencies[i] = dep->configPath; } else { // Remove the dependency since it is already accounted for - conf.dependencies.erase(conf.dependencies.begin() + i); + conf->dependencies.erase(conf->dependencies.begin() + i); --i; } } @@ -84,120 +96,99 @@ std::optional ConfigFile::GetConfigFile(const std::string& filepath, } -ConfigFile ConfigFile::Load(const std::string& filepath) +std::optional ConfigFile::Load(const std::string& filedir) { - ConfigFile conf; - conf.configPath = filepath; - unsigned int loadFlag = 0; + XMLObject object{XML::FromFile(filedir + CONFIG_FILENAME)}; - std::vector* vec; - std::string* s; - bool* b; - - bool isDirectory = false; - - std::ifstream file(filepath+CONFIG_FILENAME); - std::string line; - - if(file.is_open()) + const std::string& target = object.GetObject("target", {XMLObject{"target", {}, "Release"}})[0].GetText(); + const std::vector& configurations = object.GetObject("configuration"); + const XMLObject* configuration = nullptr; + for(auto it = configurations.begin(); it != configurations.end(); ++it) { - // config name, { pointer to memory, isDirectory} - std::map> strings = + if(!it->HasAttribute("name")) { - {"#srcdir", {&conf.srcdir, true}}, - {"#outputdir", {&conf.outputdir, true}}, - {"#outputname", {&conf.outputname, false}}, - {"#projectname", {&conf.projectname, false}}, - {"#hfile", {&conf.hFile, false}}, - }; + LOG_ERROR("No name attribute in configuration tag"); + continue; + } + if(it->GetAttribute("name") == target) + { + configuration = &(*it); + break; + } + } - // config name, { pointer to memory, isDirectory} - std::map*, bool>> vectors = - { - {"#libs", {&conf.libs, false}}, - {"#libdirs", {&conf.libdirs, true}}, - {"#includedirs", {&conf.includedirs, true}}, - {"#compileflags", {&conf.flags, false}}, - {"#defines", {&conf.defines, false}}, - {"#dependencies", {&conf.dependencies, true}}, - }; + if(configuration == nullptr) + { + LOG_ERROR("No configuration matching target: ", target); + return {}; + } - std::map booleans = - { - {"#executable", &conf.executable}, - {"#shared", &conf.shared}, - {"#generatehfile", &conf.generateHFile}, - }; + ConfigFile conf; + conf.configPath = filedir; + conf.projectname = configuration->GetObject("projectname", + {XMLObject{"projectname", {}, conf.projectname}})[0].GetText(); + conf.outputname = configuration->GetObject("outputname", + {XMLObject{"outputname", {}, conf.outputname}})[0].GetText(); + conf.srcdir = configuration->GetObject("srcdir", + {XMLObject{"srcdir", {}, conf.srcdir}})[0].GetText(); + conf.outputdir = configuration->GetObject("outputdir", + {XMLObject{"outputdir", {}, conf.outputdir}})[0].GetText(); + conf.hFile = configuration->GetObject("hfile", + {XMLObject{"hfile", {}, conf.hFile}})[0].GetText(); + std::string outputtype = configuration->GetObject("outputtype", + {XMLObject{"outputtype", {}, "executable"}})[0].GetText(); - while(std::getline(file,line)) + if(conf.srcdir[conf.srcdir.size()-1] != '/') + conf.srcdir += '/'; + if(conf.outputdir[conf.srcdir.size()-1] != '/') + conf.outputdir += '/'; + + if(outputtype == "executable") + conf.executable = true; + else if(outputtype == "staticlibrary") + { + conf.executable = false; + conf.shared = false; + } + else if(outputtype == "sharedlibrary") + { + conf.executable = false; + conf.shared = true; + } + else + { + LOG_ERROR("Invalid outputtype: ", outputtype); + LOG_ERROR("Valid arguments are executable, staticlibrary and sharedlibrary"); + } + conf.generateHFile = configuration->GetObject("generatehfile", + {XMLObject{"generatehfile", {}, conf.generateHFile ? "true" : "false"}})[0].GetText() == "true"; + + const int vectorCount = 6; + std::tuple, std::vector*, bool> vectors[vectorCount] = { + {configuration->GetObject("library"), &conf.libs, false}, + {configuration->GetObject("libdir"), &conf.libdirs, true}, + {configuration->GetObject("includedir"), &conf.includedirs, true}, + {configuration->GetObject("define"), &conf.defines, false}, + {configuration->GetObject("compileflag"), &conf.flags, false}, + {configuration->GetObject("dependency"), &conf.dependencies, true} + }; + + for(int i = 0;i& xmls = std::get<0>(vectors[i]); + std::vector* vec = std::get<1>(vectors[i]); + bool isDir = std::get<2>(vectors[i]); + for(auto it = xmls.begin(); it != xmls.end();++it) { - if(line == "") - continue; - if(line[0]=='#') + if(it->GetText() != "") { - // The format is a bit wacky, but it is this way since we do not want - // to use map::find for all maps. This way we gain some optimization. - auto&& itStr{strings.find(line)}; - if(itStr != strings.end()) - { - s = itStr->second.first; - isDirectory = itStr->second.second; - loadFlag = FLAG_STRING; - } - else - { - auto&& itVec{vectors.find(line)}; - if(itVec != vectors.end()) - { - vec = itVec->second.first; - isDirectory = itVec->second.second; - loadFlag = FLAG_VECTOR; - } - else - { - auto&& itBool{booleans.find(line)}; - if(itBool != booleans.end()) - { - b = itBool->second; - loadFlag = FLAG_BOOL; - } - else - { - LOG_ERROR("Invalid flag: ", line); - loadFlag = FLAG_NONE; - } - } - } - } - else - { - if(loadFlag == FLAG_STRING) - { - if(isDirectory && line[line.size()-1] != '/') - line += '/'; - *s = line; - } - else if(loadFlag == FLAG_VECTOR) - { - if(isDirectory && line[line.size()-1] != '/') - {; - line += '/'; - } - vec->push_back(line); - } - else if(loadFlag == FLAG_BOOL) - { - if(line == "true") - *b = true; - else - *b = false; - } + std::string s = it->GetText(); + if(isDir && s[s.size()-1] != '/') + s += '/'; + vec->push_back(s); } } } - if(conf.hFile == "") - conf.hFile = conf.projectname+".h"; - return conf; } @@ -279,58 +270,36 @@ ConfigFile ConfigFile::Gen() void ConfigFile::Save() const { - std::ofstream file("makegen.conf"); - file << "#libs" << std::endl; - for(auto it = libs.begin();it!=libs.end();++it) - { - file << *it << std::endl; - } - file << "#libdirs" << std::endl; - for(auto it = libdirs.begin();it!=libdirs.end();++it) - { - file << *it << std::endl; - } - file << "#includedirs" << std::endl; - for(auto it = includedirs.begin();it!=includedirs.end();++it) - { - file << *it << std::endl; - } - file << "#defines" << std::endl; - for(auto it = defines.begin();it!=defines.end();++it) - { - file << *it << std::endl; - } - file << "#compileflags" << std::endl; - for(auto it = flags.begin();it!=flags.end();++it) - { - file << *it << std::endl; - } - file << "#dependencies" << std::endl; - for(auto it = dependencies.begin();it!=dependencies.end();++it) - { - file << *it << std::endl; - } - file << "#srcdir" << std::endl; - file << srcdir << std::endl; - file << "#outputdir" << std::endl; - file << outputdir << std::endl; - file << "#projectname" << std::endl; - file << projectname << std::endl; - file << "#outputname" << std::endl; - file << outputname << std::endl; - file << "#executable" << std::endl; - file << (executable ? "true" : "false") << std::endl; - file << "#generatehfile" << std::endl; - file << (generateHFile ? "true" : "false") << std::endl; - if(generateHFile) - { - file << "#hfile" << std::endl; - file << hFile << std::endl; - } - if(!executable) - { - file << "#shared" << std::endl; - file << (shared ? "true" : "false") << std::endl; - } - file.close(); + XMLObject makegen("makegen", {}, std::map>{}); + + // Version, target and configuration is probably going to be used in the future + makegen.AddXMLObject(XMLObject("version", {}, "v1.3.0")); + makegen.AddXMLObject(XMLObject("target", {}, "Release")); + + XMLObject configuration("configuration", {{"name", "Release"}}, std::map>{}); + configuration.AddXMLObject(XMLObject("projectname", {}, projectname)); + configuration.AddXMLObject(XMLObject("outputname", {}, outputname)); + configuration.AddXMLObject(XMLObject("srcdir", {}, srcdir)); + configuration.AddXMLObject(XMLObject("outputdir", {}, outputdir)); + configuration.AddXMLObject(XMLObject("hfile", {}, hFile)); + configuration.AddXMLObject(XMLObject("outputtype", {}, + executable ? "executable" : (shared ? "sharedlibrary" : "staticlibrary"))); + configuration.AddXMLObject(XMLObject("generatehfile", {}, generateHFile ? "true" : "false")); + + for(auto it = libs.begin();it != libs.end(); ++it) + configuration.AddXMLObject({"library",{},*it}); + for(auto it = libdirs.begin();it != libdirs.end(); ++it) + configuration.AddXMLObject({"libdir",{},*it}); + for(auto it = includedirs.begin();it != includedirs.end(); ++it) + configuration.AddXMLObject({"includedir",{},*it}); + for(auto it = defines.begin();it != defines.end(); ++it) + configuration.AddXMLObject({"define",{},*it}); + for(auto it = flags.begin();it != flags.end(); ++it) + configuration.AddXMLObject({"compileflag",{},*it}); + for(auto it = dependencies.begin();it != dependencies.end(); ++it) + configuration.AddXMLObject({"dependency",{},*it}); + + makegen.AddXMLObject(configuration); + std::ofstream file("makegen.xml"); + file << makegen; } diff --git a/src/ConfigFile.h b/src/ConfigFile.h index 3d9b36b..6e8cc71 100755 --- a/src/ConfigFile.h +++ b/src/ConfigFile.h @@ -1,16 +1,19 @@ #pragma once +#include "xml/XMLObject.h" + #include #include #include #include -static const std::string CONFIG_FILENAME = "makegen.conf"; +static const std::string CONFIG_FILENAME = "makegen.xml"; class ConfigFile { public: std::string configPath; + std::vector libs; std::vector libdirs; std::vector includedirs; @@ -26,6 +29,7 @@ class ConfigFile bool executable; bool shared; bool generateHFile; + std::vector dependencyConfigs; public: ConfigFile(); @@ -34,7 +38,7 @@ class ConfigFile static std::optional GetConfigFile(const std::string& filepath = "./"); private: static std::optional GetConfigFile(const std::string& filepath, std::map& loadedConfigs); - static ConfigFile Load(const std::string& filename); + static std::optional Load(const std::string& filename); static void InputBoolean(const std::string& inputText, bool& b); static void InputMultiple(const std::string& inputText, std::vector& vec, bool needEnding); static void InputString(const std::string& inputText, std::string& vec, bool needEnding, bool allowEmpty); diff --git a/src/compatibility/ConfigFileConf.cpp b/src/compatibility/ConfigFileConf.cpp new file mode 100644 index 0000000..f5d45c1 --- /dev/null +++ b/src/compatibility/ConfigFileConf.cpp @@ -0,0 +1,164 @@ +#include "ConfigFileConf.h" + +const std::string CONFIG_FILENAME_CONF = "makegen.conf"; + +#include "../ConfigFile.h" +#include "../FileUtils.h" + +#include +#include + +#define FLAG_NONE 0 +#define FLAG_VECTOR 1 +#define FLAG_STRING 2 +#define FLAG_BOOL 3 + +ConfigFileConf::ConfigFileConf() + : outputdir("bin/"), srcdir("src/"), outputname(""), projectname(FileUtils::GetCurrentDirectory()), hFile(""), executable(true), shared(true), generateHFile(false) +{ + // Converts project name (current directory) to lowercase + // and replace whitespace with underscore + std::transform( + projectname.begin(), + projectname.end(), + std::back_inserter(outputname), + [](unsigned char c) + { + if(c == ' ') + return '_'; + return (char)std::tolower(c); + }); + + // Removes all other characters + std::remove_if( + outputdir.begin(), + outputdir.end(), + [](unsigned char c) + { + return (c < 'a' || c > 'z') && c != '_'; + }); + + // Add suffix + outputname += ".out"; +} + +ConfigFile ConfigFileConf::Load(const std::string& filepath) +{ + ConfigFile conf; + conf.configPath = filepath; + unsigned int loadFlag = 0; + + std::vector* vec; + std::string* s; + bool* b; + + bool isDirectory = false; + + std::ifstream file(filepath + CONFIG_FILENAME_CONF); + std::string line; + + if(file.is_open()) + { + // config name, { pointer to memory, isDirectory} + std::map> strings = + { + {"#srcdir", {&conf.srcdir, true}}, + {"#outputdir", {&conf.outputdir, true}}, + {"#outputname", {&conf.outputname, false}}, + {"#projectname", {&conf.projectname, false}}, + {"#hfile", {&conf.hFile, false}}, + }; + + // config name, { pointer to memory, isDirectory} + std::map*, bool>> vectors = + { + {"#libs", {&conf.libs, false}}, + {"#libdirs", {&conf.libdirs, true}}, + {"#includedirs", {&conf.includedirs, true}}, + {"#compileflags", {&conf.flags, false}}, + {"#defines", {&conf.defines, false}}, + {"#dependencies", {&conf.dependencies, true}}, + }; + + std::map booleans = + { + {"#executable", &conf.executable}, + {"#shared", &conf.shared}, + {"#generatehfile", &conf.generateHFile}, + }; + + while(std::getline(file,line)) + { + if(line == "") + continue; + if(line[0]=='#') + { + // The format is a bit wacky, but it is this way since we do not want + // to use map::find for all maps. This way we gain some optimization. + auto&& itStr{strings.find(line)}; + if(itStr != strings.end()) + { + s = itStr->second.first; + isDirectory = itStr->second.second; + loadFlag = FLAG_STRING; + } + else + { + auto&& itVec{vectors.find(line)}; + if(itVec != vectors.end()) + { + vec = itVec->second.first; + isDirectory = itVec->second.second; + loadFlag = FLAG_VECTOR; + } + else + { + auto&& itBool{booleans.find(line)}; + if(itBool != booleans.end()) + { + b = itBool->second; + loadFlag = FLAG_BOOL; + } + else + { + LOG_ERROR("Invalid flag: ", line); + loadFlag = FLAG_NONE; + } + } + } + } + else + { + if(loadFlag == FLAG_STRING) + { + if(isDirectory && line[line.size()-1] != '/') + line += '/'; + *s = line; + } + else if(loadFlag == FLAG_VECTOR) + { + if(isDirectory && line[line.size()-1] != '/') + {; + line += '/'; + } + vec->push_back(line); + } + else if(loadFlag == FLAG_BOOL) + { + if(line == "true") + *b = true; + else + *b = false; + } + } + } + } + if(conf.hFile == "") + conf.hFile = conf.projectname+".h"; + + LOG_INFO("------ COULDN\'T FIND makegen.xml. BUT FOUND OLD makegen.conf."); + LOG_INFO("------ GENERATING NEW CONFIGURATION FILE"); + + conf.Save(); + return conf; +} diff --git a/src/compatibility/ConfigFileConf.h b/src/compatibility/ConfigFileConf.h new file mode 100644 index 0000000..1bf3f4b --- /dev/null +++ b/src/compatibility/ConfigFileConf.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include + +class ConfigFile; + +class ConfigFileConf +{ + public: + std::string configPath; + std::vector libs; + std::vector libdirs; + std::vector includedirs; + std::vector defines; + std::vector flags; + std::vector dependencies; + + std::string outputdir; + std::string srcdir; + std::string outputname; + std::string projectname; + std::string hFile; + bool executable; + bool shared; + bool generateHFile; + public: + ConfigFileConf(); + + static ConfigFile Load(const std::string& filename); + private: +}; diff --git a/src/xml/XMLObject.cpp b/src/xml/XMLObject.cpp index 649214e..4466325 100644 --- a/src/xml/XMLObject.cpp +++ b/src/xml/XMLObject.cpp @@ -34,7 +34,7 @@ XMLObject::XMLObject(const std::string& name, const std::map& attributes, const std::vector& objects) +XMLObject::XMLObject(const std::string& name, const std::map& attributes, const std::map>& objects) : name(name), attributes(attributes), objects(objects) { @@ -66,15 +66,16 @@ unsigned int XMLObject::GetObjectCount() const return objects.size(); } -const XMLObject& XMLObject::GetObject(unsigned int i) const +const std::vector& XMLObject::GetObject(const std::string& name, const std::vector& defaults) const { - if (i >= objects.size()) - throw XMLException((std::string("XML index out of bounds \"") + std::to_string(i) + "\".").c_str()); + auto it = objects.find(name); + if(it == objects.end()) + return defaults; - return objects[i]; + return it->second; } -const std::vector& XMLObject::GetObjects() const +const std::map>& XMLObject::GetObjects() const { return objects; } @@ -108,7 +109,14 @@ void XMLObject::AddAttribute(const std::string& property, const std::string& val attributes.emplace(property, value); else LOG_ERROR("XML property name can only be made up of letters"); - +} +void XMLObject::AddXMLObject(const XMLObject& object) +{ + auto it = objects.find(object.name); + if(it == objects.end()) + objects.emplace(object.name, std::vector{object}); + else + it->second.push_back(object); } XMLObject XMLObject::GetStrippedXMLObject() const @@ -234,8 +242,7 @@ void XMLObject::ReadBodyTail(const std::string& string, XMLLoadData& data) std::string closeTag = GetClosingTag(string, data); while (closeTag.length() == 0) { - XMLObject object = XMLObject(string, data); - objects.push_back(object); + AddXMLObject(XMLObject(string, data)); ReadWhiteSpace(string, data); closeTag = GetClosingTag(string, data); } @@ -333,3 +340,46 @@ std::string XMLObject::ReadXMLName(const std::string& string, XMLLoadData& data) endPos++; return string.substr(data.pos, endPos - data.pos); } + +std::ostream& XMLObject::WriteToStream(std::ostream& stream, int indent) const +{ + for(int i = 0;ifirst << "=\"" << it->second << "\""; + } + stream << ">"; + if(text != "") + { + stream << text; + } + else + { + bool hasChild = false; + for(auto it = objects.begin(); it != objects.end();++it) + { + for(auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) + { + stream << "\n"; + it2->WriteToStream(stream, indent+1); + hasChild = true; + } + } + if(hasChild) + { + stream << "\n"; + for(int i = 0;i"; + + return stream; +} + diff --git a/src/xml/XMLObject.h b/src/xml/XMLObject.h index 6a2d2ff..817efc2 100644 --- a/src/xml/XMLObject.h +++ b/src/xml/XMLObject.h @@ -2,6 +2,7 @@ #include #include +#include #include class XMLObject @@ -19,7 +20,7 @@ class XMLObject std::string text; std::map attributes; - std::vector objects; + std::map> objects; public: XMLObject() {} @@ -27,15 +28,15 @@ class XMLObject XMLObject(const std::string& string, int pos, int line, const std::string& file); XMLObject(const std::string& string, XMLLoadData& data); XMLObject(const std::string& name, const std::map& properties, const std::string& text); - XMLObject(const std::string& name, const std::map& properties, const std::vector& objects); + XMLObject(const std::string& name, const std::map& properties, const std::map>& objects); bool HasAttribute(const std::string& property) const; const std::string& GetAttribute(const std::string& property) const; const std::string& GetAttribute(const std::string& property, const std::string& defaultValue) const; unsigned int GetObjectCount() const; - const XMLObject& GetObject(unsigned int i) const; - const std::vector& GetObjects() const; + const std::vector& GetObject(const std::string& name, const std::vector& defaults = {}) const; + const std::map>& GetObjects() const; const std::string& GetName() const; const std::string& GetText() const; XMLObject GetStrippedXMLObject() const; @@ -43,6 +44,18 @@ class XMLObject void SetName(const std::string& name); void SetText(const std::string& text); void AddAttribute(const std::string& property, const std::string& value); + void AddXMLObject(const XMLObject& object); + + friend bool operator<(const XMLObject& obj1, const XMLObject& obj2) + { + return obj1.name < obj2.name; + } + + std::ostream& WriteToStream(std::ostream& stream, int indent = 0) const; + friend std::ostream& operator<<(std::ostream& stream, const XMLObject& object) + { + return object.WriteToStream(stream); + } private: std::string GetClosingTag(const std::string& string, XMLLoadData& data);