| Version | Date | Notes |
| 0.1 | 2004-04-15 | Initial version, contains support getting and adding properties, reading, parsing and writing configuration information |
| 0.2 | 2004-04-16 | Added methods for removing properties and clearing the configuration. Corrected write/debug methods to include semicolon. Corrected parser to handle multiple simultaneous comments within an assignment. Improved documentation. |
| 0.3 | 2004-04-23 | Moved existing configuration file parser to the "Simple" namespace with appropriate class name changes. Added a configuration file parser that remembers comments, whitespace and the order of all statements. |
| 0.4 | 2004-04-24 | All AddXXXX functions now return a pointer to the value instead of a bool. Added a method to get the property table to ConfigManager class. Added a flag to ConfigManager::read() to indicate whether comment/whitespace formatting should be preserved. Removed the "Simple" namespace, the same functionality can now be achieved using ConfigManager but indicating that comments/whitespace should not be preserved. Fully documented the interface. |
| 0.41 | 2004-04-25 | Added a means to explicitly set the Preserve Formatting flag in ConfigManager. Fixed duplicate eol being written to each line of file. |
| 0.42 | 2004-04-26 | Fixed a bug: String variables were including the enclosing double-quote characters, now they are removed. |
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
sample.cfg:
// C++ style comments supported /* C-style comments also supported */ AutoStartOn = false; // boolean value BuildNumber =44; // integer property Version=1.2; // real property AppName= "CodeDread"; // string property // a composite property Player { // another comment Number = // inline comments allowed 1; Name = "Jeff"; // composite property Backpack { Color = "Brown"; Size = 10; } }
The above cfg file looks a lot like C/C++ code and thus makes it convenient for syntax highlighting in Development IDEs.
The parser can remember whitespace and all text formatting such that when it re-writes the configuration file it can preserve the file format.
The formal EBNF notation for the configuration file grammar is located on the grammar page.
A ConfigManager object has the ability to read in a configuration file, parse it and store the configuration data in memory. The configuration data is available for access, modification and removal. The ConfigManager object can also write the configuration data back to a file (with the option of preserving comments and whitespace or removing it.
Some example code may help. All of the below examples use the above configuration file:
Reading a Configuration File
Getting Simple Property Values
Getting Composite Property Values
Changing Property Values
Adding Properties
Removing Properties
Writing a Configuration File
Create a ConfigManager object and invoke the read() method on it.
ConfigManager config;
// read in configuration file
if(!config.read("sample.cfg")) {
cerr << "Error reading file" << endl;
exit(-1);
}
To retrieve a property value, call the getXXXXProperty() methods. If the property is not found, you can use the addXXXXProperty() method.
// get AutoSaveOn bool property bool* pbAutoSaveOn = NULL; if( !config.getBoolProperty("AutoSaveOn", &pbAutoSaveOn)) { pbAutoSaveOn = config.addBoolProperty("AutoSaveOn", true); } assert(pbAutoSaveOn); cout << "AutoSaveOn = " << *pbAutoSaveOn << endl; // get AppName string property string* psAppName = NULL; if( !config.getStringProperty("AppName", &psAppName)) { psAppName = config.addStringProperty("AppName", "MyApp"); } assert(psAppName); cout << "AppName = " << *psAppName << endl;
To retrieve a composite property, use the getCompositeProperty() method. To recurse several levels deep, continue to call the getCompositeProperty() method:
// get Player.Backpack.Size integer property CompositeAssignment* pcPlayer = NULL; CompositeAssignment* pcBackpack = NULL; int* pcBPSize = NULL; // we can use one if to retrieve Player.Backpack.Size if we want: if( !config.getCompositeProperty("Player", &pcPlayer) || !pcPlayer || !pcPlayer->getCompositeProperty("Backpack", &pcBackpack) || !pcBackpack || !pcBackback->getIntProperty("Size", &pcBPSize) || !pcBPSize) { cerr << "Player.Backpack.Size property not found" << endl; exit(-1); } cout << "Player.Backpack.Size = " << *pcBPSize << endl;
To change a property value, update the pointed-to values:
*pbAutoSaveOn = false; // AutoSaveOn now equals false *pcBPSize = 20; // Player.Backpack.Size now equals 20
To add a completely new property to the configuration data, invoke the addXXXXProperty method on the appropriate object:
// add another string property: string* psAuthor = config.addStringProperty("AppAuthor", "Jeff Schiller"); // add a bool property to the Player.Backpack composite: bool* pbBackpackFilled = pcBackpack->addBoolProperty("Filled", false);
Removal of a property simply requires invocation of the removeProperty method:
if(config.removeProperty("Version")) { cout << "Version property was removed" << endl; }
Perhaps the most simplest operation of all, simply invoke the write() method on the ConfigManager object:
// Write configuration file back to disk config.write("sample.cfg");
1.3.5