lib45d
45Drives C++ Library Development Documentation
Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Friends | List of all members
ffd::ConfigParser Class Reference

Main configuration parser class to inherit from in your code. More...

#include <45d/config/ConfigParser.hpp>

Public Member Functions

 ConfigParser (std::string path)
 Construct a new Config Parser object. More...
 
std::string dump_str (void) const
 Dump config to stdout as a string. More...
 
template<class T >
get (const std::string &key) const
 Get value from config map using ffd::get(). This can throw. Use this in a try...catch block. More...
 
template<class T >
get (const std::string &key, const T &fallback) const noexcept
 Try to get value from config, default to fallback if fails. Guaranteed no-throw. More...
 
template<class T >
get (const std::string &key, bool *fail_flag) const noexcept
 Try to get value from config. If ffd::get fails, return T() or 0 and set fail_flag. Guaranteed no-throw. Prints message to std::cerr to explain error. More...
 
template<class T >
get_from (const std::string &section, const std::string &key)
 Adapter for ffd::get(). Sets config_map_ptr_ to address of sub config with name section. This can throw. More...
 
template<class T >
get_from (const std::string &section, const std::string &key, const T &fallback) noexcept
 Get value from config subsection using ConfigParser::get(const std::string&,const T&) const noexcept, return fallback if the subsection DNE. More...
 
template<class T >
get_from (const std::string &section, const std::string &key, bool *fail_flag) noexcept
 Get value from config subsection using ConfigParser::get(const std::string&,bool*) const noexcept, set fail_flag if the subsection DNE. More...
 
Quota get_quota (const std::string &key, const Bytes &max) const
 Get quota from config map using ffd::get(). This can throw. Use this in a try...catch block. More...
 
Quota get_quota (const std::string &key, const Bytes &max, const Quota &fallback) const noexcept
 Try to get Quota from config, default to fallback if fails. Guaranteed no-throw. More...
 
Quota get_quota (const std::string &key, const Bytes &max, bool *fail_flag) const noexcept
 Try to get Quota from config. If ffd::get fails, return Quota(void) and set fail_flag. Guaranteed no-throw. Prints message to std::cerr to explain error. More...
 
Quota get_quota_from (const std::string &section, const std::string &key, const Bytes &max)
 Adapter for ffd::get(). Sets config_map_ptr_ to address of sub config with name section. This can throw. More...
 
Quota get_quota_from (const std::string &section, const std::string &key, const Bytes &max, const Quota &fallback) noexcept
 Get value from config subsection using ConfigParser::get(const std::string&,const T&) const noexcept, return fallback if the subsection DNE. More...
 
Quota get_quota_from (const std::string &section, const std::string &key, const Bytes &max, bool *fail_flag) noexcept
 Get value from config subsection using ConfigParser::get(const std::string&,bool*) const noexcept, set fail_flag if the subsection DNE. More...
 

Protected Attributes

std::vector< ConfigNode * > sub_confs_
 Vector of config subsections.
 
std::string current_section_
 Name of current section, set by set_subsection()
 

Private Member Functions

void parse (std::ifstream &file)
 Iterate each line of config file and determine how to parse with l::check_record_type() More...
 
void parse_entry (const std::string &line)
 Extract value from config line and insert ConfigNode into config_map_. More...
 
void parse_heading (const std::string &line)
 Create new subconfig. More...
 
void set_subsection (const std::string &section)
 Update config_map_ptr_ to the subconfig map for section. More...
 
void reset_subsection (void) noexcept
 Set config_map_ptr_ back to the address of config_map_. More...
 
void report_error (const std::string &message) const noexcept
 Print error message to stderr, conditionally prepended with current subsection name. More...
 

Private Attributes

bool guarded_
 true if a ConfigSubsectionGuard is in scope Set in ConfigSubsectionGuard::ConfigSubsectionGuard() Cleared in ConfigSubsectionGuard::~ConfigSubsectionGuard()
 
std::unordered_map< std::string, ConfigNode > * config_map_ptr_
 Pointer to current config map.
 
std::string path_
 Path to config file.
 
std::unordered_map< std::string, ConfigNodeconfig_map_
 Map of config keys (std::string) to values (ConfigNode)
 

