Go to the documentation of this file.00001 #include "utilmm/configfile/configfile.hh"
00002 #include "utilmm/configfile/exceptions.hh"
00003
00004 #include <boost/regex.hpp>
00005
00006 #include <fstream>
00007 #include <sstream>
00008
00009 using std::fstream;
00010 using std::string;
00011 using std::stringbuf;
00012 using namespace utilmm;
00013
00014 using boost::regex;
00015 using boost::smatch;
00016
00017 parse_error::parse_error(int line_, std::string const& message_)
00018 : line(line_), message(message_) {}
00019
00020 config_file::config_file(std::string const& name)
00021 {
00022 try { read(name); }
00023 catch(...) {
00024 clear();
00025 throw;
00026 }
00027 }
00028
00029 void config_file::read(const std::string& name)
00030 {
00031 clear();
00032
00033 fstream file;
00034 file.open(name.c_str(), fstream::in);
00035 if (! file.is_open())
00036 throw not_found(name);
00037
00038 static const string
00039 regexp_header("^[[:blank:]]*"),
00040 regexp_trail("[[:blank:]]*(?:#.*)?$");
00041
00042 static regex
00043 rx_empty(regexp_header + regexp_trail),
00044 rx_name(regexp_header + "([[:alnum:]_-]+)([^#]*)" + regexp_trail),
00045 rx_attribute(regexp_header + ":[[:blank:]]*([^#]+)" + regexp_trail),
00046 rx_open_bracket(regexp_header + "\\{" + regexp_trail),
00047 rx_close_bracket(regexp_header + "\\}" + regexp_trail);
00048
00049 enum { Normal, FindBracket } mode;
00050 mode = Normal;
00051
00052 config_set* cur_set = this;
00053
00054 int line_number = 1;
00055 stringbuf linebuf;
00056 const string empty_string;
00057 while (! file.eof())
00058 {
00059 while (file.peek() == '\n')
00060 {
00061 ++line_number;
00062 file.ignore();
00063 }
00064
00065 file.get(linebuf);
00066 const string line(linebuf.str());
00067 linebuf.str(empty_string);
00068
00069 smatch result;
00070 if (regex_match(line, rx_empty)) continue;
00071
00072 if (mode == FindBracket)
00073 {
00074 if (! regex_match(line, rx_open_bracket))
00075 throw parse_error(line_number, "expected '{', found " + line);
00076
00077 mode = Normal;
00078 }
00079 else if (regex_match(line, result, rx_name))
00080 {
00081 string key = result[1];
00082 string value = result[2];
00083
00084 smatch attribute_value;
00085
00086 if (value.empty()
00087 || regex_match(value, rx_open_bracket))
00088 {
00089 mode = value.empty() ? FindBracket : Normal;
00090
00091 config_set* new_set = new config_set(cur_set);
00092 cur_set->insert( key, new_set );
00093 cur_set = new_set;
00094 }
00095 else if (regex_match(value, attribute_value, rx_attribute))
00096 cur_set->insert( key, attribute_value[1] );
00097 else
00098 throw parse_error(line_number, "expected '" + key + ": value', found " + key + value);
00099 }
00100 else if (regex_match(line, rx_close_bracket))
00101 {
00102 if (cur_set -> parent() == 0)
00103 throw parse_error(line_number, "unmatched bracket");
00104 cur_set = cur_set->parent();
00105 }
00106 else
00107 throw parse_error(line_number, "expected \"key: value\", found " + line);
00108 }
00109
00110 if (mode == FindBracket)
00111 throw parse_error(line_number, "expected '{', got end of file");
00112 else if (cur_set -> parent())
00113 throw parse_error(line_number, "expected '}' before end of file");
00114 }
00115