// Copyright (C) 2003 Davis E. King ([email protected]) | |
// License: Boost Software License See LICENSE.txt for the full license. | |
namespace dlib | |
{ | |
class config_reader | |
{ | |
/*! | |
INITIAL VALUE | |
- there aren't any keys defined for this object | |
- there aren't any blocks defined for this object | |
POINTERS AND REFERENCES TO INTERNAL DATA | |
The destructor, clear(), and load_from() invalidate pointers | |
and references to internal data. All other functions are guaranteed | |
to NOT invalidate pointers or references to internal data. | |
WHAT THIS OBJECT REPRESENTS | |
This object represents something which is intended to be used to read | |
text configuration files that are defined by the following EBNF (with | |
config_file as the starting symbol): | |
config_file = block; | |
block = { key_value_pair | sub_block }; | |
key_value_pair = key_name, "=", value; | |
sub_block = block_name, "{", block, "}"; | |
key_name = identifier; | |
block_name = identifier; | |
value = matches any string of text that ends with a newline character, # or }. | |
note that the trailing newline, # or } is not part of the value though. | |
identifier = Any string that matches the following regular expression: | |
[a-zA-Z][a-zA-Z0-9_-\.]* | |
i.e. Any string that starts with a letter and then is continued | |
with any number of letters, numbers, _ . or - characters. | |
Whitespace and comments are ignored. A comment is text that starts with # (but not \# | |
since the \ escapes the # so that you can have a # symbol in a value if you want) and | |
ends in a new line. You can also escape a } (e.g. "\}") if you want to have one in a | |
value. | |
Note that in a value the leading and trailing white spaces are stripped off but any | |
white space inside the value is preserved. | |
Also note that all key_names and block_names within a block syntax group must be unique | |
but don't have to be globally unique. I.e. different blocks can reuse names. | |
EXAMPLE CONFIG FILES: | |
Example 1: | |
#comment. This line is ignored because it starts with # | |
#here we have key1 which will have the value of "my value" | |
key1 = my value | |
another_key= another value # this is another key called "another_key" with | |
# a value of "another value" | |
# this key's value is the empty string. I.e. "" | |
key2= | |
Example 2: | |
#this example illustrates the use of blocks | |
some_key = blah blah | |
# now here is a block | |
our_block | |
{ | |
# here we can define some keys and values that are local to this block. | |
a_key = something | |
foo = bar | |
some_key = more stuff # note that it is ok to name our key this even though | |
# there is a key called some_key above. This is because | |
# we are doing so inside a different block | |
} | |
another_block { foo = bar2 } # this block has only one key and is all on a single line | |
!*/ | |
public: | |
// exception classes | |
class config_reader_error : public dlib::error | |
{ | |
/*! | |
GENERAL | |
This exception is thrown if there is an error while parsing the | |
config file. The type member of this exception will be set | |
to ECONFIG_READER. | |
INTERPRETING THIS EXCEPTION | |
- line_number == the line number the parser was at when the | |
error occurred. | |
- if (redefinition) then | |
- The key or block name on line line_number has already | |
been defined in this scope which is an error. | |
- else | |
- Some other general syntax error was detected | |
!*/ | |
public: | |
const unsigned long line_number; | |
const bool redefinition; | |
}; | |
class file_not_found : public dlib::error | |
{ | |
/*! | |
GENERAL | |
This exception is thrown if the config file can't be opened for | |
some reason. The type member of this exception will be set | |
to ECONFIG_READER. | |
INTERPRETING THIS EXCEPTION | |
- file_name == the name of the config file which we failed to open | |
!*/ | |
public: | |
const std::string file_name; | |
}; | |
class config_reader_access_error : public dlib::error | |
{ | |
/*! | |
GENERAL | |
This exception is thrown if you try to access a key or | |
block that doesn't exist inside a config reader. The type | |
member of this exception will be set to ECONFIG_READER. | |
!*/ | |
public: | |
config_reader_access_error( | |
const std::string& block_name_, | |
const std::string& key_name_ | |
); | |
/*! | |
ensures | |
- #block_name == block_name_ | |
- #key_name == key_name_ | |
!*/ | |
const std::string block_name; | |
const std::string key_name; | |
}; | |
// -------------------------- | |
config_reader( | |
); | |
/*! | |
ensures | |
- #*this is properly initialized | |
- This object will not have any keys or blocks defined in it. | |
throws | |
- std::bad_alloc | |
- config_reader_error | |
!*/ | |
config_reader( | |
std::istream& in | |
); | |
/*! | |
ensures | |
- #*this is properly initialized | |
- reads the config file to parse from the given input stream, | |
parses it and loads this object up with all the sub blocks and | |
key/value pairs it finds. | |
- before the load is performed, the previous state of the config file | |
reader is erased. So after the load the config file reader will contain | |
only information from the given config file. | |
- This object will represent the top most block of the config file. | |
throws | |
- std::bad_alloc | |
- config_reader_error | |
!*/ | |
config_reader( | |
const std::string& config_file | |
); | |
/*! | |
ensures | |
- #*this is properly initialized | |
- parses the config file named by the config_file string. Specifically, | |
parses it and loads this object up with all the sub blocks and | |
key/value pairs it finds in the file. | |
- before the load is performed, the previous state of the config file | |
reader is erased. So after the load the config file reader will contain | |
only information from the given config file. | |
- This object will represent the top most block of the config file. | |
throws | |
- std::bad_alloc | |
- config_reader_error | |
- file_not_found | |
!*/ | |
virtual ~config_reader( | |
); | |
/*! | |
ensures | |
- all memory associated with *this has been released | |
!*/ | |
void clear( | |
); | |
/*! | |
ensures | |
- #*this has its initial value | |
throws | |
- std::bad_alloc | |
If this exception is thrown then *this is unusable | |
until clear() is called and succeeds | |
!*/ | |
void load_from ( | |
std::istream& in | |
); | |
/*! | |
ensures | |
- reads the config file to parse from the given input stream, | |
parses it and loads this object up with all the sub blocks and | |
key/value pairs it finds. | |
- before the load is performed, the previous state of the config file | |
reader is erased. So after the load the config file reader will contain | |
only information from the given config file. | |
- *this will represent the top most block of the config file contained | |
in the input stream in. | |
throws | |
- std::bad_alloc | |
If this exception is thrown then *this is unusable | |
until clear() is called and succeeds | |
- config_reader_error | |
If this exception is thrown then this object will | |
revert to its initial value. | |
!*/ | |
void load_from ( | |
const std::string& config_file | |
); | |
/*! | |
ensures | |
- parses the config file named by the config_file string. Specifically, | |
parses it and loads this object up with all the sub blocks and | |
key/value pairs it finds in the file. | |
- before the load is performed, the previous state of the config file | |
reader is erased. So after the load the config file reader will contain | |
only information from the given config file. | |
- This object will represent the top most block of the config file. | |
throws | |
- std::bad_alloc | |
If this exception is thrown then *this is unusable | |
until clear() is called and succeeds | |
- config_reader_error | |
If this exception is thrown then this object will | |
revert to its initial value. | |
- file_not_found | |
If this exception is thrown then this object will | |
revert to its initial value. | |
!*/ | |
bool is_key_defined ( | |
const std::string& key_name | |
) const; | |
/*! | |
ensures | |
- if (there is a key with the given name defined within this config_reader's block) then | |
- returns true | |
- else | |
- returns false | |
!*/ | |
bool is_block_defined ( | |
const std::string& block_name | |
) const; | |
/*! | |
ensures | |
- if (there is a sub block with the given name defined within this config_reader's block) then | |
- returns true | |
- else | |
- returns false | |
!*/ | |
typedef config_reader this_type; | |
const this_type& block ( | |
const std::string& block_name | |
) const; | |
/*! | |
ensures | |
- if (is_block_defined(block_name) == true) then | |
- returns a const reference to the config_reader that represents the given named sub block | |
- else | |
- throws config_reader_access_error | |
throws | |
- config_reader_access_error | |
if this exception is thrown then its block_name field will be set to the | |
given block_name string. | |
!*/ | |
const std::string& operator[] ( | |
const std::string& key_name | |
) const; | |
/*! | |
ensures | |
- if (is_key_defined(key_name) == true) then | |
- returns a const reference to the value string associated with the given key in | |
this config_reader's block. | |
- else | |
- throws config_reader_access_error | |
throws | |
- config_reader_access_error | |
if this exception is thrown then its key_name field will be set to the | |
given key_name string. | |
!*/ | |
template < | |
typename queue_of_strings | |
> | |
void get_keys ( | |
queue_of_strings& keys | |
) const; | |
/*! | |
requires | |
- queue_of_strings is an implementation of queue/queue_kernel_abstract.h | |
with T set to std::string, or std::vector<std::string>, or | |
dlib::std_vector_c<std::string> | |
ensures | |
- #keys == a collection containing all the keys defined in this config_reader's block. | |
(i.e. for all strings str in keys it is the case that is_key_defined(str) == true) | |
!*/ | |
template < | |
typename queue_of_strings | |
> | |
void get_blocks ( | |
queue_of_strings& blocks | |
) const; | |
/*! | |
requires | |
- queue_of_strings is an implementation of queue/queue_kernel_abstract.h | |
with T set to std::string, or std::vector<std::string>, or | |
dlib::std_vector_c<std::string> | |
ensures | |
- #blocks == a collection containing the names of all the blocks defined in this | |
config_reader's block. | |
(i.e. for all strings str in blocks it is the case that is_block_defined(str) == true) | |
!*/ | |
private: | |
// restricted functions | |
config_reader(config_reader&); // copy constructor | |
config_reader& operator=(config_reader&); // assignment operator | |
}; | |
} | |