Day 17 : 24 June 2022 : Adding a Configuration File
My 100 Daze of Code
https://github.com/davidjwalling/100-days-of-code
#17 : Adding a Configuration File
Today we'll add the final component of our configuration design, support for reading a configuration file. There are various standards for configuration file. Which might be another way of saying there is no real standard for configuration files. Here, I've adopted a simple "<name> = <value>" structure.
The configuration file settings are given higher precedence than Registry or Environment settings. But they are lower in priority than program arguments. So after we apply system-wide settings values from the Registry (on Windows only) and then apply current Environment (user) settings, then we can apply settings from a configuration file that can be specific to the location where the program is run, so that multiple copies of the program can run concurrently, in different paths, and have distinct settings. Finally, any setting can be overridden with program arguments per execution.
The name of the configuration file can be set to a default. But even the configuration file name could be set in the Registry, Environment or on the command line. Overriding which configuration file is read by setting that file name in the Registry or Environment is straightforward, since those sources are read first. But if we want to override our configuration file name on the command-line, then we will have to look at our program arguments to see if a configuration file name is specified there before we apply configuration file settings. Then, to keep things in order, we'll need to return to the program arguments again in case we need to override anything that was set in the configuration file.
We'll start by defining a GetFileArg method in Driver, that will be called right after applying Registry and Environment variables, to scan the program arguments for an alternate configuration file name.
Next, we'll define a GetFileVars method in Driver to open the configuration file, read and process each line, and then close the configuration file. Since file I/O operations are reusable, we'll add a File class to the project, implemented in a file.cpp file and declared in a file.h file.
The ParseLine method isolates the "name" and "value" portions of the line, determine whether the "name" is valid setting, and calling a "SetVar" method to apply the value of the setting.
The SetVar method is a simple case structure that will invoke the appropriate setter for the setting. This could be a good candidate for using std::bind in the future.
Now we'll add a call to GetFileVars in our Configuration routine.
To test, we'll combine all four settings methods and also provide an alternate configuration file name in our program arguments. We leave our Registry setting for the logging prefix as we had it from before. Also, we still are setting our logging path in the Environment. Our default configuration file name is "ava.cfg" (to distinguish it from ava.conf that used with systemctl on Linux). But we'll define a new program argument "-f" to specify an alternate configuration file, "day17.cfg". Lastly, we'll include a logging-level setting value in the day17.cfg file. Our logging output should show all configuration settings being applied in the correct order.
Here is our day17.cfg file:
Here are our debugging settings showing the program arguments:
Here is the logging output shown on the console:








Comments
Post a Comment