configfile.cc
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 


utilmm
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:31