00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef MATCHER_H
00017 #define MATCHER_H
00018
00019 #ifndef USE_PCH
00020 #include <string>
00021 #include <boost/shared_ptr.hpp>
00022 #include <boost/noncopyable.hpp>
00023 #include <libcw/events.h>
00024 #include <sys/types.h>
00025 #include <regex.h>
00026 #include "debug.h"
00027 #endif
00028
00029 #include "match.h"
00030 #include "MessageIn.h"
00031 #include "Counter.h"
00032
00033
00034 enum match0_type {
00035
00036 anystring_mt = 0,
00037 nonemptystring_mt = 1,
00038 anyglobalchannel_mt = 2,
00039 anylocalchannel_mt = 3,
00040 anychannel_mt = 4,
00041 anyserver_mt = 5,
00042 anynick_mt = 6,
00043 mynick_mt = 8,
00044 localserver_mt = 9
00045 };
00046
00047
00048 enum match1_type {
00049
00050 exactmatch_mt = 7,
00051 wildcard_mt = 10,
00052 regexp_mt = 11
00053 };
00054
00055 #ifdef CWDEBUG
00056 extern std::ostream& operator<<(std::ostream& os, match0_type mt);
00057 extern std::ostream& operator<<(std::ostream& os, match1_type mt);
00058 #endif
00059
00060 static int const prefix = -1;
00061
00062
00063 class Matcher {
00064 private:
00065 int M_param;
00066 bool M_single_param;
00067
00068 public:
00069
00070 Matcher(int param, bool single_param) : M_param(param), M_single_param(single_param) { }
00071
00072 virtual ~Matcher() { }
00073
00074
00075
00076 static boost::shared_ptr<Matcher> create(int param, match0_type mt, bool single_param = true);
00077
00078
00079 static boost::shared_ptr<Matcher> create(int param, match1_type mt, std::string const& arg, bool single_param = true);
00080
00081
00082 bool match(ServerMessageIn const& msg);
00083
00084 #ifdef CWDEBUG
00085 virtual void print_type_on(std::ostream&) const = 0;
00086
00087 virtual void print_on(std::ostream& os) const
00088 {
00089 os << "param:";
00090 if (M_param == prefix)
00091 os << "prefix";
00092 else
00093 os << M_param;
00094 os << ", single_param:" << (M_single_param ? "true" : "false");
00095 }
00096 #endif
00097
00098 protected:
00099
00100
00101 virtual bool match_impl(ServerSession const& server_session, char const* start, size_t len) = 0;
00102
00103 public:
00104
00105 virtual int sort_value(void) = 0;
00106 };
00107
00108
00109
00110 class Matcher_noarg : public Matcher {
00111 protected:
00112 match0_type M_mt;
00113
00114 public:
00115
00116 Matcher_noarg(int param, match0_type mt, bool single_param) : Matcher(param, single_param), M_mt(mt) { }
00117
00118 #ifdef CWDEBUG
00119
00120 virtual void print_type_on(std::ostream& os) const { os << "Matcher_noarg"; }
00121
00122 virtual void print_on(std::ostream& os) const { os << "mt:" << M_mt; }
00123 #endif
00124
00125 protected:
00126 virtual bool match_impl(ServerSession const& server_session, char const* start, size_t len);
00127
00128 public:
00129
00130 virtual int sort_value(void) { return M_mt; }
00131 };
00132
00133
00134 class Matcher_matchcomp : public Matcher {
00135 private:
00136 char* M_cmask;
00137 int M_minlen;
00138
00139 public:
00140
00141 Matcher_matchcomp(int param, std::string const& arg, bool single_param) :
00142 Matcher(param, single_param), M_cmask(new char[arg.size() + 1])
00143 { AllocTag(M_cmask, "Matcher_matchcomp::M_cmask"); matchcomp(M_cmask, &M_minlen, NULL, arg.c_str()); }
00144
00145 ~Matcher_matchcomp() { delete [] M_cmask; }
00146
00147 #ifdef CWDEBUG
00148
00149 virtual void print_type_on(std::ostream& os) const { os << "Matcher_matchcomp"; }
00150
00151 virtual void print_on(std::ostream& os) const
00152 { os << "cmask: \"" << M_cmask << "\", minlen: " << M_minlen; }
00153 #endif
00154
00155 protected:
00156
00157
00158 virtual bool match_impl(ServerSession const& LIBCW_UNUSED(server_session), char const* start, size_t len)
00159 { return len >= (size_t)M_minlen && matchexec(start, len, M_cmask, M_minlen) == 0; }
00160
00161 public:
00162
00163 virtual int sort_value(void) { return wildcard_mt; }
00164 };
00165
00166
00167 class Matcher_regexp : public Matcher {
00168 private:
00169 regex_t M_regex;
00170
00171 public:
00172
00173 Matcher_regexp(int param, std::string const& arg, bool single_param) :
00174 Matcher(param, single_param)
00175 {
00176 #if defined(CWDEBUG) || defined(DEBUG)
00177 int regcomp_error =
00178 #endif
00179 regcomp(&M_regex, arg.c_str(), REG_ICASE | REG_NOSUB);
00180 ASSERT(regcomp_error == 0); }
00181
00182 ~Matcher_regexp() { regfree(&M_regex); }
00183
00184 #ifdef CWDEBUG
00185
00186 virtual void print_type_on(std::ostream& os) const { os << "Matcher_regexp"; }
00187
00188 virtual void print_on(std::ostream& os) const { os << "regex: " << M_regex; }
00189 #endif
00190
00191 protected:
00192 virtual bool match_impl(ServerSession const& server_session, char const* start, size_t len);
00193
00194 public:
00195
00196 virtual int sort_value(void) { return regexp_mt; }
00197 };
00198
00199
00200 class Matcher_exactmatch : public Matcher {
00201 private:
00202 std::string M_string;
00203
00204 public:
00205
00206 Matcher_exactmatch(int param, std::string const& arg, bool single_param) :
00207 Matcher(param, single_param), M_string(arg) { }
00208
00209 #ifdef CWDEBUG
00210
00211 virtual void print_type_on(std::ostream& os) const { os << "Matcher_exactmatch"; }
00212
00213 virtual void print_on(std::ostream& os) const { os << "string: \"" << M_string << '"'; }
00214 #endif
00215
00216 protected:
00217
00218
00219 virtual bool match_impl(ServerSession const& LIBCW_UNUSED(server_session), char const* start, size_t len)
00220 { return M_string.compare(0, std::string::npos, start, len) == 0; }
00221
00222 public:
00223
00224 virtual int sort_value(void) { return exactmatch_mt; }
00225 };
00226
00227
00228 inline boost::shared_ptr<Matcher> Matcher::create(int param, match0_type mt, bool single_param)
00229 {
00230 return boost::shared_ptr<Matcher>(NEW(Matcher_noarg(param, mt, single_param)));
00231 }
00232
00233
00234 inline bool operator<(boost::shared_ptr<Matcher> const& matcher1, boost::shared_ptr<Matcher> const& matcher2)
00235 {
00236 return matcher1->sort_value() < matcher2->sort_value();
00237 }
00238
00239
00240 struct MatchRequestList :public boost::noncopyable {
00241 int M_command;
00242 std::multiset<boost::shared_ptr<Matcher> > M_conditions;
00243
00244
00245 MatchRequestList(void) : M_command(-2) { }
00246
00247
00248 bool is_match(ServerMessageIn const& msg) const
00249 {
00250 ASSERT(M_command != -2);
00251 if (M_command != msg.key())
00252 return false;
00253 return check_list(msg);
00254 }
00255
00256 private:
00257
00258 bool check_list(ServerMessageIn const& msg) const;
00259 };
00260
00261
00262 class MatchRequest {
00263 private:
00264 boost::shared_ptr<MatchRequestList> M_match_request_list;
00265 bool M_sink;
00266 public:
00267
00268 MatchRequest(bool sink = false) : M_match_request_list(NEW(MatchRequestList)), M_sink(sink) { }
00269 bool sink(void) const { return M_sink; }
00270
00271 MatchRequest& operator()(int command)
00272 {
00273 M_match_request_list->M_conditions.clear();
00274 M_match_request_list->M_command = command;
00275 return *this;
00276 }
00277
00278 MatchRequest& anystring(int param, bool single_param = true)
00279 {
00280 M_match_request_list->M_conditions.insert(Matcher::create(param, anystring_mt, single_param));
00281 return *this;
00282 }
00283
00284 MatchRequest& nonemptystring(int param, bool single_param = true)
00285 {
00286 M_match_request_list->M_conditions.insert(Matcher::create(param, nonemptystring_mt, single_param));
00287 return *this;
00288 }
00289
00290 MatchRequest& anyserver(int param)
00291 {
00292 M_match_request_list->M_conditions.insert(Matcher::create(param, anyserver_mt, true));
00293 return *this;
00294 }
00295
00296 MatchRequest& localserver(int param)
00297 {
00298 M_match_request_list->M_conditions.insert(Matcher::create(param, localserver_mt, true));
00299 return *this;
00300 }
00301
00302 MatchRequest& anynick(int param)
00303 {
00304 M_match_request_list->M_conditions.insert(Matcher::create(param, anynick_mt, true));
00305 return *this;
00306 }
00307
00308 MatchRequest& mynick(int param)
00309 {
00310 M_match_request_list->M_conditions.insert(Matcher::create(param, mynick_mt, true));
00311 return *this;
00312 }
00313
00314 MatchRequest& anychannel(int param)
00315 {
00316 M_match_request_list->M_conditions.insert(Matcher::create(param, anychannel_mt, true));
00317 return *this;
00318 }
00319
00320 MatchRequest& anyglobalchannel(int param)
00321 {
00322 M_match_request_list->M_conditions.insert(Matcher::create(param, anyglobalchannel_mt, true));
00323 return *this;
00324 }
00325
00326 MatchRequest& anylocalchannel(int param)
00327 {
00328 M_match_request_list->M_conditions.insert(Matcher::create(param, anylocalchannel_mt, true));
00329 return *this;
00330 }
00331
00332 MatchRequest& wildcard(std::string const& arg, int param, bool single_param = true)
00333 {
00334 M_match_request_list->M_conditions.insert(Matcher::create(param, wildcard_mt, arg, single_param));
00335 return *this;
00336 }
00337
00338 MatchRequest& regexp(std::string const& arg, int param, bool single_param = true)
00339 {
00340 M_match_request_list->M_conditions.insert(Matcher::create(param, regexp_mt, arg, single_param));
00341 return *this;
00342 }
00343
00344 MatchRequest& exactmatch(std::string const& arg, int param, bool single_param = true)
00345 {
00346 M_match_request_list->M_conditions.insert(Matcher::create(param, exactmatch_mt, arg, single_param));
00347 return *this;
00348 }
00349
00350 bool is_match(ServerMessageIn const& msg) const { return M_match_request_list->is_match(msg); }
00351 #ifdef CWDEBUG
00352
00353 MatchRequestList const& match_request_list(void) const { return *M_match_request_list; }
00354 #endif
00355 };
00356
00357
00358 class MatcherEventType {
00359 private:
00360 ServerMessageIn const& M_message;
00361
00362 public:
00363
00364 MatcherEventType(ServerMessageIn const& message) : M_message(message) { }
00365
00366
00367 ServerMessageIn const& message(void) const { return M_message; }
00368 };
00369
00370
00371 class MatcherEventRequestBase : public event_request_base_tct<MatcherEventType> {
00372 public:
00373 typedef MatchRequest event_request_data_ct;
00374 private:
00375 event_request_data_ct M_request_data;
00376 public:
00377
00378 MatcherEventRequestBase(event_client_tracker_ct* event_client_tracker, event_request_data_ct request_data) :
00379 event_request_base_tct<MatcherEventType>(event_client_tracker), M_request_data(request_data)
00380 { Dout(dc::objects, "Constructing MatcherEventRequestBase(" << request_data << ")"); }
00381 #ifdef CWDEBUG
00382
00383 ~MatcherEventRequestBase() { Dout(dc::objects, "Destructing MatcherEventRequestBase " << *this); }
00384
00385 MatcherEventRequestBase(MatcherEventRequestBase const& request) :
00386 event_request_base_tct<MatcherEventType>(request),
00387 M_request_data(request.M_request_data)
00388 { Dout(dc::objects, "Copy-constructing MatcherEventRequestBase from " << request); }
00389 #endif
00390
00391 event_request_data_ct const& request_data(void) const { return M_request_data; }
00392
00393
00394 friend std::ostream& operator<<(std::ostream& os, MatcherEventRequestBase const& request);
00395 };
00396
00397
00398 class MatcherEventRequestQueue {
00399 typedef std::deque<MatcherEventRequestBase*> event_requests_ct;
00400 private:
00401 Counter M_event_requests_locked;
00402 event_requests_ct M_event_requests;
00403 event_requests_ct M_event_requests_tmp;
00404 protected:
00405
00406 void add_request(MatcherEventRequestBase* request)
00407 {
00408 if (M_event_requests_locked)
00409 M_event_requests_tmp.push_back(request);
00410 else
00411 M_event_requests.push_back(request);
00412 }
00413
00414 ~MatcherEventRequestQueue() { destroy_requests(); }
00415 public:
00416
00417 void destroy_requests(void);
00418
00419 bool trigger(MatcherEventRequestBase::event_type_ct const& event_type);
00420 };
00421
00422
00423 typedef event_data_server_tct<MatcherEventRequestBase, MatcherEventRequestQueue> MatcherEventServer;
00424
00425 #endif // MATCHER_H