Friends

class ConfigSubsectionGuard
 Guard to change config subsection within a scope: ConfigSubsectionGuard.
 

Detailed Description

Main configuration parser class to inherit from in your code.

Example usage:

#include <45d/config/ConfigParser.hpp>
#include <cassert>
#include <iostream>
class ConfigFailFlag : public ffd::ConfigParser {
bool parse_failed_ = false;
public:
bool bool_test_ = get<bool>("Bool Test", &parse_failed_);
int integer_test_ = get<int>("Integer Test", &parse_failed_);
unsigned unsigned_test_ = get<unsigned>("Unsigned Test", &parse_failed_);
float float_test_ = get<float>("Float Test", &parse_failed_);
double double_test_ = get<double>("Double Test", &parse_failed_);
std::string string_test_ = get<std::string>("String Test", &parse_failed_);
ConfigFailFlag(std::string path) : ffd::ConfigParser(path) {
if (parse_failed_)
"################ Config Fail Flag ################\nOne or more options missing from configuration.");
}
void dump(void) {
std::cout << "Bool Test: " << std::boolalpha << bool_test_ << std::endl;
std::cout << "Integer Test: " << integer_test_ << std::endl;
std::cout << "Unsigned Test: " << unsigned_test_ << std::endl;
std::cout << "Float Test: " << float_test_ << std::endl;
std::cout << "Double Test: " << double_test_ << std::endl;
std::cout << "String Test: " << string_test_ << std::endl;
}
bool ok(void) {
return !parse_failed_;
}
};
int main(int argc, char *argv[]) {
assert(argc == 2);
{
try {
ConfigFailFlag config(argv[1]);
config.dump();
} catch (const ffd::MissingOptionException &err) {
std::cerr << err.what() << std::endl;
}
}
return 0;
}

Constructor & Destructor Documentation

◆ ConfigParser()

ffd::ConfigParser::ConfigParser ( std::string  path)

Construct a new Config Parser object.

Opens file at path as an std::ifstream and calls ConfigParser::parse()

Parameters
pathPath to config file

Member Function Documentation

◆ dump_str()

std::string ffd::ConfigParser::dump_str ( void  ) const

Dump config to stdout as a string.

Returns
std::string String containing config_map_ contents

◆ get() [1/3]

template<class T >
T ffd::ConfigParser::get ( const std::string &  key) const
inline

Get value from config map using ffd::get(). This can throw. Use this in a try...catch block.

try {
int integer = get<int>("Field");
} catch (const ffd::ConfigException &err) {
std::cerr << err.what();
}
Template Parameters
TType of variable to get
Parameters
keyKey to index config_map_
Returns
T Value returned from config

◆ get() [2/3]

template<class T >
T ffd::ConfigParser::get ( const std::string &  key,
bool *  fail_flag 
) const
inlinenoexcept

Try to get value from config. If ffd::get fails, return T() or 0 and set fail_flag. Guaranteed no-throw. Prints message to std::cerr to explain error.

Example:

#include <45d/config/ConfigParser.hpp>
#include <cassert>
#include <iostream>
class ConfigFailFlag : public ffd::ConfigParser {
bool parse_failed_ = false;
public:
bool bool_test_ = get<bool>("Bool Test", &parse_failed_);
int integer_test_ = get<int>("Integer Test", &parse_failed_);
unsigned unsigned_test_ = get<unsigned>("Unsigned Test", &parse_failed_);
float float_test_ = get<float>("Float Test", &parse_failed_);
double double_test_ = get<double>("Double Test", &parse_failed_);
std::string string_test_ = get<std::string>("String Test", &parse_failed_);
ConfigFailFlag(std::string path) : ffd::ConfigParser(path) {
if (parse_failed_)
"################ Config Fail Flag ################\nOne or more options missing from configuration.");
}
void dump(void) {
std::cout << "Bool Test: " << std::boolalpha << bool_test_ << std::endl;
std::cout << "Integer Test: " << integer_test_ << std::endl;
std::cout << "Unsigned Test: " << unsigned_test_ << std::endl;
std::cout << "Float Test: " << float_test_ << std::endl;
std::cout << "Double Test: " << double_test_ << std::endl;
std::cout << "String Test: " << string_test_ << std::endl;
}
bool ok(void) {
return !parse_failed_;
}
};
int main(int argc, char *argv[]) {
assert(argc == 2);
{
try {
ConfigFailFlag config(argv[1]);
config.dump();
} catch (const ffd::MissingOptionException &err) {
std::cerr << err.what() << std::endl;
}
}
return 0;
}
Template Parameters
TType of variable to return
Parameters
keyKey to index config_map_
fail_flagPointer to flag to set if ffd::get() fails
Returns
T Value returned from config

