X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fstlplus%2Fsubsystems%2Fini_manager.hpp;fp=src%2Fstlplus%2Fsubsystems%2Fini_manager.hpp;h=f1d7a66a03a18819e5b4431aea89c06af5992a1f;hp=0000000000000000000000000000000000000000;hb=6b0a0d0efafe34d48ab344fca3b479553bd4e62c;hpb=85783316365181491a3e3c0c63659972477cebba diff --git a/src/stlplus/subsystems/ini_manager.hpp b/src/stlplus/subsystems/ini_manager.hpp new file mode 100644 index 0000000..f1d7a66 --- /dev/null +++ b/src/stlplus/subsystems/ini_manager.hpp @@ -0,0 +1,201 @@ +#ifndef STLPLUS_INI_MANAGER +#define STLPLUS_INI_MANAGER +//////////////////////////////////////////////////////////////////////////////// + +// Author: Andy Rushton +// Copyright: (c) Southampton University 1999-2004 +// (c) Andy Rushton 2004-2009 +// License: BSD License, see ../docs/license.html + +// A subsystem for managing INI (i.e. .ini) files +// An INI file has the following format + +// file ::= header { section }* +// header ::= { comment | blank }* +// section ::= section_header { declaration | comment | blank }* +// section_header ::= '[' title ']' '\n' +// declaration ::= variable '=' value '\n' +// comment ::= ';' text '\n' +// blank ::= '\n' +// title ::= [~']']* +// variable ::= [~'=']* +// value ::= .* +// text ::= .* + +// Whitespace is trimmed from the leading and trailing ends of title, variable and value +// Note: a header is represented internally as a Clint section (i.e. a section with no name) + +//////////////////////////////////////////////////////////////////////////////// +#include "subsystems_fixes.hpp" +#include +#include +#include + +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + // Internals + + class ini_manager_body; + + //////////////////////////////////////////////////////////////////////////////// + // Ini-file manager class + + class ini_manager + { + public: + + ini_manager(void); + + explicit ini_manager(const std::vector& filenames); + + ini_manager(const ini_manager&); + ini_manager& operator= (const ini_manager&); + + ~ini_manager(void); + + ////////////////////////////////////////////////////////////////////////////// + // file management + + // add files starting with the most local file (e.g. the current project) which has depth 0 + // and working back to the most global (e.g. the installation settings) which has a depth of size()-1 + // This does nothing if the file has already been loaded - it is not permitted to manage the same file twice. + // Returns true if the file loaded okay or was already loaded (it is counted as successful if the file did + // not exist, only read errors cause a failure) + bool add_file(const std::string& filename); + + // as above, returns false if *none* of the files were added + // filenames[0] is the local file, and so on + bool add_files(const std::vector& filenames); + + // saves modified ini files - returns true if all modified files were written successfully + bool save(void); + + // get the number of files being managed + unsigned size(void) const; + + // get the ini filename associated with a depth + std::string filename(unsigned depth = 0) const; + + // test whether a file in the ini manager is writable + bool writable(unsigned depth = 0) const; + + // test whether a file is empty + // An ini file is considered empty if it has no named sections and the header is empty or missing + bool empty(unsigned depth = 0) const; + + // erase the ini file from the ini manager and from the disk + bool erase(unsigned depth = 0); + + // remove the file from the ini manager but do not erase it from the disk + bool remove(unsigned depth = 0); + + ////////////////////////////////////////////////////////////////////////////// + // section management + + // returns the union of all section names in all of the ini files + std::vector section_names(void) const; + + // returns the section names in one of the ini files + std::vector section_names(unsigned depth) const; + + // tests whether a section is found in any of the ini files + bool section_exists(const std::string& title) const; + + // tests whether the section is found in the specific ini file + bool section_exists(const std::string& title, unsigned depth) const; + + // adds a section to the specified ini file - does nothing if it is already present + bool add_section(const std::string& section, unsigned depth = 0); + + // test whether a section is empty + bool empty_section(const std::string& section, unsigned depth = 0); + + // removes a section from the specified ini file if it exists there but cannot remove it from any other file + bool erase_section(const std::string& section, unsigned depth = 0); + + // removes all the contents of a section from the specified ini file but keeps the empty section + bool clear_section(const std::string& section, unsigned depth = 0); + + ////////////////////////////////////////////////////////////////////////////// + // variable management + + // test whether a variable exists in any of the ini files + bool variable_exists(const std::string& section, const std::string variable) const; + + // test whether a variable exists in specified ini file + bool variable_exists(const std::string& section, const std::string variable, unsigned depth) const; + + // get the union of all variables declared in all ini files + std::vector variable_names(const std::string& section) const; + + // get the set of all varaibale names from one file + std::vector variable_names(const std::string& section, unsigned depth) const; + + // get the depth of the first ini file to define a variable + // returns 0 if defined in the local ini file, etc. Returns (unsigned)-1 if the variable doesn't exist + unsigned variable_depth(const std::string& section, const std::string variable) const; + + // get the filename that first defines the variable + std::string variable_filename(const std::string& section, const std::string variable) const; + // ditto for its linenumber within that file + unsigned variable_linenumber(const std::string& section, const std::string variable) const; + + // get the value of a variable as a single unprocessed string + // if the variable does not exist the string will be empty, but beware that + // you also get an empty string if a variable exists but has no value + // you can differentiate between the two cases by using variable_exists_all above + std::string variable_value(const std::string& section, const std::string variable) const; + + // get the value from the specified file + std::string variable_value(const std::string& section, const std::string variable, unsigned depth) const; + + // get the value of a variable as a processed string + // processing splits the value at commas and furthermore supports quoted strings (so that values can contain commas for example) + // quoted strings are dequoted before they are added to the result + // the result is a vector of dequoted strings, one per value in the comma-separated list + std::vector variable_values(const std::string& section, const std::string variable) const; + + // get the processed variable from the specified file + std::vector variable_values(const std::string& section, const std::string variable, unsigned depth) const; + + // add a variable to the specified file + bool add_variable(const std::string& section, const std::string& variable, const std::string& value, unsigned depth = 0); + + // add a variable as a processed string + // processing means that the values in the string vector are converted into a comma-separated list + // values containing reserved characters are automatically quoted - so you should not even try to quote them yourself + bool add_variable(const std::string& section, const std::string& variable, const std::vector& values, unsigned depth = 0); + + // erase a variable from the specified file + // this does not remove the variable from other ini files, so the variable may still exist + // to mask a global variable, set the variable to an empty string instead + bool erase_variable(const std::string& section, const std::string& variable, unsigned depth = 0); + + ////////////////////////////////////////////////////////////////////////////// + // sundry line-entry management + + // add a comment to the specified ini file + bool add_comment(const std::string& section, const std::string& comment, unsigned depth = 0); + + // add a blank line to the specified ini file + bool add_blank(const std::string& section, unsigned depth = 0); + + bool print(std::ostream&) const; + + private: + friend class ini_manager_body; + ini_manager_body* m_body; + }; + + //////////////////////////////////////////////////////////////////////////////// + // diagnostic print routine + + std::ostream& operator << (std::ostream&, const ini_manager&); + + //////////////////////////////////////////////////////////////////////////////// + +} // end namespace stlplus + +#endif