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 
00188         const string& getRulelist (void) {
00189                 return rulelist;
00190         }
00191 
00203         int matches(const char *newsgroup) const {
00204                 char c;
00205                 int j, clen, bmlen = 0, bmrej = 0;
00206                 int rejrule = 0;
00207 
00208                  j = 0;
00209                 do {
00210                         clen = 0;
00211                         if (c_rulelist[j] == '!') {
00212                                 j++;
00213                                 rejrule = 1;
00214                         } else {
00215                                 rejrule = 0;
00216                         }
00217                         while ((c = c_rulelist[j]) && c == newsgroup[clen]) {
00218                                 clen++;
00219                                 j++;
00220                         }
00221 
00222                         switch (c) {
00223                         case ',':
00224                         case '\0':
00225                                 if (newsgroup[clen] != '\0'
00226                                     && !isspace(newsgroup[clen])) {
00227                                         clen = -2;
00228                                 }
00229                                 clen++;
00230                                 break;
00231                         case '*':
00232                                 clen++;
00233                                 break;
00234                         default:
00235                                 clen = -1;
00236                                 break;
00237                         }
00238 
00239                         if (clen > bmlen) {
00240                                 bmlen = clen;
00241                                 bmrej = rejrule;
00242                         }
00243 
00244                         while (c && c != ',') {
00245                                 j++;
00246                                 c = c_rulelist[j];
00247                         }
00248                         j++;
00249                 } while (c);
00250 
00251                 if (bmrej) {
00252                         return -bmlen;
00253                 } else if (!WildmatSearch) {
00254                         return bmlen;
00255                 } else {
00256                         return (wildmat(newsgroup, Wildmat.c_str())? (1)
00257                                 : (0));
00258                 }
00259                 //return bmrej?-bmlen:bmlen;
00260         }
00261 
00270         NewsgroupFilter & operator|=(const NewsgroupFilter & filter2) {
00271                 string new_rulelist;
00272                 RuleIterator begin, end;
00273                 const char *grp;
00274 
00275                 begin = this->begin();
00276                 end = this->end();
00277                 while (begin != end) {
00278                         // copy all accept rules
00279                         // copy reject rules also rejected by filter2
00280                         if ((grp = *begin)[0] != '!'
00281                             || filter2.matches(grp + 1) <= 0) {
00282                                 add_rule_to_rulelist(new_rulelist, grp);
00283                         }
00284                         ++begin;
00285                 }
00286 
00287                 begin = filter2.begin();
00288                 end = filter2.end();
00289                 while (begin != end) {
00290                         // do not copy accept/reject rules of filter2 accepted by this filter
00291                         if ((grp = *begin)[0] != '!') {
00292                                 if (matches(grp) <= 0) {
00293                                         add_rule_to_rulelist(new_rulelist,
00294                                                              grp);
00295                                 }
00296                         } else if (matches(grp + 1) <= 0) {
00297                                 add_rule_to_rulelist(new_rulelist, grp);
00298                         }
00299                         ++begin;
00300                 }
00301 
00302                 long l;
00303                 if ((l = new_rulelist.length()) > 0) {
00304                         new_rulelist.replace(l - 1, l, "");
00305                 }
00306                 rulelist = new_rulelist;
00307                 c_rulelist = rulelist.c_str();
00308                 return *this;
00309         }
00310 
00319         NewsgroupFilter & operator&=(const NewsgroupFilter & filter2) {
00320                 string new_rulelist;
00321                 RuleIterator begin, end;
00322                 const char *grp;
00323 
00324                 begin = this->begin();
00325                 end = this->end();
00326                 while (begin != end) {
00327                         // copy all reject rules
00328                         // copy accept rules not rejected by filter2
00329                         if ((grp = *begin)[0] == '!'
00330                             || filter2.matches(grp) > 0) {
00331                                 add_rule_to_rulelist(new_rulelist, grp);
00332                         }
00333                         ++begin;
00334                 }
00335 
00336                 begin = filter2.begin();
00337                 end = filter2.end();
00338                 while (begin != end) {
00339                         // do not add positive/negative rules already rejected
00340                         if ((grp = *begin)[0] != '!') {
00341                                 if (matches(grp) > 0) {
00342                                         add_rule_to_rulelist(new_rulelist,
00343                                                              grp);
00344                                 }
00345                         } else if (matches(grp + 1) > 0) {
00346                                 add_rule_to_rulelist(new_rulelist, grp);
00347                         }
00348                         ++begin;
00349                 }
00350 
00351                 long l;
00352                 if ((l = new_rulelist.length()) > 0) {
00353                         new_rulelist.replace(l - 1, l, "");
00354                 }
00355                 rulelist = new_rulelist;
00356                 c_rulelist = rulelist.c_str();
00357                 return *this;
00358         }
00359 
00360         friend std::ostream & operator <<(std::ostream & os,
00361                                           const NewsgroupFilter & f) {
00362                 os << f.rulelist;
00363                 return os;
00364         }
00365 };
00366 
00367 #endif

Generated on Sun Oct 24 21:08:18 2004 for NewsCache by doxygen 1.3.6-20040222