<commit_before>#include <iostream>
#include <fstream>
#include <unordered_map>
#include <string>
#include <iterator>
#include <utility>
#include <stdexcept>
#include "logger.hpp"
#include "config.hpp"

std::unordered_map<std::string, std::pair<std::string, bool>> Config::vars = {
//	{ "name",				{ "default value", is_integer} }
	{ "type",				{ "private", false } },
	{ "port",				{ "48151", true } },
	{ "timeout",				{ "600", true } },
	{ "clear_peers_interval",		{ "300", true } },
	{ "read_buffer_size",			{ "512", true } },
	{ "max_request_size",			{ "4096", true } },
	{ "DB_Host",				{ "127.0.0.1", false } },
	{ "DB_User",				{ "jux", false } },
	{ "DB_Password",			{ "<PASSWORD>", false } },
	{ "DB_DBName",				{ "onche", false } },
	{ "DB_Port",				{ "3306", true } },
};

std::string Config::get(const std::string& name)
{
	try {
		return vars.at(name).first;
	}
	catch (const std::exception& e) {
		LOG_ERROR("Error in Config::get(" + name + ")");
		return "";
	}
}

int Config::getInt(const std::string& name)
{
	try {
		return std::stoi(vars.at(name).first);
	}
	catch (const std::exception& e) {
		LOG_ERROR("Error in Config::getInt(" + name + ")");
		return -1;
	}
}

void Config::load(const std::string& file)
{
	std::ifstream f(file);
	std::string line;
	unsigned int lineNumber = 1;
	std::string whitespaces(" \t\v\f\r");
	auto trim = [&whitespaces](const std::string& str, size_t start, size_t end) -> std::string {
		start = str.find_first_not_of(whitespaces, start);
		end = str.find_last_not_of(whitespaces, end);
		return std::string(str, start, end - start + 1);
	};

	if (!f)
		throw std::runtime_error("Couldn't open " + file + ". Aborted.");

	while (!f.eof()) {
		std::getline(f, line);
		if (line.empty())
			continue;

		size_t start = line.find_first_not_of(whitespaces);
		if (line[start] == '#')
			continue; // this line is a comment

		size_t equalSign = line.find('=');
		if (equalSign == std::string::npos || equalSign == start || equalSign == line.size() - 1) {
			LOG_ERROR(std::to_string(lineNumber) + ": syntax error");
			continue;
		}

		std::string name = trim(line, start, equalSign - 1);
		if (vars.find(name) == vars.end()) {
			LOG_ERROR(std::to_string(lineNumber) + ": " + name + ": name not valid");
			continue;
		}
		std::string value = trim(line, equalSign + 1, line.size() - 1);

		if (checkValue(name, value))
			vars.at(name).first = value;

		++lineNumber;
	}
}

bool Config::checkValue(const std::string& name, std::string& value)
{
	if (vars.at(name).second) {
		try {
			std::stoi(value);
		}
		catch (const std::exception& e) {
			LOG_ERROR(name + ": must be an integer");
			return false;
		}<commit_msg>fix lineNumber increment<commit_after>#include <iostream>
#include <fstream>
#include <unordered_map>
#include <string>
#include <iterator>
#include <utility>
#include <stdexcept>
#include "logger.hpp"
#include "config.hpp"

std::unordered_map<std::string, std::pair<std::string, bool>> Config::vars = {
//	{ "name",				{ "default value", is_integer} }
	{ "type",				{ "private", false } },
	{ "port",				{ "48151", true } },
	{ "timeout",				{ "600", true } },
	{ "clear_peers_interval",		{ "300", true } },
	{ "read_buffer_size",			{ "512", true } },
	{ "max_request_size",			{ "4096", true } },
	{ "DB_Host",				{ "127.0.0.1", false } },
	{ "DB_User",				{ "jux", false } },
	{ "DB_Password",			{ "<PASSWORD>", false } },
	{ "DB_DBName",				{ "onche", false } },
	{ "DB_Port",				{ "3306", true } },
};

std::string Config::get(const std::string& name)
{
	try {
		return vars.at(name).first;
	}
	catch (const std::exception& e) {
		LOG_ERROR("Error in Config::get(" + name + ")");
		return "";
	}
}

int Config::getInt(const std::string& name)
{
	try {
		return std::stoi(vars.at(name).first);
	}
	catch (const std::exception& e) {
		LOG_ERROR("Error in Config::getInt(" + name + ")");
		return -1;
	}
}

void Config::load(const std::string& file)
{
	std::ifstream f(file);
	std::string line;
	unsigned int lineNumber = 1;
	std::string whitespaces(" \t\v\f\r");
	auto trim = [&whitespaces](const std::string& str, size_t start, size_t end) -> std::string {
		start = str.find_first_not_of(whitespaces, start);
		end = str.find_last_not_of(whitespaces, end);
		return std::string(str, start, end - start + 1);
	};

	if (!f)
		throw std::runtime_error("Couldn't open " + file + ". Aborted.");

	while (!f.eof()) {
		std::getline(f, line);

		size_t start = line.find_first_not_of(whitespaces);
		if (line.empty() || start == std::string::npos || line[start] == '#') {
			++lineNumber;
			continue; // empty line or comment
		}

		size_t equalSign = line.find('=');
		if (equalSign == std::string::npos || equalSign == start || equalSign == line.size() - 1) {
			LOG_ERROR(std::to_string(lineNumber) + ": syntax error");
			continue;
		}

		std::string name = trim(line, start, equalSign - 1);
		if (vars.find(name) == vars.end()) {
			LOG_ERROR(std::to_string(lineNumber) + ": " + name + ": name not valid");
			continue;
		}
		std::string value = trim(line, equalSign + 1, line.size() - 1);

		if (checkValue(name, value))
			vars.at(name).first = value;

		++lineNumber;
	}
}

bool Config::checkValue(const std::string& name, std::string& value)
{
	if (vars.at(name).second) {
		try {
			std::stoi(value);
		}
		catch (const std::exception& e) {
			LOG_ERROR(name + ": must be an integer");
			return false;
		}
{'fraction_non_alphanumeric': 0.20438498699368265, 'fraction_numerical': 0.013006317354143442, 'mean_word_length': 3.9750462107208873, 'pattern_counts': {'":': 8, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '454338', 'n_tokens_mistral': 2227, 'n_tokens_neox': 2039, 'n_words': 438}