◆ get() [3/3]

template<class T >
T ffd::ConfigParser::get ( const std::string &  key,
const T &  fallback 
) const
inlinenoexcept

Try to get value from config, default to fallback if fails. Guaranteed no-throw.

Example:

#include <45d/config/ConfigParser.hpp>
#include <cassert>
#include <iostream>
class ConfigFallback : public ffd::ConfigParser {
public:
int integer_test_ = get<int>("Integer Test", -1);
unsigned unsigned_test_ = get<unsigned>("Unsigned Test", (unsigned)-1);
float float_test_ = get<float>("Float Test", -1.0);
double double_test_ = get<double>("Double Test", -1.0);
std::string string_test_ = get<std::string>("String Test", "fallback");
ConfigFallback(std::string path) : ffd::ConfigParser(path) {}
void dump(void) {
std::cout << "Integer Test: " << integer_test_ << std::endl;
std::cout << "Unsigned Test: " << unsigned_test_ << std::endl;
std::cout << "Float Test: " << float_test_ << std::endl;
std::cout << "Double Test: " << double_test_ << std::endl;
std::cout << "String Test: " << string_test_ << std::endl;
}
};
int main(int argc, char *argv[]) {
assert(argc == 2);
{
ConfigFallback config(argv[1]);
config.dump();
}
return 0;
}
Template Parameters
TType of variable to return
Parameters
keyKey to index config_map_
fallbackDefault value to return if ffd::get() fails.
Returns
T Value returned from config

◆ get_from() [1/3]

template<class T >
T ffd::ConfigParser::get_from ( const std::string &  section,
const std::string &  key 
)
inline

Adapter for ffd::get(). Sets config_map_ptr_ to address of sub config with name section. This can throw.

Template Parameters
TType of variable to get
Parameters
sectionSubsection heading from config
keyKey to index config_map_
Returns
T Value returned from config

◆ get_from() [2/3]

template<class T >
T ffd::ConfigParser::get_from ( const std::string &  section,
const std::string &  key,
bool *  fail_flag 
)
inlinenoexcept

Get value from config subsection using ConfigParser::get(const std::string&,bool*) const noexcept, set fail_flag if the subsection DNE.

Template Parameters
TType to return
Parameters
sectionConfig section name to get value from
keyKey identifying value in config
fail_flagPointer to flag to be set if error or DNE
Returns
T Value returned from config or T() or 0

◆ get_from() [3/3]

template<class T >
T ffd::ConfigParser::get_from ( const std::string &  section,
const std::string &  key,
const T &  fallback 
)
inlinenoexcept

Get value from config subsection using ConfigParser::get(const std::string&,const T&) const noexcept, return fallback if the subsection DNE.

Example:

