winix/core/confparser.h

363 lines
7.7 KiB
C++
Executable File

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* All rights reserved.
*
*/
#ifndef headerfileconfparser
#define headerfileconfparser
#include <fstream>
#include <string>
#include <vector>
#include <map>
/*
A parser for parsing config files.
A config file can look like this:
variable1 = value 1
variable2 = " value 2 "
variable3 = (value 1, value 2)
variable4 = (" value 1 " , "value2", value 3)
sample of use:
ConfParser parser;
parser.Parse("/path/to/config");
if( parser.status == ConfParser::ok )
{
// the whole config we have in parser.table (parser.table_single)
}
config syntax:
option = list
list can consists of any number of items, if you're using more than one item you should
use brackets ()
for one item the brackets can be ommited:
option = value
white characters at the beginning of the value (and at the end) will be trimmed,
or you can use quotes:
option = "value"
option2 = "value with spaces at the end "
the form without quotes:
option = value
should be written in one line, so this is not allowed:
option =
value
you can use a new line characters only between brackets and quotes:
option = "this is
a multiline string"
option = ( value1,
value2 )
but there is one requirement: the first character " or ( should be in the same line,
so this is not allowed
option =
"this is wrong"
but this is ok:
option = "
that is ok"
empty lists:
option = ()
this creates an empty list: parser.table['option'].empty() == true
option =
this creates an empty list too (the same as previously)
option = ""
but this doesn't create an empty list, it creates a list with one (empty) item
commentaries:
# this is a commentary (until the end of the line)
option = value # this is a commentary too
commentaries are treated as white characters, other example:
option = ( # this is my list
"value 1" # this is a value one
value 2 # and this is a value two
) # end of my list
overwriting:
option1 = some value
option1 = other value
# always the last option is used so option1 is "other value"
list delimiter:
option1 = (value1, value2, value3)
option2 = ("value1", "value2", "value3")
above we're using a comma ',' as a list delimiter but when using quotes (second line)
the commas can be omitted:
option2 = ("value1" "value2" "value3")
white characters:
the name of an option cannot consist of white characters
some option = value # this is wrong
some_option = value # this is ok
which characters are allowed in an option name is defined by IsVariableChar() method
you can use white characters in values
option = value with spaces or tabs
white characters at the beginning and at the end will be trimmed,
so if you want them use quotes:
option = " other value with spaces "
special characters in quoted strings:
option = "this is a string with \" a quote inside"
the option will be: this is a string with " a quote inside
\\ - means one \
basically: \char produces char
so:
"\a" gives "a"
"\\" gives "\"
"\Z" gives "Z" and so on
*/
class ConfParser
{
public:
ConfParser();
/*
status of parsing
*/
enum Status { ok, cant_open_file, syntax_error };
/*
the last status of parsing, set by Parse() methods
*/
Status status;
/*
the main methods used to parse
file_name is the path to a file
*/
Status Parse(const char * file_name);
Status Parse(const std::string & file_name);
/*
a number of a line in which there is a syntax_error
*/
int line;
/*
this is the table which represents your config file
in the Table map: the first (key) is your 'option' and the second is 'list'
*/
typedef std::vector<std::string> Value;
typedef std::map<std::string, Value> Table;
Table table;
/*
if your config file consists mainly of single forms such as:
option = value
option2 = value2
then you can call SplitSingle(true) for not inserting single values to
previous 'table' but instead to 'table_single'
table_single as the second parameter takes only std::string (instead of the whole std::vector)
so you can save a little memory from not using std::vector
*/
typedef std::map<std::string, std::string> TableSingle;
TableSingle table_single;
/*
if your list consists of only one item, e.g:
option1 = value 1
option2 = "value 2"
option3 = ( "value 3" )
then if you call SplitSingle(true) then such values will be stored in
'table_single' instead of 'table' map
default: false
*/
void SplitSingle(bool split);
/*
if true then empty lists, e.g:
option =
option2 = ()
will be omitted (not inserted to 'table' or 'table_single')
default: false
*/
void SkipEmpty(bool skip);
/*
those methods are used to extract information from table or table_single
as a parameter they take the name of an option
and a default value (if there is no such a parameter),
they return appropriate value (either text, int or boolean)
(in lists they return the first item if exists)
*/
std::string Text(const char * name);
std::string Text(const char * name, const char * def);
std::string Text(const std::string & name, const std::string & def);
int Int(const char *);
int Int(const char * name, int def);
int Int(const std::string & name, int def);
size_t Size(const char *);
size_t Size(const char * name, size_t def);
size_t Size(const std::string & name, size_t def);
bool Bool(const char *);
bool Bool(const char * name, bool def);
bool Bool(const std::string & name, bool def);
/*
some default values
used in Text() Int() or Bool() when you don't explicitly set the default value
if you don't set it directly then:
default text is: "" (empty)
default int or size is: 0
default bool is: false
*/
void SetDefaultText(const std::string & def);
void SetDefaultInt(int def);
void SetDefaultSize(size_t def);
void SetDefaultBool(bool def);
/*
those methods are used to extract lists
note: if there is one option in table_single they will return it
*/
void ListText(const char * name, std::vector<std::string> & list);
void ListText(const std::string & name, std::vector<std::string> & list);
private:
/*
last read variable (option)
*/
std::string variable;
/*
last read list item
*/
std::string value_item;
/*
last read list
*/
Value value;
/*
separator between a variable and a value, default: '='
*/
int separator;
/*
commentary char, default: '#'
*/
int commentary;
/*
list starting character, default: '('
*/
int list_start;
/*
list ending character, default: ')'
*/
int list_end;
/*
list delimiter, default: ','
*/
int list_delimiter;
/*
last read char
*/
int lastc;
/*
current file
*/
std::ifstream file;
/*
if true then lists with one item will be put into 'table_single' table
default: false
*/
bool split_single;
/*
if true then empty lists, e.g:
option =
option2 = ()
will be omitted (not inserted to 'table' or 'table_single')
default: false
*/
bool skip_empty;
std::string default_str;
int default_int;
size_t default_size;
bool default_bool;
int ToInt(const std::string & value);
size_t ToSize(const std::string & value);
bool ToBool(const std::string & value);
Status ParseFile();
void AddOption();
void DeleteFromTable(const std::string & var);
void DeleteFromTableSingle(const std::string & var);
bool ReadVariable();
bool ReadValue();
bool ReadValueList();
bool ReadValueNoList(bool use_list_delimiter = false);
bool ReadValueQuoted();
bool ReadValueSimple(bool use_list_delimiter = false);
int ReadChar();
bool IsWhite(int c);
bool IsVariableChar(int c);
void SkipWhite();
void SkipWhiteLines();
void SkipLine();
void Trim(std::string & s);
};
#endif