Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

NewsgroupFilter.h

Go to the documentation of this file.
00001 /*
00002  * Herbert Straub: February 2002
00003  *      add wildmat search in NewscacheFilter
00004 */
00005 #ifndef __NewsgroupFilter_h__
00006 #define __NewsgroupFilter_h__
00007 
00008 #include <string>
00009 
00010 #include "Newsgroup.h"
00011 #include "wildmat.h"
00012 
00019 class NewsgroupFilter {
00020       private:
00021         string rulelist;
00022         const char *c_rulelist;
00023         string Wildmat;
00024         int WildmatSearch;
00025 
00026         class RuleIterator {
00027                 const char *rulelist, *rulelistp;
00028                 char rule[1 + MAXNEWSGROUPNAMELEN];     // '!'+MAXNEWSGROUPNAMELEN
00029 
00030               public:
00031                 enum { iter_begin, iter_end };
00032 
00033                  RuleIterator():rulelist(NULL), rulelistp(NULL) {
00034                         rule[0] = '\0';
00035                 } RuleIterator(const char *rulelist, int pos)
00036                 :rulelist(rulelist) {
00037                         if (pos == iter_begin) {
00038                                 char *rulep = rule;
00039                                 char c;
00040                                  rulelistp = rulelist;
00041                                 while ((c = *rulelistp) && c != ',') {
00042                                         *rulep = c;
00043                                         ++rulelistp;
00044                                         ++rulep;
00045                                 } *rulep = '\0';
00046                         } else {
00047                                 rulelistp = NULL;
00048                         }
00049                 }
00050 
00051                 RuleIterator & operator++() {   //prefix
00052                         char *rulep = rule;
00053                         char c;
00054                         if (*rulelistp) {
00055                                 ++rulelistp;
00056                                 while ((c = *rulelistp) && c != ',') {
00057                                         *rulep = c;
00058                                         ++rulelistp;
00059                                         ++rulep;
00060                                 }
00061                                 *rulep = '\0';
00062                         } else {
00063                                 rulelistp = NULL;
00064                         }
00065 
00066                         return *this;
00067                 }
00068 
00069                 const char *operator*() {
00070                         return rule;
00071                 }
00072 
00073                 int operator==(const RuleIterator & iter2) {
00074                         return rulelistp == iter2.rulelistp;
00075                 }
00076 
00077                 int operator!=(const RuleIterator & iter2) {
00078                         return rulelistp != iter2.rulelistp;
00079                 }
00080 
00081                 const RuleIterator & operator=(const RuleIterator & iter2) {
00082                         rulelistp = iter2.rulelistp;
00083                         strcpy(rule, iter2.rule);
00084                         return *this;
00085                 }
00086         };
00087 
00094         void add_rule_to_rulelist(string & rulelist, const char *rule) {
00095                 const char *p = rulelist.c_str(), *q;
00096 
00097                 do {
00098                         q = rule;
00099                         while (*p == *q) {
00100                                 ++p;
00101                                 ++q;
00102                         }
00103                         if (*q == '\0' && (*p == '\0' || *p == ',')) {
00104                                 // current rule already contained in rulelist
00105                                 return;
00106                         }
00107                         while (*p && *p++ != ',');
00108                 } while (*p);
00109 
00110                 rulelist += rule;
00111                 rulelist += ',';
00112         }
00113 
00114         RuleIterator begin() const {
00115                 return RuleIterator(c_rulelist, RuleIterator::iter_begin);
00116         } RuleIterator end() const {
00117                 return RuleIterator(c_rulelist, RuleIterator::iter_end);
00118       } public:
00119          NewsgroupFilter():WildmatSearch(0) {
00120                 c_rulelist = rulelist.c_str();
00121         }
00122 
00128         NewsgroupFilter(const NewsgroupFilter & filter)
00129       :    rulelist(filter.rulelist), WildmatSearch(0) {
00130                 this->c_rulelist = this->rulelist.c_str();
00131         }
00132 
00140         NewsgroupFilter(const char *rulelist)
00141         :rulelist(rulelist), WildmatSearch(0) {
00142                 this->c_rulelist = this->rulelist.c_str();
00143         }
00144 
00145         NewsgroupFilter & operator=(const NewsgroupFilter & filter) {
00146                 this->rulelist = filter.rulelist;
00147                 this->c_rulelist = rulelist.c_str();
00148                 this->WildmatSearch = filter.WildmatSearch;
00149                 if (this->WildmatSearch) {
00150                         this->Wildmat = filter.Wildmat;
00151                 }
00152                 return *this;
00153         }
00154 
00155         NewsgroupFilter & operator=(const char *rulelist) {
00156                 this->rulelist = rulelist;
00157                 this->c_rulelist = this->rulelist.c_str();
00158                 return *this;
00159         }
00160 
00161         NewsgroupFilter & operator=(const string & rulelist) {
00162                 this->rulelist = rulelist;
00163                 this->c_rulelist = this->rulelist.c_str();
00164                 return *this;
00165         }
00166 
00167         int operator==(const char *rulelist) {
00168                 return this->rulelist == rulelist;
00169         }
00170 
00178         void setWildmat(const char *pWildmat) {
00179                 Wildmat = pWildmat;
00180                 WildmatSearch = 1;
00181         }
00182 
00189         const string& getRulelist (void) {
00190                 return rulelist;
00191         }
00192 
00204         int matches(const char *newsgroup) const {
00205                 char c;
00206                 int j, clen, bmlen = 0, bmrej = 0;
00207                 int rejrule = 0;
00208 
00209                  j = 0;
00210                 do {
00211                         clen = 0;
00212                         if (c_rulelist[j] == '!') {
00213                                 j++;
00214                                 rejrule = 1;
00215                         } else {
00216                                 rejrule = 0;
00217                         }
00218                         while ((c = c_rulelist[j]) && c == newsgroup[clen]) {
00219                                 clen++;
00220                                 j++;
00221                         }
00222 
00223                         switch (c) {
00224                         case ',':
00225                         case '\0':
00226                                 if (newsgroup[clen] != '\0'
00227                                     && !isspace(newsgroup[clen])) {
00228                                         clen = -2;
00229                                 }
00230                                 clen++;
00231                                 break;
00232                         case '*':
00233                                 clen++;
00234                                 break;
00235                         default:
00236                                 clen = -1;
00237                                 break;
00238                         }
00239 
00240                         if (clen > bmlen) {
00241                                 bmlen = clen;
00242                                 bmrej = rejrule;
00243                         }
00244 
00245                         while (c && c != ',') {
00246                                 j++;
00247                                 c = c_rulelist[j];
00248                         }
00249                         j++;
00250                 } while (c);
00251 
00252                 if (bmrej) {
00253                         return -bmlen;
00254                 } else if (!WildmatSearch) {
00255                         return bmlen;
00256                 } else {
00257                         return (wildmat(newsgroup, Wildmat.c_str())? (1)
00258                                 : (0));
00259                 }
00260                 //return bmrej?-bmlen:bmlen;
00261         }
00262 
00271         NewsgroupFilter & operator|=(const NewsgroupFilter & filter2) {
00272                 string new_rulelist;
00273                 RuleIterator begin, end;
00274                 const char *grp;
00275 
00276                 begin = this->begin();
00277                 end = this->end();
00278                 while (begin != end) {
00279                         // copy all accept rules
00280                         // copy reject rules also rejected by filter2
00281                         if ((grp = *begin)[0] != '!'
00282                             || filter2.matches(grp + 1) <= 0) {
00283                                 add_rule_to_rulelist(new_rulelist, grp);
00284                         }
00285                         ++begin;
00286                 }
00287 
00288                 begin = filter2.begin();
00289                 end = filter2.end();
00290                 while (begin != end) {
00291                         // do not copy accept/reject rules of filter2 accepted by this filter
00292                         if ((grp = *begin)[0] != '!') {
00293                                 if (matches(grp) <= 0) {
00294                                         add_rule_to_rulelist(new_rulelist,
00295                                                              grp);
00296                                 }
00297                         } else if (matches(grp + 1) <= 0) {
00298                                 add_rule_to_rulelist(new_rulelist, grp);
00299                         }
00300                         ++begin;
00301                 }
00302 
00303                 long l;
00304                 if ((l = new_rulelist.length()) > 0) {
00305                         new_rulelist.replace(l - 1, l, "");
00306                 }
00307                 rulelist = new_rulelist;
00308                 c_rulelist = rulelist.c_str();
00309                 return *this;
00310         }
00311 
00320         NewsgroupFilter & operator&=(const NewsgroupFilter & filter2) {
00321                 string new_rulelist;
00322                 RuleIterator begin, end;
00323                 const char *grp;
00324 
00325                 begin = this->begin();
00326                 end = this->end();
00327                 while (begin != end) {
00328                         // copy all reject rules
00329                         // copy accept rules not rejected by filter2
00330                         if ((grp = *begin)[0] == '!'
00331                             || filter2.matches(grp) > 0) {
00332                                 add_rule_to_rulelist(new_rulelist, grp);
00333                         }
00334                         ++begin;
00335                 }
00336 
00337                 begin = filter2.begin();
00338                 end = filter2.end();
00339                 while (begin != end) {
00340                         // do not add positive/negative rules already rejected
00341                         if ((grp = *begin)[0] != '!') {
00342                                 if (matches(grp) > 0) {
00343                                         add_rule_to_rulelist(new_rulelist,
00344                                                              grp);
00345                                 }
00346                         } else if (matches(grp + 1) > 0) {
00347                                 add_rule_to_rulelist(new_rulelist, grp);
00348                         }
00349                         ++begin;
00350                 }
00351 
00352                 long l;
00353                 if ((l = new_rulelist.length()) > 0) {
00354                         new_rulelist.replace(l - 1, l, "");
00355                 }
00356                 rulelist = new_rulelist;
00357                 c_rulelist = rulelist.c_str();
00358                 return *this;
00359         }
00360 
00361         friend std::ostream & operator <<(std::ostream & os,
00362                                           const NewsgroupFilter & f) {
00363                 os << f.rulelist;
00364                 return os;
00365         }
00366 };
00367 
00368 #endif

Generated on Fri Aug 20 10:58:07 2004 for NewsCache by doxygen 1.3.6-20040222