#include <45d/config/ConfigParser.hpp>
#include <cassert>
#include <iostream>
class ConfigSubSections : public ffd::ConfigParser {
private:
bool parse_failed_ = false;
public:
bool global_bool_test_ = get<bool>("Bool Test", &parse_failed_);
int global_integer_test_ = get<int>("Integer Test", &parse_failed_);
unsigned global_unsigned_test_ = get<unsigned>("Unsigned Test", &parse_failed_);
float global_float_test_ = get<float>("Float Test", &parse_failed_);
double global_double_test_ = get<double>("Double Test", &parse_failed_);
std::string global_string_test_ = get<std::string>("String Test", &parse_failed_);
bool section1_bool_test_ = get_from<bool>("Section 1", "Bool Test", &parse_failed_);
int section1_integer_test_ = get_from<int>("Section 1", "Integer Test", &parse_failed_);
unsigned section1_unsigned_test_ =
get_from<unsigned>("Section 1", "Unsigned Test", &parse_failed_);
float section1_float_test_ = get_from<float>("Section 1", "Float Test", &parse_failed_);
double section1_double_test_ = get_from<double>("Section 1", "Double Test", &parse_failed_);
std::string section1_string_test_ =
get_from<std::string>("Section 1", "String Test", &parse_failed_);
bool section2_bool_test_ = get_from<bool>("Section 2", "Bool Test", &parse_failed_);
int section2_integer_test_ = get_from<int>("Section 2", "Integer Test", &parse_failed_);
unsigned section2_unsigned_test_ =
get_from<unsigned>("Section 2", "Unsigned Test", &parse_failed_);
float section2_float_test_ = get_from<float>("Section 2", "Float Test", &parse_failed_);
double section2_double_test_ = get_from<double>("Section 2", "Double Test", &parse_failed_);
std::string section2_string_test_ =
get_from<std::string>("Section 2", "String Test", &parse_failed_);
ConfigSubSections(std::string path) : ffd::ConfigParser(path) {}
void dump(void) {
std::cout << "Global Bool Test: " << std::boolalpha << global_bool_test_ << std::endl;
std::cout << "Global Integer Test: " << global_integer_test_ << std::endl;
std::cout << "Global Unsigned Test: " << global_unsigned_test_ << std::endl;
std::cout << "Global Float Test: " << global_float_test_ << std::endl;
std::cout << "Global Double Test: " << global_double_test_ << std::endl;
std::cout << "Global String Test: " << global_string_test_ << std::endl;
std::cout << "Section 1 Bool Test: " << std::boolalpha << section1_bool_test_ << std::endl;
std::cout << "Section 1 Integer Test: " << section1_integer_test_ << std::endl;
std::cout << "Section 1 Unsigned Test: " << section1_unsigned_test_ << std::endl;
std::cout << "Section 1 Float Test: " << section1_float_test_ << std::endl;
std::cout << "Section 1 Double Test: " << section1_double_test_ << std::endl;
std::cout << "Section 1 String Test: " << section1_string_test_ << std::endl;
std::cout << "Section 2 Bool Test: " << std::boolalpha << section2_bool_test_ << std::endl;
std::cout << "Section 2 Integer Test: " << section2_integer_test_ << std::endl;
std::cout << "Section 2 Unsigned Test: " << section2_unsigned_test_ << std::endl;
std::cout << "Section 2 Float Test: " << section2_float_test_ << std::endl;
std::cout << "Section 2 Double Test: " << section2_double_test_ << std::endl;
std::cout << "Section 2 String Test: " << section2_string_test_ << std::endl;
}
};
int main(int argc, char *argv[]) {
assert(argc == 2);
ConfigSubSections config(argv[1]);
config.dump();
return 0;
}
Template Parameters
TType to return
Parameters
sectionConfig section name to get value from
keyKey identifying value in config
fallbackReturned if error or DNE
Returns
T Value returned from config or fallback

◆ get_quota() [1/3]

Quota ffd::ConfigParser::get_quota ( const std::string &  key,
const Bytes max 
) const
inline

Get quota from config map using ffd::get(). This can throw. Use this in a try...catch block.

ffd::Bytes total(1024);
try {
ffd::Quota quota = get("Quota", total);
} catch (const ffd::ConfigException &err) {
std::cerr << err.what();
}
Parameters
keyKey to index config_map_
maxMaximum number of bytes
Returns
ffd::Quota Value returned from config

◆ get_quota() [2/3]

Quota ffd::ConfigParser::get_quota ( const std::string &  key,
const Bytes max,
bool *  fail_flag 
) const
inlinenoexcept

Try to get Quota from config. If ffd::get fails, return Quota(void) and set fail_flag. Guaranteed no-throw. Prints message to std::cerr to explain error.

Parameters
keyKey to index config_map_
maxMaximum number of bytes
fail_flagPointer to flag to set if ffd::get() fails
Returns
T Value returned from config

◆ get_quota() [3/3]

