/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #ifndef headerfile_winix_core_confparser #define headerfile_winix_core_confparser #include #include #include #include /* 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 you can call UseEscapeChar(false) to turn this off */ 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); Status Parse(const wchar_t * file_name); Status Parse(const std::wstring & 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 Value; typedef std::map 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::wstring (instead of the whole std::vector) so you can save a little memory from not using std::vector */ typedef std::map 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); /* '\' character is used to escape other characters in a quoted string so "some \t t\"ext" will produce "some t t"ext" (this is only use in quoted string) default: true */ void UseEscapeChar(bool escape); /* 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::wstring Text(const wchar_t * name); std::wstring Text(const wchar_t * name, const wchar_t * def); std::wstring Text(const std::wstring & name, const std::wstring & def); std::string AText(const wchar_t * name); std::string AText(const wchar_t * name, const wchar_t * def); std::string AText(const std::wstring & name, const std::wstring & def); int Int(const wchar_t *); int Int(const wchar_t * name, int def); int Int(const std::wstring & name, int def); size_t Size(const wchar_t *); size_t Size(const wchar_t * name, size_t def); size_t Size(const std::wstring & name, size_t def); bool Bool(const wchar_t *); bool Bool(const wchar_t * name, bool def); bool Bool(const std::wstring & 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::wstring & 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 wchar_t * name, std::vector & list); void ListText(const std::wstring & name, std::vector & list); /* if true then the input file is treated as UTF-8 */ void UTF8(bool utf); /* printing the content (for debug purposes) */ void Print(std::ostream & out); private: /* last read variable (option) */ std::wstring variable; /* last read list item */ std::wstring 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 or -1 if the end */ 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; /* input file is in UTF-8 default: false */ bool input_as_utf8; /* if true you can use an escape character '\' in quoted values */ bool use_escape_char; std::string afile_name; std::wstring default_str; int default_int; size_t default_size; bool default_bool; int ToInt(const std::wstring & value); size_t ToSize(const std::wstring & value); bool ToBool(const std::wstring & value); Status ParseFile(); void AddOption(); void DeleteFromTable(const std::wstring & var); void DeleteFromTableSingle(const std::wstring & var); bool ReadVariable(); bool ReadValue(); bool ReadValueList(); bool ReadValueNoList(bool use_list_delimiter = false); bool ReadValueQuoted(); bool ReadValueSimple(bool use_list_delimiter = false); int ReadUTF8Char(); int ReadASCIIChar(); int ReadChar(); bool IsWhite(int c); bool IsVariableChar(int c); void SkipWhite(); void SkipWhiteLines(); void SkipLine(); void Trim(std::wstring & s); }; #endif