Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

configuration.C

Go to the documentation of this file.
00001 // $Id: configuration_C-source.html,v 1.1 2001/04/16 17:42:57 dvermeir Exp $
00002 #include <string>
00003 #include <algorithm>
00004 #include <stdlib.h> // for strtol()
00005 #include "configuration.h"
00006 #include "datepattern.h"
00007 #include "path.h"
00008 #include "domain.h"
00009 
00010 Configuration::Configuration(): format_(NONE), max_level_(0), select_(0) {
00011 }
00012 
00013 Configuration::~Configuration() {
00014 delete select_;
00015 }
00016 
00017 void
00018 Configuration::add_expression(Expression* e) {
00019 if (e) {
00020   if (!select_)
00021     select_ = new AndExpression();
00022   select_->add(e);
00023   }
00024 }
00025 
00026 unsigned int
00027 Configuration::parse(istream& is) {
00028 string  word; // first word on the line
00029 bool    ok(true);
00030 criteria_.clear();
00031 unsigned int lineno(1);
00032 while (is >> word) { // while we can read the first word of a line
00033   if (word.size() && word[0]=='#') { // comment, just skip until the end of the line
00034     string junk;
00035     getline(is,junk);
00036     }
00037   else if (word=="format") {
00038     if (format_!=NONE) // a format_ is already there
00039       return lineno;
00040     ok = parse_format(is);
00041     }
00042   else if (word=="select")
00043     ok = parse_select(is);
00044   else if (word=="exclude")
00045     ok = parse_exclude(is);
00046   else
00047     return lineno;
00048   if (!ok)
00049     return lineno;
00050   ++lineno;
00051   }
00052 return 0;
00053 }
00054 
00055 bool
00056 Configuration::parse_format(istream& is) {
00057 format_ = parse_criterium(is);
00058 if (format_ == NONE)
00059   return false;
00060 criteria_.insert(format_);
00061 if (parse_levels(is,levels_))  {
00062   if (levels_.size()==0) { // insert default
00063     levels_.insert(1);
00064     levels_.insert(2);
00065     levels_.insert(3);
00066     }
00067   // compute max_level_
00068   max_level_ = *(max_element(levels_.begin(),levels_.end()));
00069   }
00070 return true;
00071 }
00072 
00073 bool
00074 Configuration::parse_select(istream& is) {
00075 Expression* e(parse_expression(is));
00076 if (e) {
00077   add_expression(e);
00078   return true;
00079   }
00080 return false;
00081 }
00082 
00083 
00084 Expression*
00085 Configuration::parse_expression(istream& is) {
00086 CRITERIUM crit = parse_criterium(is);
00087 if (crit == NONE)
00088   return false;
00089 criteria_.insert(crit);
00090 string pattern; // rest of line
00091 if (!getline(is,pattern))
00092   return false;
00093 // remove leading blanks or tabs
00094 if (pattern.size()) { // remove leading and trailing blanks and tabs
00095   string::size_type n0(pattern.find_first_not_of(" \t"));
00096   if (n0)
00097     pattern.erase(0,n0);
00098   if (pattern.size()) {
00099     string::size_type n1(pattern.find_last_not_of(" \t"));
00100     if (n1<(pattern.size()-1)) 
00101       pattern.erase(n1+1);
00102     }
00103   }
00104 if (pattern.size()==0)
00105   return false;
00106 switch (crit) {
00107   case DATE: {
00108     DatePattern dp;
00109     if (!dp.parse(pattern))
00110       return false;
00111     return new DateExpression(dp);
00112     }
00113     break;
00114   case DOMAIN: {
00115     Domain d;
00116     if (!d.parse(pattern))
00117       return false;
00118     return new DomainExpression(d);
00119     }
00120     break;
00121   case PATH: {
00122     Path p;
00123     if (!p.parse(pattern))
00124       return false;
00125     return new PathExpression(p);
00126     }
00127     break;
00128   default: return false;
00129   }
00130 }
00131 
00132 bool
00133 Configuration::parse_exclude(istream& is) {
00134 Expression* e(parse_expression(is));
00135 if (e) {
00136   add_expression(new NotExpression(e));
00137   return true;
00138   }
00139 return false;
00140 }
00141 
00142 Configuration::CRITERIUM
00143 Configuration::parse_criterium(istream& is) {
00144 string word;
00145 if (is >> word) {
00146   if (word=="path")
00147     return PATH;
00148   else if (word=="date")
00149     return DATE;
00150   else if (word=="domain")
00151     return DOMAIN;
00152   else 
00153     return NONE;
00154   }
00155 return NONE;
00156 }
00157 
00158 bool
00159 Configuration::parse_levels(istream& is,set<unsigned int>& levels) {
00160 levels.clear();
00161 string line;
00162 if (!getline(is,line))
00163   return false;
00164 const char* cline(line.c_str());
00165 const char* start(0);
00166 // The const_cast is needed because strtol's 3rd is wrongly types as char**.
00167 char* end(const_cast<char*>(cline));
00168 
00169 while (start!=end) {
00170   start = end;
00171   long l = strtol(start,&end,10);
00172   if (start!=end) {
00173     if (l<0)
00174       return false;
00175     unsigned int u1(static_cast<unsigned int>(l));
00176     levels.insert(u1);
00177     if (*end=='-') { // a range like 1-4
00178       start = end+1;
00179       if (*start=='\0') // syntax error: something like '1-'
00180         return false;
00181       long l2 = strtol(start,&end,10);
00182       if (start==end) // syntax error: something like '1-asda'
00183         return false;
00184       if (l2<0)
00185         return false;
00186       unsigned int u2(static_cast<unsigned int>(l2));
00187       for (unsigned int u=u1+1; u<=u2; ++u) 
00188         levels.insert(u);
00189       }
00190     }
00191   }
00192 return true;
00193 }
00194 
00195 ostream&
00196 operator<<(ostream& os,const Configuration& conf) {
00197 os << "format " <<  conf.format() << " ";
00198 copy(conf.levels().begin(),conf.levels().end(),ostream_iterator<unsigned int>(os," "));
00199 os << "\n";
00200 if (conf.select()) 
00201   os << *(conf.select());
00202 return os;
00203 }
00204 
00205 ostream&
00206 operator<<(ostream& os,const Configuration::CRITERIUM& c) {
00207 switch (c) {
00208   case Configuration::DATE: os << "date"; break;
00209   case Configuration::DOMAIN: os << "domain"; break;
00210   case Configuration::PATH: os << "path"; break;
00211   case Configuration::NONE: os << "none"; break;
00212   default: os << "ERROR!!!"; break;
00213   }
00214 return os;
00215 }

httpstats-stage04 [ 7 April, 2001]