// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt /* This is an example illustrating the use of the config_reader component from the dlib C++ Library. This example uses the config_reader to load a config file and then prints out the values of various fields in the file. */ #include "dlib/config_reader.h" #include "dlib/string.h" #include #include #include // Here I'm just making a typedef of the config reader we will be using. If you // look at the documentation you will see that there are two possible config_reader // types we could use here. The other one is a thread-safe version for use in an // application that needs to access a global config reader from multiple threads. // But we aren't doing that here so I'm using the normal kind. typedef dlib::config_reader cr_type; using namespace std; using namespace dlib; // ---------------------------------------------------------------------------------------- // For reference, the contents of the config file used in this example is reproduced below: /* # This is an example config file. Note that # is used to create a comment. # At its most basic level a config file is just a bunch of key/value pairs. # So for example: key1 = value2 dlib = a C++ library # You can also define "sub blocks" in your config files like so user1 { # Inside a sub block you can list more key/value pairs. id = 42 name = davis # you can also nest sub-blocks as deep as you want details { editor = vim home_dir = /home/davis } } user2 { id = 1234 name = joe details { editor = emacs home_dir = /home/joe } } */ // ---------------------------------------------------------------------------------------- void print_config_reader_contents ( const cr_type& cr, int depth = 0 ); /* This is a simple function that recursively walks through everything in a config reader and prints it to the screen. */ // ---------------------------------------------------------------------------------------- int main() { try { cr_type cr("config.txt"); // Use our recursive function to print everything in the config file. print_config_reader_contents(cr); // Now lets access some of the fields of the config file directly. You // use [] for accessing key values and .block() for accessing sub-blocks. // Print out the string value assigned to key1 in the config file cout << cr["key1"] << endl; // Print out the name field inside the user1 sub-block cout << cr.block("user1")["name"] << endl; // Now print out the editor field in the details block cout << cr.block("user1").block("details")["editor"] << endl; // Note that you can use the string_assign object, sa, to easily convert fields // into non-string types. For example, the config file has an integer id // field that could be converted into an int like so: int id1 = sa = cr.block("user1")["id"]; int id2 = sa = cr.block("user2")["id"]; cout << "user1's id is " << id1 << endl; cout << "user2's id is " << id2 << endl; } catch (exception& e) { // Finally, note that the config_reader throws exceptions if the config // file is corrupted or if you ask it for a key or block that doesn't exist. // Here we print out any such error messages. cout << e.what() << endl; } } // ---------------------------------------------------------------------------------------- void print_config_reader_contents ( const cr_type& cr, int depth ) { // Make a string with depth*4 spaces in it. const string padding(depth*4, ' '); // We can obtain a list of all the keys and sub-blocks defined // at the current level in the config reader like so: vector keys, blocks; cr.get_keys(keys); cr.get_blocks(blocks); // Now print all the key/value pairs for (unsigned long i = 0; i < keys.size(); ++i) cout << padding << keys[i] << " = " << cr[keys[i]] << endl; // Now print all the sub-blocks. for (unsigned long i = 0; i < blocks.size(); ++i) { // First print the block name cout << padding << blocks[i] << " { " << endl; // Now recursively print the contents of the sub block. Note that the cr.block() // function returns another config_reader that represents the sub-block. print_config_reader_contents(cr.block(blocks[i]), depth+1); cout << padding << "}" << endl; } } // ----------------------------------------------------------------------------------------