forked from MrBesen/libmrbesen
CMPASSERT, config WIP
This commit is contained in:
parent
bb068d12e4
commit
432b3de3eb
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace mrbesen {
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
public:
|
||||||
|
class Section {
|
||||||
|
public:
|
||||||
|
template<typename T = const std::string*>
|
||||||
|
T get(const std::string& valueName) const;
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> values;
|
||||||
|
friend class Config;
|
||||||
|
};
|
||||||
|
|
||||||
|
Config(const std::string& filename);
|
||||||
|
virtual ~Config();
|
||||||
|
|
||||||
|
bool loadConfig();
|
||||||
|
const Section* getSection(std::string sectionName) const;
|
||||||
|
|
||||||
|
template<typename T = const std::string*>
|
||||||
|
T get(const std::string& valueName) const;
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::string filename;
|
||||||
|
|
||||||
|
std::map<std::string, Section> sections;
|
||||||
|
Section main; // config values without a section
|
||||||
|
|
||||||
|
static const std::string SPLIT;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,12 @@ enum class FileType : unsigned char {
|
||||||
//copied from dirent.h -> see man readdir
|
//copied from dirent.h -> see man readdir
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//read through a file line by line call the callback with every line (without \n or \r) return true on sccess or false on error
|
||||||
|
typedef std::function<void(const std::string&)> fileLineCallback;
|
||||||
|
bool iterateFile(const std::string& filename, fileLineCallback clb, bool ignoreBlanks = true);
|
||||||
|
bool iterateFile(std::istream& file, fileLineCallback clb, bool ignoreBlanks = true);
|
||||||
|
|
||||||
|
//iterate over a folder
|
||||||
typedef std::function<bool(const std::string&, FileType type)> fileNameFilter;
|
typedef std::function<bool(const std::string&, FileType type)> fileNameFilter;
|
||||||
typedef std::function<void(const std::string&, FileType type)> fileCallback;
|
typedef std::function<void(const std::string&, FileType type)> fileCallback;
|
||||||
template<class Container>
|
template<class Container>
|
||||||
|
|
|
@ -24,6 +24,7 @@ bool removeStart(std::string& str, const std::string& start);
|
||||||
bool insertEnd(std::string& str, const std::string& ending);
|
bool insertEnd(std::string& str, const std::string& ending);
|
||||||
bool insertStart(std::string& str, const std::string& start);
|
bool insertStart(std::string& str, const std::string& start);
|
||||||
|
|
||||||
|
// splits a string into components. It removes the token from the strings. Retunrs the Count of elements in the array after the function completes.
|
||||||
unsigned int split(const std::string& str, const std::string& token, std::string* out, unsigned int count);
|
unsigned int split(const std::string& str, const std::string& token, std::string* out, unsigned int count);
|
||||||
|
|
||||||
bool trim(std::string& str, char c = ' '); //return true if the string was changed
|
bool trim(std::string& str, char c = ' '); //return true if the string was changed
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "files.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
namespace mrbesen {
|
||||||
|
|
||||||
|
const std::string Config::SPLIT = ".";
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
const std::string* Config::Section::get(const std::string& valueName) const {
|
||||||
|
auto it = values.find(valueName);
|
||||||
|
if(it == values.end()) return nullptr;
|
||||||
|
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Config::Section::get(const std::string& valueName) const {
|
||||||
|
return (T) get<const std::string*>(valueName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Config::Config(const std::string& filename) : filename(filename) {}
|
||||||
|
|
||||||
|
Config::~Config() {}
|
||||||
|
|
||||||
|
bool Config::loadConfig() {
|
||||||
|
main.values.clear();
|
||||||
|
sections.clear();
|
||||||
|
|
||||||
|
Config::Section* currentSection = &main;
|
||||||
|
|
||||||
|
files::iterateFile(filename, [this](const std::string& line){
|
||||||
|
if(line[0] == '#' || line[0] == ';') return;
|
||||||
|
|
||||||
|
if(line[0] == '[' && util::endsWith(line, "]")) {
|
||||||
|
std::string sectionName = line.substr(1, line.length()-2);
|
||||||
|
util::trim(sectionName);
|
||||||
|
if(sectionName.empty()) {
|
||||||
|
//currentSection = &main;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//check for existing section
|
||||||
|
auto it = sections.find(sectionName);
|
||||||
|
if(it == sections.end()) {
|
||||||
|
//create new section
|
||||||
|
//TODO
|
||||||
|
sections.insert({sectionName, {}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string split[2];
|
||||||
|
unsigned int spl = util::split(line, "=", split, 2);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Config::Section* Config::getSection(std::string sectionName) const {
|
||||||
|
util::removeEnd(sectionName, SPLIT);
|
||||||
|
if(sectionName.empty())
|
||||||
|
return &main;
|
||||||
|
auto it = sections.find(sectionName);
|
||||||
|
if(it == sections.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &it->second;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Config::get(const std::string& valueName) const {
|
||||||
|
if(valueName.empty()) return nullptr;
|
||||||
|
|
||||||
|
std::string out[2];
|
||||||
|
unsigned int i = util::split(valueName, ".", out, 2);
|
||||||
|
|
||||||
|
if(i == 1) {
|
||||||
|
//main section
|
||||||
|
return main.get<T>(out[0]);
|
||||||
|
}
|
||||||
|
const Config::Section* sect = getSection(out[0]);
|
||||||
|
if(sect) return sect->get(out[1]);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <fstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
@ -54,6 +55,28 @@ void mrbesen::files::extention(const std::string& path, std::string& ext) {
|
||||||
ext = filestr.substr(pos+1);
|
ext = filestr.substr(pos+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mrbesen::files::iterateFile(const std::string& filename, fileLineCallback clb, bool ignoreBlanks) {
|
||||||
|
std::ifstream fs(filename);
|
||||||
|
return iterateFile(fs, clb, ignoreBlanks);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mrbesen::files::iterateFile(std::istream& file, fileLineCallback clb, bool ignoreBlanks) {
|
||||||
|
if(!clb) return false;
|
||||||
|
if(!file) return false;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while(std::getline(file, line)) {
|
||||||
|
mrbesen::util::removeEnd(line, "\r");
|
||||||
|
|
||||||
|
if(ignoreBlanks && line.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clb(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<class Container>
|
template<class Container>
|
||||||
bool mrbesen::files::scan(const std::string& path, std::insert_iterator<Container> it, bool prefixdir, fileNameFilter fnf) {
|
bool mrbesen::files::scan(const std::string& path, std::insert_iterator<Container> it, bool prefixdir, fileNameFilter fnf) {
|
||||||
return scan(path, [&](const std::string& p, FileType t){ it = p; }, prefixdir, fnf);
|
return scan(path, [&](const std::string& p, FileType t){ it = p; }, prefixdir, fnf);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -12,6 +13,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define NONEXISTENT_FILE "tests/blabla.exe"
|
||||||
|
|
||||||
using namespace mrbesen;
|
using namespace mrbesen;
|
||||||
|
|
||||||
int testFiles_parent() {
|
int testFiles_parent() {
|
||||||
|
@ -19,20 +22,20 @@ int testFiles_parent() {
|
||||||
std::string testpath1 = "/asdf1/asdf2/test.png";
|
std::string testpath1 = "/asdf1/asdf2/test.png";
|
||||||
|
|
||||||
files::parent(testpath1, out);
|
files::parent(testpath1, out);
|
||||||
ASSERT(out == "/asdf1/asdf2/", out);
|
CMPASSERT(out, "/asdf1/asdf2/");
|
||||||
|
|
||||||
files::parent(out, out2);
|
files::parent(out, out2);
|
||||||
ASSERT(out2 == "/asdf1/", out2);
|
CMPASSERT(out2, "/asdf1/");
|
||||||
|
|
||||||
files::parent(out2, out);
|
files::parent(out2, out);
|
||||||
ASSERT(out == "/", out);
|
CMPASSERT(out, "/");
|
||||||
|
|
||||||
testpath1 = "assets/tex/img1.png";
|
testpath1 = "assets/tex/img1.png";
|
||||||
files::parent(testpath1, out);
|
files::parent(testpath1, out);
|
||||||
ASSERT(out == "assets/tex/", out);
|
CMPASSERT(out, "assets/tex/");
|
||||||
|
|
||||||
files::parent("asd", out);
|
files::parent("asd", out);
|
||||||
ASSERT(out == "", out);
|
CMPASSERT(out, "");
|
||||||
|
|
||||||
return TESTGOOD;
|
return TESTGOOD;
|
||||||
}
|
}
|
||||||
|
@ -110,6 +113,16 @@ int testFiles_extention() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int testFiles_iterateFile() {
|
||||||
|
std::ifstream f1(NONEXISTENT_FILE);
|
||||||
|
ASSERT(!files::iterateFile(f1, [](const std::string&) {}), "");
|
||||||
|
|
||||||
|
//TODO: more tests
|
||||||
|
|
||||||
|
return TESTGOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int testFiles_scan() {
|
int testFiles_scan() {
|
||||||
std::string path = "./tests";
|
std::string path = "./tests";
|
||||||
std::list<std::string> out, out2;
|
std::list<std::string> out, out2;
|
||||||
|
@ -132,7 +145,7 @@ int testFiles_readFile() {
|
||||||
|
|
||||||
std::ostringstream buf;
|
std::ostringstream buf;
|
||||||
|
|
||||||
ASSERT(!files::readFile("tests/blabla.exe", buf), "this file should not be read"); //try to read non existing file
|
ASSERT(!files::readFile(NONEXISTENT_FILE, buf), "this file should not be read"); //try to read non existing file
|
||||||
|
|
||||||
bool r = files::readFile(std::string("tests/filestests.cpp"), buf);
|
bool r = files::readFile(std::string("tests/filestests.cpp"), buf);
|
||||||
ASSERT(r, "failed to read");
|
ASSERT(r, "failed to read");
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
int testFiles_parent();
|
int testFiles_parent();
|
||||||
int testFiles_file();
|
int testFiles_file();
|
||||||
int testFiles_extention();
|
int testFiles_extention();
|
||||||
|
int testFiles_iterateFile();
|
||||||
int testFiles_scan();
|
int testFiles_scan();
|
||||||
int testFiles_readFile();
|
int testFiles_readFile();
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ int testUtilSplit();
|
||||||
|
|
||||||
int testGetDoy();
|
int testGetDoy();
|
||||||
|
|
||||||
test_t tests[] = {testFiles_parent, testFiles_file, testFiles_extention, testFiles_scan, testFiles_readFile,
|
test_t tests[] = {testFiles_parent, testFiles_file, testFiles_extention, testFiles_iterateFile, testFiles_scan, testFiles_readFile,
|
||||||
testUtil_Count, testUtil_equalsIgnoreCase, testUtil_toLower, testUtil_start_endWith, testUtil_removeStart_End, testUtil_insertStart_End, testUtil_trim, testUtil_trimOnce, testUtil_base, testUtil_replace, testUtil_replace2,
|
testUtil_Count, testUtil_equalsIgnoreCase, testUtil_toLower, testUtil_start_endWith, testUtil_removeStart_End, testUtil_insertStart_End, testUtil_trim, testUtil_trimOnce, testUtil_base, testUtil_replace, testUtil_replace2,
|
||||||
testStringSpliterator, testUtilSplit,
|
testStringSpliterator, testUtilSplit,
|
||||||
testGetDoy,
|
testGetDoy,
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#define TESTDATA "./tests/data/"
|
#define TESTDATA "./tests/data/"
|
||||||
|
|
||||||
#define ASSERT(BED, ERR) if(!(BED)) { std::cout << __FILE__ << ":" << __LINE__ << " " << ERR << std::endl; return TESTFAILED; }
|
#define ASSERT(BED, ERR) if(!(BED)) { std::cout << __FILE__ << ":" << __LINE__ << " " << ERR << std::endl; return TESTFAILED; }
|
||||||
|
#define CMPASSERTE(A, B, ERR) if( !((A) == (B))) { std::cout << __FILE__ << ":" << __LINE__ << " is: \"" << (A) << "\" should: \"" << (B) << "\""<< std::endl; return TESTFAILED; }
|
||||||
|
#define CMPASSERT(A, B) CMPASSERTE(A, B, "")
|
||||||
// #define ASSERT(BED) ASSERT(BED, "")
|
// #define ASSERT(BED) ASSERT(BED, "")
|
||||||
|
|
||||||
typedef int (*test_t)();
|
typedef int (*test_t)();
|
||||||
|
|
Loading…
Reference in New Issue