readconf/source/readconf.d

158 lines
3.7 KiB
D

module readconf;
import std.stdio, std.conv, std.path, std.file;
import core.stdc.stdlib : exit;
import std.regex;
import std.meta;
import singlog;
class Config
{
private:
static Config config;
string path;
PP[string] properties;
bool readed = false;
/**
* Parameter and its value with the ability to convert to the desired data type
*/
struct PP
{
private string property;
private string value;
/**
* Checking for the presence of a parameter
* Returns: true if the parameter is missing, otherwise false
*/
@property bool empty()
{
return this.property.length = 0;
}
/**
* Get a string representation of the value
* Returns: default string value
*/
@property string toString() const
{
return value;
}
alias toString this;
auto opCast(T)() const
{
try {
return this.value.to!T;
} catch (Exception e) {
Log.msg.error("Cannot convert type");
Log.msg.warning(e);
return T.init;
}
}
}
/**
* Reading the configuration file
*/
void readConfig()
{
File configuration;
try {
configuration = File(this.path, "r");
} catch (Exception e) {
Log.msg.error("Unable to open the configuration file " ~ this.path);
Log.msg.warning(e);
return;
}
string pattern = "^ *(\\w+)(( +=> +)|( += +))(?!\\/\\/)(([^ >\"'\\n#;].*?)|"
~ "(\"(.+?)\")|('(.+?)')){1} *( #.*?)?( ;.*?)?( \\/\\/.*)?$";
auto regular = regex(pattern, "m");
while (!configuration.eof())
{
string line = configuration.readln();
auto match = matchFirst(line, regular);
if (match)
{
int group = 5;
if (match[group].length)
{
if (match[group][0] == '\'')
group = 10;
if (match[group][0] == '\"')
group = 8;
}
this.properties[match[1]] = PP(match[1], match[group]);
}
}
try {
configuration.close();
this.readed = true;
} catch (Exception e) {
Log.msg.error("Unable to close the configuration file " ~ this.path);
Log.msg.warning(e);
return;
}
}
this() {}
public:
/**
* Accessing the Config object
* Returns: Config Object
*/
@property static Config file()
{
if (this.config is null)
this.config = new Config;
return this.config;
}
/**
* Read the configuration file
* Params:
* path = the path to the configuration file
*/
void read(string path)
{
this.path = path;
if (!path.exists)
{
Log.msg.error("The configuration file does not exist: " ~ path);
return;
}
readConfig();
}
/**
* Get the parameter value
* Params:
* key = parameter from the configuration file
* Returns: the value of the parameter in the PP structure view
*/
PP key(string key)
{
if (this.readed)
return key in this.properties ? this.properties[key] : PP();
Log.msg.warning("The configuration file was not read!");
return PP();
}
/**
* Get all keys and their values
* Returns: collection of properties structures PP
*/
PP[string] keys()
{
return this.properties;
}
}