364 lines
14 KiB
C++
364 lines
14 KiB
C++
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#undef DLIB_CONFIG_READER_KERNEl_ABSTRACT_
|
|
#ifdef DLIB_CONFIG_READER_KERNEl_ABSTRACT_
|
|
|
|
#include <string>
|
|
#include <iosfwd>
|
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif // DLIB_CONFIG_READER_KERNEl_ABSTRACT_
|
|
|