Quota ffd::ConfigParser::get_quota ( const std::string &  key,
const Bytes max,
const Quota fallback 
) const
inlinenoexcept

Try to get Quota from config, default to fallback if fails. Guaranteed no-throw.

Parameters
keyKey to index config_map_
maxMaximum number of bytes
fallbackDefault value to return if ffd::get() fails.
Returns
T Value returned from config

◆ get_quota_from() [1/3]

Quota ffd::ConfigParser::get_quota_from ( const std::string &  section,
const std::string &  key,
const Bytes max 
)
inline

Adapter for ffd::get(). Sets config_map_ptr_ to address of sub config with name section. This can throw.

Parameters
sectionSubsection heading from config
keyKey to index config_map_
maxMaximum number of bytes
Returns
Quota Value returned from config

◆ get_quota_from() [2/3]

Quota ffd::ConfigParser::get_quota_from ( const std::string &  section,
const std::string &  key,
const Bytes max,
bool *  fail_flag 
)
inlinenoexcept

Get value from config subsection using ConfigParser::get(const std::string&,bool*) const noexcept, set fail_flag if the subsection DNE.

Parameters
sectionConfig section name to get value from
keyKey identifying value in config
maxMaximum number of bytes
fail_flagPointer to flag to be set if error or DNE
Returns
Quota Value returned from config or T() or 0

◆ get_quota_from() [3/3]

Quota ffd::ConfigParser::get_quota_from ( const std::string &  section,
const std::string &  key,
const Bytes max,
const Quota fallback 
)
inlinenoexcept

Get value from config subsection using ConfigParser::get(const std::string&,const T&) const noexcept, return fallback if the subsection DNE.

Example:

#include <45d/config/ConfigParser.hpp>
#include <cassert>
#include <iostream>
class ConfigSubSections : public ffd::ConfigParser {
private:
bool parse_failed_ = false;
public:
bool global_bool_test_ = get<bool>("Bool Test", &parse_failed_);
int global_integer_test_ = get<int>("Integer Test", &parse_failed_);
unsigned global_unsigned_test_ = get<unsigned>("Unsigned Test", &parse_failed_);
float global_float_test_ = get<float>("Float Test", &parse_failed_);
double global_double_test_ = get<double>("Double Test", &parse_failed_);
std::string global_string_test_ = get<std::string>("String Test", &parse_failed_);
bool section1_bool_test_ = get_from<bool>("Section 1", "Bool Test", &parse_failed_);
int section1_integer_test_ = get_from<int>("Section 1", "Integer Test", &parse_failed_);
unsigned section1_unsigned_test_ =
get_from<unsigned>("Section 1", "Unsigned Test", &parse_failed_);
float section1_float_test_ = get_from<float>("Section 1", "Float Test", &parse_failed_);
double section1_double_test_ = get_from<double>("Section 1", "Double Test", &parse_failed_);
std::string section1_string_test_ =
get_from<std::string>("Section 1", "String Test", &parse_failed_);
bool section2_bool_test_ = get_from<bool>("Section 2", "Bool Test", &parse_failed_);
int section2_integer_test_ = get_from<int>("Section 2", "Integer Test", &parse_failed_);
unsigned section2_unsigned_test_ =
get_from<unsigned>("Section 2", "Unsigned Test", &parse_failed_);
float section2_float_test_ = get_from<float>("Section 2", "Float Test", &parse_failed_);
double section2_double_test_ = get_from<double>("Section 2", "Double Test", &parse_failed_);
std::string section2_string_test_ =
get_from<std::string>("Section 2", "String Test", &parse_failed_);
ConfigSubSections(std::string path) : ffd::ConfigParser(path) {}
void dump(void) {
std::cout << "Global Bool Test: " << std::boolalpha << global_bool_test_ << std::endl;
std::cout << "Global Integer Test: " << global_integer_test_ << std::endl;
std::cout << "Global Unsigned Test: " << global_unsigned_test_ << std::endl;
std::cout << "Global Float Test: " << global_float_test_ << std::endl;
std::cout << "Global Double Test: " << global_double_test_ << std::endl;
std::cout << "Global String Test: " << global_string_test_ << std::endl;
std::cout << "Section 1 Bool Test: " << std::boolalpha << section1_bool_test_ << std::endl;
std::cout << "Section 1 Integer Test: " << section1_integer_test_ << std::endl;
std::cout << "Section 1 Unsigned Test: " << section1_unsigned_test_ << std::endl;
std::cout << "Section 1 Float Test: " << section1_float_test_ << std::endl;
std::cout << "Section 1 Double Test: " << section1_double_test_ << std::endl;
std::cout << "Section 1 String Test: " << section1_string_test_ << std::endl;
std::cout << "Section 2 Bool Test: " << std::boolalpha << section2_bool_test_ << std::endl;
std::cout << "Section 2 Integer Test: " << section2_integer_test_ << std::endl;
std::cout << "Section 2 Unsigned Test: " << section2_unsigned_test_ << std::endl;
std::cout << "Section 2 Float Test: " << section2_float_test_ << std::endl;
std::cout << "Section 2 Double Test: " << section2_double_test_ << std::endl;
std::cout << "Section 2 String Test: " << section2_string_test_ << std::endl;
}
};
int main(int argc, char *argv[]) {
assert(argc == 2);
ConfigSubSections config(argv[1]);
config.dump();
return 0;
}
Parameters
sectionConfig section name to get value from
keyKey identifying value in config
maxMaximum number of bytes
fallbackReturned if error or DNE
Returns
Quota Value returned from config or fallback

