============================================================================= Iniphile ============================================================================= ----------------------------------------------------------------------------- Ini file parsing library for C++ ----------------------------------------------------------------------------- :Author: Roman Neuhauser :Contact: neuhauser@sigpipe.cz :Copyright: This document is in the public domain. .. this file is marked up using reStructuredText lines beginning with ".." are reST directives "foo_" or "`foo bar`_" is a link, defined at ".. _foo" or ".. _foo bar" "::" introduces a literal block (usually some form of code) "`foo`" is some kind of identifier suspicious backslashes in the text ("`std::string`\s") are required for reST to recognize the preceding character as syntax .. contents:: Introduction ============ Iniphile is a C++ library for parsing a dialect of INI file format. Prerequisities ++++++++++++++ Iniphile is known to build and run on FreeBSD 9 with gcc >= 4.2.1, and on Windows XP with Visual Studio 2008 (vc9). The library uses a few header-only Boost_ libraries in both its interface and implementation. The interface mentions Boost.Optional_ and Boost.Variant_, The most prominent implementation detail is Boost.Spirit_, specifically v2.1 (Boost_ 1.41) or higher. Unit tests require Boost.Test_ to compile and run. .. important:: For now, Iniphile supports linking only against Boost libraries built with ``--layout=system``, ``-DBOOST_ALL_NO_LIB`` is used unconditionally. This means that if your Boost shared libraries have funny names like `boost_regex-vc90-mt-1_45.dll`, linking the test executables will fail. The Iniphile *library* depends on header-only Boost libraries and the linker failure has no effect on it. You just won't be able to run its unit tests. .. _Boost: http://boost.org/ .. _Boost.Optional: http://www.boost.org/doc/libs/1_42_0/libs/optional/index.html .. _Boost.Variant: http://www.boost.org/doc/libs/1_42_0/libs/variant/index.html .. _Boost.Spirit: http://www.boost.org/doc/libs/1_42_0/libs/spirit/index.html .. _Boost.Test: http://www.boost.org/doc/libs/1_42_0/libs/test/index.html Example ======= notify.ini :: [notify] enabled = No addresses = alice@example.com bob@example.com chris@example.com notify.cpp :: #include #include #include #include #include "input.hpp" #include "ast.hpp" #include "output.hpp" bool notify(std::vector const& addrs) { // whatever } int main() { namespace ini = iniphile; std::ifstream input("notify.ini"); std::ostringstream diag; ini::parse_result cfg(ini::parse(input, diag)); if (!cfg) { std::cerr << "garbled configuration\n"; return EXIT_FAILURE; } ini::ast::node afg(ini::normalize(*cfg)); typedef std::vector values; bool enabled = ini::get(afg, "notify.enabled", false); long attempts = ini::get(afg, "notify.attempts", 3L); values addrs = ini::get(afg, "notify.addresses", values()); while (enabled && attempts--) { if (notify(addrs)) return EXIT_SUCCESS; } return EXIT_FAILURE; } Reference ========= INI file syntax +++++++++++++++ There's no standard definition of INI file syntax and semantics. The ABNF_ grammar below approximates the dialect supported by this library (only *significant* whitespace is part of the grammar). See the following prose for clarifications). .. _ABNF: http://tools.ietf.org/html/std68 :: inifile = *section EOF section = *comentline headerline sectionbody headerline = "[" sectionname "]" comment sectionname = 1*LCHAR ; except "]" sectionbody = *(assignment / comment) assignment = optname "=" optval optname = 1*VCHAR ; except "=" optval = ovlinefirst *ovlinecont ovlinefirst = [ovline] comment ovlinecont = 1*WSP ovline comment ovline = *optvalpart optvalpart = qstring / bareword qstring = DQUOTE *CHAR DQUOTE bareword = 1*VCHAR ; except ";" comment = *1(";" *LCHAR) EOL EOL = CRLF / CR / LF LCHAR = VCHAR / WSP An `inifile` is a flat, possibly empty, collection of `section`\s. A `section` begins at a `headerline` and continues until the next `headerline` or `EOF`, whichever comes first. Each `section` contains zero or more `assignment`\s, `optname`/`optval` pairs. Whitespace allowed around the "=". `optname` must begin at the start of a line. `optval` is a list of strings (`optvalpart`, either a `qstring` or a `bareword`) separated by whitespace. It may span multiple lines: continuation lines begin with horizontal whitespace, and `qstring`\s may also contain newlines. Library +++++++ Header Organization ~~~~~~~~~~~~~~~~~~~ Each header `#include`\s all its dependencies. * metagram.hpp :: typedef unspecified iniphile::config; * input.hpp :: #include typedef boost::optional parse_result; iniphile::parse_result iniphile::parse( std::string const& input , std::ostream& diag ); iniphile::parse_result iniphile::parse( std::istream& input , std::ostream& diag ); * astfwd.hpp :: #include typedef std::vector iniphile::valpath; valpath to_valpath(std::string const & path); typedef unspecified iniphile::ast::node; * ast.hpp :: #include "astfwd.hpp" iniphile::ast::node iniphile::normalize(iniphile::config const & cst); * output.hpp :: template T iniphile::get( iniphile::ast::node const& cfg , iniphile::valpath const& path , T dflt ); template T iniphile::get( iniphile::ast::node const& cfg , std::string const& path , T dflt ); T get(ast::node, std::string, T) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The library defines these specializations: * `std::vector` One `optvalpart` per `std::string`. `DQUOTE`\s from `qstrings` are not maintained. * `std::string` The whole `optval` with whitespace between `optvalpart`\s normalized to single spaces. `DQUOTE`\s from `qstrings` are maintained. * `bool` The first `optvalpart` interpreted as a bool according to these rules: :: true <= "1" / "true" / "yes" / "on" ; case insensitive false <= "0" / "false" / "no" / "off" ; case insensitive * `long` The first `optvalpart` interpreted as a long using the `boost::spirit::qi::long_`_ parser (decimal representation with optional leading sign). * `double` The first `optvalpart` interpreted as a double using the `boost::spirit::qi::double_`_ parser (decimal representation of ints and doubles, scientific representation (nnn.fff.Eeee) of doubles. .. _boost::spirit::qi::double_: .. _boost::spirit::qi::long_: .. _boost::spirit::qi::numeric: http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/spirit/qi/reference/numeric.html Downloads ========= Repository ++++++++++ The latest source can be checked out from the Mercurial_ repository_. .. _Mercurial: http://selenic.com/mercurial/ .. _repository: https://hg.sigpipe.cz/ Official tarballs +++++++++++++++++ All Iniphile releases can be found in the `download directory`_. .. _download directory: http://codex.sigpipe.cz/iniphile/dist/ Build and Installation ====================== Iniphile is distributed with a set of Makefiles suitable for several environments. Currently supported are: FreeBSD make and GNU make with the GNU C++ compiler, MSVC nmake with the Microsoft compiler. Let `$make` be your make command, and let `$env` be `bsd`, `gnu` or `msvc` as appropriate. Then ``$make -f $env.mk libs`` (requires Boost.Spirit_) creates a static library and a dll plus import library ``$make -f $env.mk check`` (requires Boost.Test_) creates the libraries and runs their unit tests Unix ++++ Main variables and their default values: `CXX`: ``g++$(GCCVER)`` `GCCVER`: ```` `PREFIX`: ``/usr/local`` `LIBDIR`: ``$(PREFIX)/lib`` `INCDIR`: ``$(PREFIX)/include`` `PKGCONFIGDIR`: ``$(LIBDIR)/pkgconfig`` `_BOOST`: ``$(PREFIX)`` `SPIRIT`: ``$(_BOOST)/include`` `UTFINC`: ``$(_BOOST)/include`` `UTFLIB`: ``$(_BOOST)/lib`` `UTFRUN`: ``$(UTFLIB)`` FreeBSD ~~~~~~~ :: make -f bsd.mk gmake -f gnu.mk pkg-config files are stored in a nonstandard path on this system. If you install into `/usr/local`, make sure to do so with `PKGCONFIGDIR=/usr/local/libdata/pkgconfig`. GNU/Linux (or other with the GNU toolchain) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: make -f gnu.mk Both `bsd.mk` and `gnu.mk` assume the GNU gcc suite; there are two makefiles because of syntactic differences between the GNU make and the FreeBSD one. Windows +++++++ Main variables and their default values: `PREFIX`: ``.\stage`` `INCDIR` ``$(PREFIX)\include`` `LIBDIR` ``$(PREFIX)\lib`` `BOOST_INCDIR`: ```` `BOOST_LIBDIR`: ```` `msvc.mk` assumes and relies on tools provided with MS Visual C++ Express exclusively. It's tested on MS Windows Vista with VC++ 2008/9.0 Express, and works in the Visual Studio Command Prompt and the Windows SDK CMD Shell. :: nmake -f msvc.mk No attempt to guess or find the Boost prerequisities is made, you must supply `BOOST_INCDIR` and `BOOST_LIBDIR` or the compilation will fail. ``nmake -f msvc.mk install`` puts built libraries in ``$(LIBDIR)`` (defaults to ``$(PREFIX)\lib``) and header files in ``$(INCDIR)`` (defaults to ``$(PREFIX)\include``). .. target-notes:: .. section-numbering:: .. vim: ft=rst sts=2 sw=2 tw=77