mIni doesn't parse properly strings
Closed this issue · 4 comments
Hi !
I realised a problem in mIni as it doesn't parse strings properly, the string should be parsed as A MineServer !
but is instead parsed as A
.
Config :
[network]
port = 25565
[display]
motd = A MineServer !
[other]
max-players = 100
Using logging here is what I get :
[DEBUG] 10:34:32 - Parsed port as 25565
[DEBUG] 10:34:32 - Parsed motd as A
[DEBUG] 10:34:32 - Parsed max-players as 100
[INFO] 10:34:32 - Motd : A
Hi. I tried it on my end and it works for me. Can you share your code - preferably a small testcase that reproduces the problem? Which library version are you using? Thanks.
Hi there !
I am using the latest version that you uploaded yesterday ! And for the config, I wrote my own wrapper around it, here is the code :
Config.h
//
// Created by Lygaen on 22/02/2022.
//
#ifndef MINESERVER_CONFIG_H
#define MINESERVER_CONFIG_H
#include <unordered_map>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include "../vendor/ini.h"
#define MINESERVER_VERSION_NAME "1.8.9 MineServer"
#define MINESERVER_PROTOCOL_VERSION 47
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, std::string> stringify(T t) {
return std::to_string(t);
}
template<typename T>
std::enable_if_t<!std::is_arithmetic<T>::value, std::string> stringify(T t) {
return static_cast<std::ostringstream &>(std::ostringstream() << t).str();
}
inline std::string stringify(std::string t) {
return t;
}
template<typename T>
T getStringAs(std::string &s) {
std::stringstream convert(s);
T value;
convert >> value;
return value;
}
inline std::string getStringAs(std::string &s) {
return s;
}
template<typename T>
class Field {
private:
T value;
const char* fieldName;
const char* section;
public:
Field(const char* section, const char* fieldName, T defaultValue) : section(section), value(defaultValue),
fieldName(fieldName) {}
void parseFromMap(const mINI::INIStructure &structure) {
if (structure.has(section) && structure.get(section).has(fieldName)) {
auto val = structure.get(section).get(fieldName);
value = getStringAs<T>(val);
}
}
void parseFromArgs(std::vector<std::string> &args) {
auto loc = std::find(args.begin(), args.end(), "--" + std::string(fieldName));
if (loc != args.end() && std::next(loc) != args.end()) {
auto index = std::distance(args.begin(), std::next(loc));
auto val = args[index];
value = getStringAs<T>(val);
}
}
void saveToMap(mINI::INIStructure &structure) {
if (!structure.has(section) || !structure.get(section).has(fieldName)) {
structure[section][fieldName] = stringify(value);
}
}
void set(T v) { value = v; }
[[nodiscard]] T get() const { return value; }
};
class Config {
private:
mINI::INIFile file = mINI::INIFile("config.ini");
mINI::INIStructure data;
static Config* instance;
public:
Config(int argc, char* argv[]);
bool loadFromFile();
bool save();
static Config* getInstance() {
return instance;
}
Field<unsigned short> port = Field<unsigned short>("network", "port", 25565);
Field<unsigned int> maxPlayers = Field<unsigned int>("other", "max-players", 100);
Field<std::string> motd = Field<std::string>("display", "motd", "A MineServer !");
};
#endif //MINESERVER_CONFIG_H
Config.cpp
//
// Created by Lygaen on 22/02/2022.
//
#include "config.h"
#include <iostream>
#include <filesystem>
#include "logger.h"
Config* Config::instance;
bool Config::loadFromFile() {
bool success = file.read(data);
if (!success) {
return false;
}
port.parseFromMap(data);
motd.parseFromMap(data);
maxPlayers.parseFromMap(data);
return true;
}
bool Config::save() {
port.saveToMap(data);
motd.saveToMap(data);
maxPlayers.saveToMap(data);
return file.write(data, false);
}
Config::Config(int argc, char** argv) {
if (!std::filesystem::exists("./config.ini")) {
std::ofstream ofs("./config.ini");
ofs.close();
}
bool success = loadFromFile();
if (!success) {
logger::critical("Cannot load data from config !");
exit(1);
}
std::vector<std::string> args{argv + 1, argv + argc};
port.parseFromArgs(args);
motd.parseFromArgs(args);
maxPlayers.parseFromArgs(args);
success = save();
if (!success) {
logger::critical("Cannot save data to the config !");
exit(1);
}
instance = this;
}
While you checkout the code, I'll be writing a test case !
Sorry for the bother, after some extensive search I found out that the error was on my side...
I'm deeply sorry...
Thank you for your time !
No problem - glad you found the issue!