◆ parse()

void ffd::ConfigParser::parse ( std::ifstream &  file)
private

Iterate each line of config file and determine how to parse with l::check_record_type()

Case Function Called
l::RecordType::UNK prints error message and continues
l::RecordType::ENTRY ConfigParser::parse_entry()
l::RecordType::HEADING ConfigParser::parse_heading()
l::RecordType::EMPTY continues
Parameters
fileOpened file stream for config file

◆ parse_entry()

void ffd::ConfigParser::parse_entry ( const std::string &  line)
private

Extract value from config line and insert ConfigNode into config_map_.

Parameters
lineString containing some form of "key = value"

◆ parse_heading()

void ffd::ConfigParser::parse_heading ( const std::string &  line)
private

Create new subconfig.

construct new ConfigNode containing name and new config map, assign config_map_ptr_ to address of new config map, place into global config_map_, push address of new ConfigNode into sub_confs_

Parameters
lineString containing some form of "[Section Name]"

◆ report_error()

void ffd::ConfigParser::report_error ( const std::string &  message) const
inlineprivatenoexcept

Print error message to stderr, conditionally prepended with current subsection name.

Parameters
message

◆ reset_subsection()

void ffd::ConfigParser::reset_subsection ( void  )
inlineprivatenoexcept

Set config_map_ptr_ back to the address of config_map_.

◆ set_subsection()

void ffd::ConfigParser::set_subsection ( const std::string &  section)
inlineprivate

Update config_map_ptr_ to the subconfig map for section.

Parameters
sectionThe config section to set to

The documentation for this class was generated from the following files:
ffd::ConfigParser::ConfigParser
ConfigParser(std::string path)
Construct a new Config Parser object.
Definition: config_parser.cpp:25
ffd::Bytes
Use this class for byte-formatted values. e.g.: "123 KiB".
Definition: Bytes.hpp:32
ffd::Quota
This class extends ffd::Bytes to specify percents of an amount of bytes.
Definition: Quota.hpp:30
ffd::ConfigParser::get
T get(const std::string &key) const
Get value from config map using ffd::get(). This can throw. Use this in a try...catch block.
Definition: ConfigParser.hpp:105
ffd
45Drives namespace
Definition: Bytes.hpp:27
ffd::MissingOptionException
Throw this exception when a config entry is missing.
Definition: Exceptions.hpp:48
ffd::Exception::what
const char * what(void) const noexcept
Return string containing explanation message.
Definition: Exceptions.hpp:44
ffd::ConfigException
General exception for all Config* related issues.
Definition: Exceptions.hpp:30
ffd::ConfigParser
Main configuration parser class to inherit from in your code.
Definition: ConfigParser.hpp:68