CMPASSERT, config WIP

This commit is contained in:
mrbesen 2021-02-07 21:25:58 +01:00
parent bb068d12e4
commit 432b3de3eb
Signed by untrusted user: MrBesen
GPG Key ID: 596B2350DCD67504
8 changed files with 179 additions and 8 deletions

37
inc/config.h Normal file
View File

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

View File

@ -24,13 +24,19 @@ enum class FileType : unsigned char {
//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<void(const std::string&, FileType type)> fileCallback;
template<class Container>
bool scan(const std::string& path, std::insert_iterator<Container> it, bool prefixdir = false, fileNameFilter fnf = fileNameFilter(nullptr));
bool scan(const std::string& path, fileCallback clb, bool prefixdir = false, fileNameFilter fnf = fileNameFilter(nullptr));
bool readFile(const std::string& name, std::ostream& output, unsigned int maxsize = 0); //reads file name and writes it line for line into output, it stops at maxsize (it might be a bit more, its not a hard limit - see it more as a hint), if maxsize is 0 it reads unlimited
bool readFile(const std::string& name, std::ostream& output, unsigned int maxsize = 0); //reads file name and writes it line for line into output, it stops at maxsize (it might be a bit more, its not a hard limit - see it more as a hint), if maxsize is 0 it reads unlimited
bool readFile(int fd, std::ostream& output, unsigned int maxsize = 0);
bool copy(int fd_from, int fd_to);

View File

@ -24,6 +24,7 @@ bool removeStart(std::string& str, const std::string& start);
bool insertEnd(std::string& str, const std::string& ending);
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);
bool trim(std::string& str, char c = ' '); //return true if the string was changed

88
src/config.cpp Normal file
View File

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

View File

@ -1,6 +1,7 @@
#include "files.h"
#include <dirent.h>
#include <fstream>
#include <list>
#include <set>
@ -54,6 +55,28 @@ void mrbesen::files::extention(const std::string& path, std::string& ext) {
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>
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);

View File

@ -2,6 +2,7 @@
#include "files.h"
#include "util.h"
#include <fstream>
#include <list>
#include <set>
#include <string>
@ -12,6 +13,8 @@
#include <unistd.h>
#include <fcntl.h>
#define NONEXISTENT_FILE "tests/blabla.exe"
using namespace mrbesen;
int testFiles_parent() {
@ -19,20 +22,20 @@ int testFiles_parent() {
std::string testpath1 = "/asdf1/asdf2/test.png";
files::parent(testpath1, out);
ASSERT(out == "/asdf1/asdf2/", out);
CMPASSERT(out, "/asdf1/asdf2/");
files::parent(out, out2);
ASSERT(out2 == "/asdf1/", out2);
CMPASSERT(out2, "/asdf1/");
files::parent(out2, out);
ASSERT(out == "/", out);
CMPASSERT(out, "/");
testpath1 = "assets/tex/img1.png";
files::parent(testpath1, out);
ASSERT(out == "assets/tex/", out);
CMPASSERT(out, "assets/tex/");
files::parent("asd", out);
ASSERT(out == "", out);
CMPASSERT(out, "");
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() {
std::string path = "./tests";
std::list<std::string> out, out2;
@ -132,7 +145,7 @@ int testFiles_readFile() {
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);
ASSERT(r, "failed to read");

View File

@ -5,6 +5,7 @@
int testFiles_parent();
int testFiles_file();
int testFiles_extention();
int testFiles_iterateFile();
int testFiles_scan();
int testFiles_readFile();
@ -25,7 +26,7 @@ int testUtilSplit();
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,
testStringSpliterator, testUtilSplit,
testGetDoy,

View File

@ -6,6 +6,8 @@
#define TESTDATA "./tests/data/"
#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, "")
typedef int (*test_t)();