00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012 #ifndef FILTER_UTILS_H_INCLUDED
00013 #error dirstream.filterutils - Do not include this file directly! Include fiter_utils.h instead.
00014 #endif
00015 #ifndef FILTER_UTILS_IMPL_H_INCLUDED
00016 #define FILTER_UTILS_IMPL_H_INCLUDED
00017 #include "../smartpointer.h"
00018 #include "../filter_base.h"
00019 #include "filter_asserter.h"
00020 #include <memory>
00021 namespace dirstr { namespace detail {
00023
00025 struct and_op
00026 {
00027 template <class F1, class F2>
00028 bool operator()(const F1& f1, const F2& f2, const std::string& str) const
00029 {
00030 return (f1(str) != 0) && (f2(str) != 0);
00031 }
00032 };
00033 struct or_op
00034 {
00035 template <class F1, class F2>
00036 bool operator()(const F1& f1, const F2& f2, const std::string& str) const
00037 {
00038 return (f1(str) != 0) || (f2(str) != 0);
00039 }
00040 };
00041 struct xor_op
00042 {
00043 template <class F1, class F2>
00044 bool operator()(const F1& f1, const F2& f2, const std::string& str) const
00045 {
00046 return (f1(str) != 0) ^ (f2(str) != 0);
00047 }
00048 };
00049
00051
00053 #if defined(_MSC_VER) && _MSC_VER <= 1200
00054 template <class Op1, class Op2>
00055 struct assert_equal_op
00056 {
00057 template <bool b> struct operation_types_not_equal;
00058 template <> struct operation_types_not_equal<true> {typedef int type;};
00059 static char test(const Op1&);
00060 static char (&test(...))[2];
00061 enum {result = sizeof(test(Op2()))};
00062 typedef operation_types_not_equal<result == 1>::type type;
00063 };
00064 #endif
00065 template <class F1, class F2, class Op> struct expr_binary_v;
00066 template <class F1, class F2, class Op> struct expr_binary_s;
00067 template <class F> struct expr_not_v;
00068 template <class F> struct expr_not_s;
00069
00070
00071 struct ptr_checker
00072 {
00073 public:
00074 static char (&test(const volatile dirstr::filter_base*))[2];
00075 static char (&test(const volatile void*))[6];
00076 };
00077
00078 template <int> struct expr_traits_impl;
00079 struct expr_traits_types
00080 {
00081 enum {
00082 filter = sizeof(char),
00083 ptr_filter_base = sizeof(char[2]),
00084 shared_ptr_filter_base = sizeof(char[3]),
00085 shared_ptr_other = sizeof(char[4]),
00086 expression = sizeof(char[5]),
00087 ptr_other = sizeof(char[6]),
00088 shared_ptr_select = sizeof(char[99]),
00089 ptr_select = sizeof(char[100])
00090 };
00091 };
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 template <>
00106 struct expr_traits_impl<expr_traits_types::filter>
00107 {
00108 template <class T>
00109 struct in : assert_is_filter<T>
00110 {
00111 typedef T copy_type;
00112 typedef const T& ref_t;
00113 static const T& transform(const T& t) {return t;}
00114 static const T& filter_obj(const T& t)
00115 {
00116 return t;
00117 }
00118 };
00119 };
00120
00121
00122
00123
00124 template <>
00125 struct expr_traits_impl<expr_traits_types::ptr_filter_base>
00126 {
00127 template <class T>
00128 struct in
00129 {
00130 typedef T ref_t;
00131 typedef SharedPtr<dirstr::filter_base> copy_type;
00132 static copy_type transform(const T& t)
00133 {
00134 return SharedPtr<dirstr::filter_base>(t->clone());
00135 }
00136 static const filter_base& filter_obj(filter_base* t)
00137 {
00138 return *t;
00139 }
00140 };
00141 enum {is_filter = 1};
00142 };
00143
00144
00145
00146
00147
00148 template <>
00149 struct expr_traits_impl<expr_traits_types::ptr_other>
00150 {
00151 template <class T>
00152 struct in : assert_is_filter<typename T::PLAIN_POINTER_NOT_SUPPORTED>
00153 {
00154
00155 };
00156 };
00157
00158
00159
00160 template <>
00161 struct expr_traits_impl<expr_traits_types::shared_ptr_filter_base>
00162 {
00163 template <class T>
00164 struct in
00165 {
00166 typedef T ref_t;
00167 typedef T copy_type;
00168 static copy_type transform(const T& t)
00169 {
00170 return copy_type(t->clone());
00171 }
00172 };
00173 };
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 template <>
00186 struct expr_traits_impl<expr_traits_types::shared_ptr_other>
00187 {
00188 template <class T>
00189 struct in
00190 {
00191 typedef T ref_t;
00192 typedef typename T::VT VT;
00193 typedef T copy_type;
00194 static copy_type transform(const T& t)
00195 {
00196 enum {r = assert_is_filter<VT>::T_IS_NOT_A_VALID_FILTER};
00197 return copy_type(new VT(*t));
00198 }
00199 };
00200 };
00201
00202
00203
00204
00205
00206 template <>
00207 struct expr_traits_impl<expr_traits_types::shared_ptr_select>
00208 {
00209 template <class T>
00210 struct in
00211 {
00212 private:
00213 typedef typename T::PT PT;
00214 typedef typename T::VT VT;
00215 enum {temp = sizeof( ptr_checker::test( (PT)0 ) ) };
00216 enum {result = temp == (unsigned) expr_traits_types::ptr_filter_base ?
00217 expr_traits_types::shared_ptr_filter_base
00218 : expr_traits_types::shared_ptr_other
00219 };
00220 public:
00221 typedef T copy_type;
00222 typedef T ref_t;
00223 static copy_type transform(const T& t)
00224 {
00225 return expr_traits_impl<result>::template in<T>::transform(t);
00226 }
00227 static const VT& filter_obj(const T& t)
00228 {
00229 return *t;
00230 }
00231 };
00232 };
00233
00234
00235
00236
00237
00238 template <>
00239 struct expr_traits_impl<expr_traits_types::ptr_select>
00240 {
00241 template <class T>
00242 struct in
00243 {
00244 public:
00245 enum {result = sizeof( ptr_checker::test( (T)0 ) )};
00246 enum {PLAIN_POINTER_NOT_SUPPORTED = expr_traits_impl<result>::is_filter};
00247 typedef SharedPtr<dirstr::filter_base> copy_type;
00248 typedef T ref_t;
00249 static copy_type transform(const T& t)
00250 {
00251 return expr_traits_impl<result>::template in<T>::transform(t);
00252 }
00253 static const filter_base& filter_obj(const T& t)
00254 {
00255 return expr_traits_impl<result>::template in<T>::filter_obj(t);
00256 }
00257 };
00258 };
00259
00260
00261
00262
00263 template <>
00264 struct expr_traits_impl<expr_traits_types::expression>
00265 {
00266 template <class T>
00267 struct in
00268 {
00269 typedef T ref_t;
00270 typedef typename T::copy_type copy_type;
00271 static const T& transform(const T& t)
00272 {
00273 return t;
00274 }
00275 };
00276 };
00277
00278
00279 template <class T>
00280 struct impl_checker
00281 {
00282 struct A {};
00283 struct B : public A {};
00284 template <class E1, class E2, class Op>
00285 static char (&test(const expr_binary_v<E1, E2, Op>&, B))[5];
00286 template <class E>
00287 static char (&test(const expr_not_v<E>&, B))[5];
00288 template <class V>
00289 static char (&test(const SharedPtr<V>&, B))[99];
00290
00291 template <class Z>
00292 static char (&test(Z*, B))[100];
00293 template <class Z>
00294 static char test(Z z, A);
00295 template <class R, class A1>
00296 static char test( R (*)(A1), B);
00297 };
00298 template <class T>
00299 struct expr_traits_selector
00300 {
00301 public:
00302 enum {result = sizeof( impl_checker<T>::test( maker<T>::make_t(), impl_checker<T>::B() ) )};
00303 typedef typename expr_traits_impl<result>::template in<T> type;
00304 };
00305 template <class T>
00306 struct expr_traits : expr_traits_selector<T>::type
00307 {
00308 typedef typename dirstr::detail::expr_traits_selector<T>::type base_t;
00309 typedef typename base_t::copy_type copy_type;
00310 };
00311
00313
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 template <class F1, class F2, class Op>
00360 struct expr_binary_v
00361 {
00362 expr_binary_v(const F1& f1, const F2& f2)
00363 : f1_(f1)
00364 , f2_(f2)
00365 {}
00366
00367 typedef F1 left_type;
00368 typedef F2 right_type;
00369 typedef Op op_type;
00370 typedef typename expr_traits<F1>::copy_type copy_type_e1;
00371 typedef typename expr_traits<F2>::copy_type copy_type_e2;
00372 typedef expr_binary_s<copy_type_e1, copy_type_e2, Op> copy_type;
00373 typename expr_traits<F1>::ref_t f1_;
00374 typename expr_traits<F2>::ref_t f2_;
00375 };
00376
00377
00378 template <class F>
00379 struct expr_not_v
00380 {
00381 expr_not_v(const F& f1)
00382 : f_(f1)
00383 {}
00384 typedef F inner_type;
00385 typedef typename expr_traits<F>::copy_type copy_type_e;
00386 typedef expr_not_s<copy_type_e> copy_type;
00387 typename expr_traits<F>::ref_t f_;
00388 };
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 template <class F1, class F2, class Op>
00400 struct expr_binary_s
00401 {
00402 #if defined(_MSC_VER) && _MSC_VER <= 1200
00403
00404
00405
00406
00407
00408 template <class Exp>
00409 expr_binary_s(const Exp& e)
00410 : f1_(expr_traits<Exp::left_type>::transform(e.f1_))
00411 , f2_(expr_traits<Exp::right_type>::transform(e.f2_))
00412 {
00413 assert_equal_op<Op, Exp::op_type>::result;
00414 }
00415 #else
00416 template <class OF1, class OF2>
00417 expr_binary_s(const expr_binary_v<OF1, OF2, Op>& o)
00418 : f1_(expr_traits<OF1>::transform(o.f1_))
00419 , f2_(expr_traits<OF2>::transform(o.f2_))
00420 {}
00421 #endif
00422 expr_binary_s(const expr_binary_s& o)
00423 : f1_(expr_traits<F1>::transform(o.f1_))
00424 , f2_(expr_traits<F2>::transform(o.f2_))
00425 {}
00426
00427 bool operator()(const std::string& str) const
00428 {
00429 return Op()(expr_traits<F1>::filter_obj(f1_),
00430 expr_traits<F2>::filter_obj(f2_),
00431 str);
00432 }
00433 private:
00434 F1 f1_;
00435 F2 f2_;
00436 };
00437
00438
00439
00440 template <class F>
00441 struct expr_not_s
00442 {
00443 #if defined(_MSC_VER) && _MSC_VER <= 1200
00444 template <class Exp>
00445 expr_not_s(const Exp& e)
00446 : f_(expr_traits<Exp::inner_type>::transform(e.f_))
00447 {}
00448 #else
00449 template <class OF>
00450 expr_not_s(const expr_not_v<OF>& o)
00451 : f_(expr_traits<OF>::transform(o.f_))
00452 {}
00453 #endif
00454 expr_not_s(const expr_not_s& o)
00455 : f_(expr_traits<F>::transform(o.f_))
00456 {}
00457
00458 bool operator()(const std::string& str) const
00459 {
00460 return !expr_traits<F>::filter_obj(f_)(str);
00461 }
00462 private:
00463 F f_;
00464 };
00465
00466 template <class F>
00467 struct expr;
00468
00469
00470
00471 template <class Exp>
00472 class expr_f_t : public filter_base
00473 {
00474
00475 public:
00476 template <class OExp>
00477 expr_f_t(const detail::expr<OExp>& other)
00478 : exp_(detail::expr_traits<OExp>::transform(other.f_))
00479 {}
00480 public:
00481 expr_f_t(const expr_f_t& other)
00482 : exp_(detail::expr_traits<Exp>::transform(other.exp_))
00483 {}
00484
00485 bool operator()(const std::string& str) const
00486 {
00487 return detail::expr_traits<Exp>::filter_obj(exp_)(str);
00488 }
00489 filter_base* clone() const
00490 {
00491 return new expr_f_t(*this);
00492 }
00493 private:
00494 Exp exp_;
00495 };
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 template <class F>
00524 struct expr : public filter_base
00525 {
00526 public:
00527 expr(const F& f)
00528 : f_(f)
00529 {}
00530
00531 dirstr::filter_base* clone() const
00532 {
00533 typedef typename detail::expr_traits<F>::copy_type copy_type;
00534 return new dirstr::detail::expr_f_t<copy_type>(*this);
00535 }
00536
00537
00538 bool operator()(const std::string& str) const
00539 {
00540 std::auto_ptr<filter_base> f(this->clone());
00541 return (*f)(str);
00542 }
00543 typename detail::expr_traits<F>::ref_t f_;
00544 };
00545
00546
00547 } }
00548
00549 #endif