v0.3.0
This commit is contained in:
commit
2b9e0366f4
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -1,11 +1,36 @@
|
|||
# Changelog
|
||||
|
||||
## [0.2.0]()
|
||||
## [v0.3.0](https://git.zhirov.kz/dlang/readconf/compare/v0.2.0...v0.3.0) (2023.03.30)
|
||||
|
||||
26.03.2023
|
||||
### New
|
||||
|
||||
- Read multiple configuration files
|
||||
- Quick access to a file/section/parameter using indexes
|
||||
|
||||
### Other
|
||||
|
||||
- Updated unittests
|
||||
- Added [examples](examples/) of configuration files
|
||||
- [Wiki](https://git.zhirov.kz/dlang/readconf/wiki) added
|
||||
|
||||
## [v0.2.0](https://git.zhirov.kz/dlang/readconf/compare/v0.1.1...v0.2.0) (2023.03.26)
|
||||
|
||||
### New
|
||||
|
||||
- Adding sections support
|
||||
- Taking into account spaces and tabs to separate the parameter, value and comment
|
||||
- Added aliases to convenient parameter access to the value
|
||||
|
||||
## [v0.1.1](https://git.zhirov.kz/dlang/readconf/compare/v0.1.0...v0.1.1) (2023.03.24)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Checking empty keys
|
||||
- Reading an expression in quotation marks
|
||||
|
||||
## [v0.1.0](https://git.zhirov.kz/dlang/readconf/commits/6409917cbe6a287db73fe3eea4bccaadf00379e7) (2023.03.23)
|
||||
|
||||
### The first stable working release
|
||||
|
||||
- The parameters are separated by `=` or `=>`
|
||||
- The ability to comment lines through delimiters `;`, `#`, `//`
|
||||
|
|
44
README.md
44
README.md
|
@ -1,13 +1,25 @@
|
|||
# readconf
|
||||
<p align="center">
|
||||
<img src="img/logo.png" width=320>
|
||||
</p>
|
||||
|
||||
<h1 align="center">readconf</h1>
|
||||
|
||||
[![license](https://img.shields.io/github/license/AlexanderZhirov/readconf.svg?sort=semver&style=for-the-badge&color=green)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
|
||||
[![main](https://img.shields.io/badge/dynamic/json.svg?label=git.zhirov.kz&style=for-the-badge&url=https://git.zhirov.kz/api/v1/repos/dlang/readconf/tags&query=$[0].name&color=violet&logo=D)](https://git.zhirov.kz/dlang/readconf)
|
||||
[![githab](https://img.shields.io/github/v/tag/AlexanderZhirov/readconf.svg?sort=semver&style=for-the-badge&color=blue&label=github&logo=D)](https://github.com/AlexanderZhirov/readconf)
|
||||
[![dub](https://img.shields.io/dub/v/readconf.svg?sort=semver&style=for-the-badge&color=orange&logo=D)](https://code.dlang.org/packages/readconf)
|
||||
[![linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)](https://www.linux.org/)
|
||||
|
||||
Singleton for reading the configuration file required for your program.
|
||||
|
||||
## What can do
|
||||
|
||||
1. Separation of parameter and value by separators `=` and `=>`
|
||||
2. Commenting on lines using special characters `;`, `#`, `//`, `/*`
|
||||
3. Support for sections for describing parameter blocks (sections are set by the name in `[]`)
|
||||
4. Support for spaces and tabs for visual separation
|
||||
- Reading multiple configuration files
|
||||
- Separation of parameters by sections
|
||||
- Access to parameters and sections using keys and indexes
|
||||
- Commenting on lines
|
||||
|
||||
You will get more detailed information on the [wiki](https://git.zhirov.kz/dlang/readconf/wiki).
|
||||
|
||||
## Quick start
|
||||
|
||||
|
@ -23,7 +35,7 @@ import std.stdio;
|
|||
|
||||
void main()
|
||||
{
|
||||
rc.read("./settings.conf");
|
||||
rc.read("./tests/settings.conf");
|
||||
|
||||
foreach (key, param; rc.sn.keys())
|
||||
writefln("%s => %s", key, param);
|
||||
|
@ -33,7 +45,7 @@ void main()
|
|||
foreach (key, param; rc.sn("part2").keys())
|
||||
writefln("%s => %s", key, param);
|
||||
|
||||
writeln(rc.sn("part2").key("value1"));
|
||||
writeln(rc["part2"]["value1"]);
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -53,6 +65,20 @@ value3 => good value!
|
|||
this value will be in the new section
|
||||
```
|
||||
|
||||
## Dub
|
||||
## Unittests
|
||||
|
||||
Add a dependency on `"readconf": "~>0.2.0"`
|
||||
The unittests provide [examples](examples/) of configuration files and the `settings.conf` file located in the [tests](tests/):
|
||||
|
||||
```sh
|
||||
Running bin/readconf-test-unittest
|
||||
✓ test __unittest_L4_C1
|
||||
✓ test __unittest_L106_C1
|
||||
✓ test __unittest_L25_C1
|
||||
✓ test __unittest_L51_C1
|
||||
|
||||
Summary: 4 passed, 0 failed in 7 ms
|
||||
```
|
||||
|
||||
## DUB
|
||||
|
||||
Add a dependency on `"readconf": "~>0.3.0"`
|
||||
|
|
2
dub.json
2
dub.json
|
@ -33,6 +33,6 @@
|
|||
],
|
||||
"targetName": "readconf",
|
||||
"dependencies": {
|
||||
"singlog": "~>0.1.0"
|
||||
"singlog": "~>0.2.1"
|
||||
}
|
||||
}
|
|
@ -3,6 +3,6 @@
|
|||
"versions": {
|
||||
"datefmt": "1.0.4",
|
||||
"silly": "1.1.1",
|
||||
"singlog": "0.1.0"
|
||||
"singlog": "0.2.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
This line will be a comment, since it does not match the basic template
|
||||
parameter1 => value1 ; This will be a comment
|
||||
parameter2 => value2 # This will be a comment
|
||||
parameter3 => value3 // This will be a comment
|
||||
parameter4 => value4 /* This will be a comment
|
||||
parameter5 => value5;This will not be a comment
|
||||
parameter6 => value6// This will also be a whole value
|
||||
parameter7 => //value7 ;The value will not be read
|
||||
parameter8 => "//value8" # Now the value is correctly
|
||||
parameter9 => ';value9' // The value is correctly too
|
||||
parameter10 => '"value10"' // Quotes inside
|
|
@ -0,0 +1,22 @@
|
|||
parameter1 = value1
|
||||
parameter_2 = value2
|
||||
|
||||
[first-section] ; Creating the first section
|
||||
parameter1 = value3 ; A section may contain similar parameter names
|
||||
parameter_2 = value4
|
||||
|
||||
[second-section] // Another section
|
||||
parameter1 = value5
|
||||
parameter_2 = value6
|
||||
|
||||
[] /* Addition of the main section
|
||||
parameter3 = value7 /* A new parameter will be added
|
||||
parameter1 = value8 /* And parameter1 will be redefined
|
||||
|
||||
[first-section] # Addition of the first section
|
||||
parameter3 = value9
|
||||
parameter4 = value10
|
||||
|
||||
[_section] # Creating the new section
|
||||
parameter1 = value11
|
||||
parameter2 = value12
|
|
@ -0,0 +1,16 @@
|
|||
parameter1=value1
|
||||
parameter2=>value2
|
||||
parameter3=value3
|
||||
parameter4=>value4
|
||||
|
||||
_parameter5 = value5
|
||||
parameter6 => value6
|
||||
parameter7 = value7
|
||||
|
||||
parameter8 => value8
|
||||
parameter9 =value9
|
||||
parameter-10 =>value10
|
||||
parameter11 = value11
|
||||
|
||||
|
||||
parameter12_ => value12
|
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
|
@ -7,27 +7,32 @@ import std.meta;
|
|||
import singlog;
|
||||
|
||||
/**
|
||||
* Read config object
|
||||
* **Get an object to read the configuration file**
|
||||
*
|
||||
* - The `read()` will allow you to read the configuration file
|
||||
* - `cf()` or `configFile()` will allow you to refer to the read file to get the parameters
|
||||
*/
|
||||
alias rc = Config.file;
|
||||
|
||||
private const string mainSection = "[]";
|
||||
|
||||
class Config
|
||||
{
|
||||
private:
|
||||
enum {
|
||||
GROUP_PROPERTY = 4,
|
||||
GROUP_PARAMETER = 4,
|
||||
GROUP_VALUE_1 = 11, // string
|
||||
GROUP_VALUE_2 = 14, // "strin"
|
||||
GROUP_VALUE_3 = 16, // 'string'
|
||||
GROUP_SECTION_OTHER_OUTER = 17, // "[string]"
|
||||
GROUP_SECTION_OTHER_INNER = 18, // "[string]"
|
||||
GROUP_SECTION_MAIN = 20, // "[]"
|
||||
GROUP_SECTION_OTHER_OUTER = 17, // [string]
|
||||
GROUP_SECTION_OTHER_INNER = 18, // string
|
||||
GROUP_SECTION_MAIN = 20, // []
|
||||
}
|
||||
|
||||
static Config config;
|
||||
string path;
|
||||
bool readed = false;
|
||||
ConfigSection[string] sections;
|
||||
ConfigFile[string] configs;
|
||||
|
||||
const string pattern = "^( |\\t)*(((\\w(\\w|-)+)(( |\\t)*(=>|=){1}"
|
||||
~ "( |\\t)*)(?!\\/(\\/|\\*))(([^ >\"'=\\n\\t#;].*?)|(\"(.+)\")"
|
||||
|
@ -37,61 +42,63 @@ private:
|
|||
/**
|
||||
* Reading the configuration file
|
||||
*/
|
||||
bool readConfig()
|
||||
bool readConfig(const string configName)
|
||||
{
|
||||
File configuration;
|
||||
|
||||
try {
|
||||
configuration = File(this.path, "r");
|
||||
} catch (Exception e) {
|
||||
Log.msg.warning("Unable to open the configuration file " ~ this.path);
|
||||
Log.msg.error(e);
|
||||
log.w("Unable to open the configuration file " ~ this.path);
|
||||
log.e(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (configName !in this.configs)
|
||||
this.configs[configName] = ConfigFile(configName);
|
||||
|
||||
auto regular = regex(this.pattern, "m");
|
||||
|
||||
// reading from the main section
|
||||
string sectionName = "[]";
|
||||
string sectionName = mainSection;
|
||||
|
||||
while (!configuration.eof())
|
||||
{
|
||||
string line = configuration.readln();
|
||||
auto match = matchFirst(line, regular);
|
||||
if (match)
|
||||
|
||||
if (match.length == 0)
|
||||
continue;
|
||||
|
||||
// if again main section
|
||||
if (match[GROUP_SECTION_MAIN].length)
|
||||
{
|
||||
// if again main section
|
||||
if (match[GROUP_SECTION_MAIN].length)
|
||||
{
|
||||
sectionName = match[GROUP_SECTION_MAIN];
|
||||
continue;
|
||||
}
|
||||
if (match[GROUP_SECTION_OTHER_OUTER].length)
|
||||
{
|
||||
sectionName = match[GROUP_SECTION_OTHER_INNER];
|
||||
continue;
|
||||
}
|
||||
|
||||
int group = GROUP_VALUE_1;
|
||||
|
||||
if (match[group][0] == '\"')
|
||||
group = GROUP_VALUE_2;
|
||||
else if (match[group][0] == '\'')
|
||||
group = GROUP_VALUE_3;
|
||||
|
||||
if (sectionName !in this.sections)
|
||||
this.sections[sectionName] = ConfigSection(sectionName);
|
||||
|
||||
this.sections[sectionName].add(ConfigParameter(match[GROUP_PROPERTY], match[group]));
|
||||
sectionName = match[GROUP_SECTION_MAIN];
|
||||
continue;
|
||||
}
|
||||
if (match[GROUP_SECTION_OTHER_OUTER].length)
|
||||
{
|
||||
sectionName = match[GROUP_SECTION_OTHER_INNER];
|
||||
continue;
|
||||
}
|
||||
|
||||
int group = GROUP_VALUE_1;
|
||||
|
||||
if (match[group][0] == '\"')
|
||||
group = GROUP_VALUE_2;
|
||||
else if (match[group][0] == '\'')
|
||||
group = GROUP_VALUE_3;
|
||||
|
||||
this.configs[configName].add(sectionName, ConfigParameter(match[GROUP_PARAMETER], match[group]));
|
||||
}
|
||||
|
||||
try {
|
||||
configuration.close();
|
||||
this.readed = true;
|
||||
} catch (Exception e) {
|
||||
Log.msg.warning("Unable to close the configuration file " ~ this.path);
|
||||
Log.msg.error(e);
|
||||
log.w("Unable to close the configuration file " ~ this.path);
|
||||
log.e(e);
|
||||
this.configs.remove(configName);
|
||||
this.readed = false;
|
||||
}
|
||||
|
||||
|
@ -117,38 +124,123 @@ public:
|
|||
* Read the configuration file
|
||||
* Params:
|
||||
* path = the path to the configuration file
|
||||
* configName = a specific name to bind to the configuration file (default file name)
|
||||
* Returns: `true` if the file was read successfully
|
||||
*/
|
||||
bool read(string path)
|
||||
bool read(string path, string configName = "")
|
||||
{
|
||||
this.path = path;
|
||||
if (!path.exists)
|
||||
throw new Exception("The configuration file does not exist: " ~ path);
|
||||
return readConfig();
|
||||
if (configName.length == 0)
|
||||
configName = path.baseName();
|
||||
if (configName in configs)
|
||||
throw new Exception("The configuration file with this name has already been read");
|
||||
return readConfig(configName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessing the read configuration file
|
||||
* Params:
|
||||
* configName = specific name to bind to the configuration file
|
||||
* (if the read files are > 1, then specify a specific name, otherwise default file name)
|
||||
* Returns: configuration file object ConfigFile
|
||||
*/
|
||||
@property ConfigFile configFile(string configName = "")
|
||||
{
|
||||
if (configName.length == 0)
|
||||
{
|
||||
if (configs.length == 1)
|
||||
return configs[configs.byKey.front];
|
||||
else
|
||||
throw new Exception("You must explicitly specify the name of the configuration file");
|
||||
}
|
||||
|
||||
return configName in configs ? configs[configName] : ConfigFile(configName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read configuration file
|
||||
* Params:
|
||||
* configName = specific name to bind to the configuration file
|
||||
* (if the read files are > 1, then specify a specific name, otherwise default file name)
|
||||
* Returns: configuration file object ConfigFile
|
||||
*/
|
||||
alias cf = configFile;
|
||||
|
||||
@property ConfigFile opIndex(string configName = "")
|
||||
{
|
||||
if (configName.length == 0)
|
||||
{
|
||||
if (configs.length == 1)
|
||||
return configs[configs.byKey.front];
|
||||
else
|
||||
throw new Exception("More than one configuration file has been read. "
|
||||
~ "It is necessary to specify the name of a specific");
|
||||
}
|
||||
|
||||
return configName in configs ? configs[configName] : ConfigFile(configName);
|
||||
}
|
||||
}
|
||||
|
||||
struct ConfigFile
|
||||
{
|
||||
private string name;
|
||||
private ConfigSection[string] sections;
|
||||
|
||||
@property bool exist()
|
||||
{
|
||||
return this.sections.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the section
|
||||
* Params:
|
||||
* section = section name (default main "[]")
|
||||
* section = section name (default main section)
|
||||
* Returns: the object of the configuration file section ConfigSection
|
||||
*/
|
||||
@property ConfigSection sectionName(string section = "[]")
|
||||
@property ConfigSection sectionName(string section = mainSection)
|
||||
{
|
||||
return section in sections ? sections[section] : ConfigSection();
|
||||
if (!this.exist)
|
||||
throw new Exception("The configuration file does not exist");
|
||||
if (section == mainSection && sections.length == 1)
|
||||
return sections[sections.byKey.front];
|
||||
if (section.length == 0)
|
||||
section = mainSection;
|
||||
return section in sections ? sections[section] : ConfigSection(section);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section name
|
||||
*
|
||||
* Get the section
|
||||
* Params:
|
||||
* section = section name (default main "[]")
|
||||
* section = section name (default main section)
|
||||
* Returns: the object of the configuration file section ConfigSection
|
||||
*/
|
||||
alias sn = sectionName;
|
||||
|
||||
private void add(string sectionName, ConfigParameter parameter)
|
||||
{
|
||||
if (sectionName !in this.sections)
|
||||
this.sections[sectionName] = ConfigSection(sectionName);
|
||||
|
||||
this.sections[sectionName].add(parameter);
|
||||
}
|
||||
|
||||
@property ConfigSection opIndex(string section = mainSection)
|
||||
{
|
||||
if (!this.exist)
|
||||
throw new Exception("The configuration file does not exist");
|
||||
if (section == mainSection && sections.length == 1)
|
||||
return sections[sections.byKey.front];
|
||||
if (section.length == 0)
|
||||
section = mainSection;
|
||||
return section in sections ? sections[section] : ConfigSection(section);
|
||||
}
|
||||
}
|
||||
|
||||
struct ConfigSection
|
||||
{
|
||||
private string name = "[]";
|
||||
private string name = mainSection;
|
||||
private ConfigParameter[string] parameters;
|
||||
|
||||
/**
|
||||
|
@ -164,16 +256,20 @@ struct ConfigSection
|
|||
* Get the parameter value
|
||||
* Params:
|
||||
* key = parameter from the configuration file
|
||||
* Returns: the value of the parameter in the PP structure view
|
||||
* Returns: the object of the parameter ConfigParameter
|
||||
*/
|
||||
ConfigParameter key(string key)
|
||||
{
|
||||
return key in this.parameters ? this.parameters[key] : ConfigParameter();
|
||||
if (key.length == 0)
|
||||
throw new Exception("The key cannot be empty");
|
||||
if (this.empty)
|
||||
throw new Exception("The selected section has no parameters or does not exist");
|
||||
return key in this.parameters ? this.parameters[key] : ConfigParameter(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all keys and their values
|
||||
* Returns: collection of properties structures PP
|
||||
* Returns: collection of parameters
|
||||
*/
|
||||
ConfigParameter[string] keys()
|
||||
{
|
||||
|
@ -183,14 +279,20 @@ struct ConfigSection
|
|||
private void add(ConfigParameter parameter)
|
||||
{
|
||||
if (parameter.property in parameters)
|
||||
Log.msg.warning("The parameter exists but will be overwritten");
|
||||
log.w("The parameter exists but will be overwritten");
|
||||
this.parameters[parameter.property] = parameter;
|
||||
}
|
||||
|
||||
ConfigParameter opIndex(string key)
|
||||
{
|
||||
if (key.length == 0)
|
||||
throw new Exception("The key cannot be empty");
|
||||
if (this.empty)
|
||||
throw new Exception("The selected section has no parameters or does not exist");
|
||||
return key in this.parameters ? this.parameters[key] : ConfigParameter(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameter and its value with the ability to convert to the desired data type
|
||||
*/
|
||||
struct ConfigParameter
|
||||
{
|
||||
private string property;
|
||||
|
@ -202,7 +304,7 @@ struct ConfigParameter
|
|||
*/
|
||||
@property bool empty()
|
||||
{
|
||||
return this.property.length == 0 || this.value.length == 0;
|
||||
return this.value.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,8 +323,8 @@ struct ConfigParameter
|
|||
try {
|
||||
return this.value.to!T;
|
||||
} catch (Exception e) {
|
||||
Log.msg.warning("Cannot convert type");
|
||||
Log.msg.error(e);
|
||||
log.w("Cannot convert type");
|
||||
log.e(e);
|
||||
return T.init;
|
||||
}
|
||||
}
|
||||
|
|
141
tests/test.d
141
tests/test.d
|
@ -1,34 +1,121 @@
|
|||
import readconf;
|
||||
import std.conv;
|
||||
|
||||
unittest
|
||||
{
|
||||
rc.read("./examples/simple.conf");
|
||||
|
||||
auto configFile = rc.cf;
|
||||
auto mainSection = configFile.sn;
|
||||
|
||||
assert(mainSection.key("parameter1") == "value1");
|
||||
assert(mainSection["parameter2"] == "value2");
|
||||
assert(mainSection.key("parameter3") == "value3");
|
||||
assert(mainSection["parameter4"] == "value4");
|
||||
assert(mainSection.key("_parameter5") == "value5");
|
||||
assert(mainSection["parameter6"] == "value6");
|
||||
assert(mainSection.key("parameter7") == "value7");
|
||||
assert(mainSection["parameter8"] == "value8");
|
||||
assert(mainSection.key("parameter9") == "value9");
|
||||
assert(mainSection["parameter-10"] == "value10");
|
||||
assert(mainSection.key("parameter11") == "value11");
|
||||
assert(mainSection["parameter12_"] == "value12");
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
rc.read("./examples/sections.conf");
|
||||
auto configFile = rc.cf;
|
||||
|
||||
auto mainSection = configFile.sn;
|
||||
auto firstSection = configFile.sn("first-section");
|
||||
auto secondSection = configFile["second-section"];
|
||||
auto section = configFile["_section"];
|
||||
|
||||
assert(mainSection.key("parameter1") == "value8");
|
||||
assert(mainSection["parameter_2"] == "value2");
|
||||
assert(mainSection["parameter3"] == "value7");
|
||||
|
||||
assert(firstSection["parameter1"] == "value3");
|
||||
assert(firstSection["parameter_2"] == "value4");
|
||||
assert(firstSection["parameter3"] == "value9");
|
||||
assert(firstSection["parameter4"] == "value10");
|
||||
|
||||
assert(secondSection["parameter1"] == "value5");
|
||||
assert(secondSection["parameter_2"] == "value6");
|
||||
|
||||
assert(section["parameter1"] == "value11");
|
||||
assert(section["parameter2"] == "value12");
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
rc.read("./examples/simple.conf", "simple");
|
||||
rc.read("./examples/sections.conf");
|
||||
rc.read("./examples/comments.conf", "comments");
|
||||
|
||||
auto simpleConfig = rc.cf("simple");
|
||||
auto sectionsConfig = rc["sections.conf"];
|
||||
auto commentsConfig = rc["comments"];
|
||||
|
||||
auto simConMaiSec = simpleConfig.sn;
|
||||
|
||||
assert(simConMaiSec.key("parameter1") == "value1");
|
||||
assert(simConMaiSec["parameter2"] == "value2");
|
||||
assert(simConMaiSec.key("parameter3") == "value3");
|
||||
assert(simConMaiSec["parameter4"] == "value4");
|
||||
assert(simConMaiSec.key("_parameter5") == "value5");
|
||||
assert(simConMaiSec["parameter6"] == "value6");
|
||||
assert(simConMaiSec.key("parameter7") == "value7");
|
||||
assert(simConMaiSec["parameter8"] == "value8");
|
||||
assert(simConMaiSec.key("parameter9") == "value9");
|
||||
assert(simConMaiSec["parameter-10"] == "value10");
|
||||
assert(simConMaiSec.key("parameter11") == "value11");
|
||||
assert(simConMaiSec["parameter12_"] == "value12");
|
||||
|
||||
auto secConMaiSec = sectionsConfig.sn;
|
||||
auto secConFirSec = sectionsConfig.sn("first-section");
|
||||
auto secConSecSec = sectionsConfig["second-section"];
|
||||
auto secConSec = sectionsConfig["_section"];
|
||||
|
||||
assert(secConMaiSec.key("parameter1") == "value8");
|
||||
assert(secConMaiSec["parameter_2"] == "value2");
|
||||
assert(secConMaiSec["parameter3"] == "value7");
|
||||
assert(secConFirSec["parameter1"] == "value3");
|
||||
assert(secConFirSec["parameter_2"] == "value4");
|
||||
assert(secConFirSec["parameter3"] == "value9");
|
||||
assert(secConFirSec["parameter4"] == "value10");
|
||||
assert(secConSecSec["parameter1"] == "value5");
|
||||
assert(secConSecSec["parameter_2"] == "value6");
|
||||
assert(secConSec["parameter1"] == "value11");
|
||||
assert(secConSec["parameter2"] == "value12");
|
||||
|
||||
auto comConMaiSec = commentsConfig.sn;
|
||||
|
||||
assert(comConMaiSec["parameter1"] == "value1");
|
||||
assert(comConMaiSec["parameter2"] == "value2");
|
||||
assert(comConMaiSec["parameter3"] == "value3");
|
||||
assert(comConMaiSec["parameter4"] == "value4");
|
||||
assert(comConMaiSec["parameter5"] == "value5;This will not be a comment");
|
||||
assert(comConMaiSec["parameter6"] == "value6// This will also be a whole value");
|
||||
assert(comConMaiSec["parameter8"] == "//value8");
|
||||
assert(comConMaiSec["parameter9"] == ";value9");
|
||||
assert(comConMaiSec["parameter10"] == "\"value10\"");
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
rc.read("./tests/settings.conf");
|
||||
|
||||
assert(rc.sn.key("value1") == "text without quotes");
|
||||
assert(rc.sn.key("value2") == "Yes!");
|
||||
assert(rc.sn.key("value3") == "value in apostrophes");
|
||||
assert(rc.sn.key("value4") == "1000");
|
||||
assert(rc.sn.key("value5") == "0.000");
|
||||
assert(rc.sn.key("value7") == "//path");
|
||||
assert(rc.sn.key("value8") == "\"Hey!\"");
|
||||
assert(rc.sn("part2").key("value1") == "this value will be in the new section");
|
||||
assert(rc.sn("part2").key("value3") == "good value!");
|
||||
assert(rc.sn("part3").key("value1") == "-2");
|
||||
assert(rc.sn("part3").key("value3") == "100");
|
||||
assert(rc.cf.sn.key("value1") == "text without quotes");
|
||||
assert(rc[][]["value2"] == "Yes!");
|
||||
assert(rc.cf.sn.key("value3") == "value in apostrophes");
|
||||
assert(rc[][]["value4"] == "1000");
|
||||
assert(rc.cf.sn["value5"] == "0.000");
|
||||
assert(rc[][].key("value7") == "//path");
|
||||
assert(rc.cf.sn.key("value8") == "\"Hey!\"");
|
||||
assert(rc[]["part2"]["value1"] == "this value will be in the new section");
|
||||
assert(rc.cf.sn("part2").key("value3") == "good value!");
|
||||
assert(rc[].sn("part3").key("value1") == "-2");
|
||||
assert(rc.cf["part3"]["value3"] == "100");
|
||||
}
|
||||
|
||||
// void main()
|
||||
// {
|
||||
// import std.stdio;
|
||||
// rc.read("./tests/settings.conf");
|
||||
|
||||
// foreach (key, param; rc.sn.keys())
|
||||
// writefln("%s => %s", key, param);
|
||||
|
||||
// writeln(rc.sn.key("value1"));
|
||||
|
||||
// foreach (key, param; rc.sn("part2").keys())
|
||||
// writefln("%s => %s", key, param);
|
||||
|
||||
// writeln(rc.sn("part2").key("value1"));
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue