1 ///////////////////////////////////////////////////////////////////////////////
2 // chset.hpp
3 //
4 //  Copyright 2008 Eric Niebler. Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #ifndef BOOST_XPRESSIVE_DETAIL_CHSET_CHSET_HPP_EAN_10_04_2005
9 #define BOOST_XPRESSIVE_DETAIL_CHSET_CHSET_HPP_EAN_10_04_2005
10 
11 // MS compatible compilers support #pragma once
12 #if defined(_MSC_VER)
13 # pragma once
14 #endif
15 
16 #include <vector>
17 #include <boost/call_traits.hpp>
18 #include <boost/xpressive/detail/detail_fwd.hpp>
19 #include <boost/xpressive/detail/utility/algorithm.hpp>
20 #include <boost/xpressive/detail/utility/chset/basic_chset.ipp>
21 
22 namespace boost { namespace xpressive { namespace detail
23 {
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 // compound_charset
27 //
28 template<typename Traits>
29 struct compound_charset
30   : private basic_chset<typename Traits::char_type>
31 {
32     typedef typename Traits::char_type char_type;
33     typedef basic_chset<char_type> base_type;
34     typedef Traits traits_type;
35     typedef typename Traits::char_class_type char_class_type;
36 
compound_charsetboost::xpressive::detail::compound_charset37     compound_charset()
38       : base_type()
39       , complement_(false)
40       , has_posix_(false)
41       , posix_yes_()
42       , posix_no_()
43     {
44     }
45 
46     ///////////////////////////////////////////////////////////////////////////////
47     // accessors
baseboost::xpressive::detail::compound_charset48     basic_chset<char_type> const &base() const
49     {
50         return *this;
51     }
52 
is_invertedboost::xpressive::detail::compound_charset53     bool is_inverted() const
54     {
55         return this->complement_;
56     }
57 
posix_yesboost::xpressive::detail::compound_charset58     char_class_type posix_yes() const
59     {
60         return this->posix_yes_;
61     }
62 
posix_noboost::xpressive::detail::compound_charset63     std::vector<char_class_type> const &posix_no() const
64     {
65         return this->posix_no_;
66     }
67 
68     ///////////////////////////////////////////////////////////////////////////////
69     // complement
inverseboost::xpressive::detail::compound_charset70     void inverse()
71     {
72         this->complement_ = !this->complement_;
73     }
74 
75     ///////////////////////////////////////////////////////////////////////////////
76     // set
set_charboost::xpressive::detail::compound_charset77     void set_char(char_type ch, Traits const &tr, bool icase)
78     {
79         icase ? this->base_type::set(ch, tr) : this->base_type::set(ch);
80     }
81 
set_rangeboost::xpressive::detail::compound_charset82     void set_range(char_type from, char_type to, Traits const &tr, bool icase)
83     {
84         icase ? this->base_type::set(from, to, tr) : this->base_type::set(from, to);
85     }
86 
set_classboost::xpressive::detail::compound_charset87     void set_class(char_class_type const &m, bool no)
88     {
89         this->has_posix_ = true;
90 
91         if(no)
92         {
93             this->posix_no_.push_back(m);
94         }
95         else
96         {
97             this->posix_yes_ |= m;
98         }
99     }
100 
101     ///////////////////////////////////////////////////////////////////////////////
102     // test
103     template<typename ICase>
testboost::xpressive::detail::compound_charset104     bool test(char_type ch, Traits const &tr, ICase) const
105     {
106         return this->complement_ !=
107             (this->base_type::test(ch, tr, ICase()) ||
108             (this->has_posix_ && this->test_posix(ch, tr)));
109     }
110 
111 private:
112 
113     ///////////////////////////////////////////////////////////////////////////////
114     // not_posix_pred
115     struct not_posix_pred
116     {
117         char_type ch_;
118         Traits const *traits_ptr_;
119 
operator ()boost::xpressive::detail::compound_charset::not_posix_pred120         bool operator ()(typename call_traits<char_class_type>::param_type m) const
121         {
122             return !this->traits_ptr_->isctype(this->ch_, m);
123         }
124     };
125 
126     ///////////////////////////////////////////////////////////////////////////////
127     // test_posix
test_posixboost::xpressive::detail::compound_charset128     bool test_posix(char_type ch, Traits const &tr) const
129     {
130         not_posix_pred const pred = {ch, &tr};
131         return tr.isctype(ch, this->posix_yes_)
132             || any(this->posix_no_.begin(), this->posix_no_.end(), pred);
133     }
134 
135     bool complement_;
136     bool has_posix_;
137     char_class_type posix_yes_;
138     std::vector<char_class_type> posix_no_;
139 };
140 
141 
142 ///////////////////////////////////////////////////////////////////////////////
143 // helpers
144 template<typename Char, typename Traits>
set_char(compound_charset<Traits> & chset,Char ch,Traits const & tr,bool icase)145 inline void set_char(compound_charset<Traits> &chset, Char ch, Traits const &tr, bool icase)
146 {
147     chset.set_char(ch, tr, icase);
148 }
149 
150 template<typename Char, typename Traits>
set_range(compound_charset<Traits> & chset,Char from,Char to,Traits const & tr,bool icase)151 inline void set_range(compound_charset<Traits> &chset, Char from, Char to, Traits const &tr, bool icase)
152 {
153     chset.set_range(from, to, tr, icase);
154 }
155 
156 template<typename Traits>
set_class(compound_charset<Traits> & chset,typename Traits::char_class_type char_class,bool no,Traits const &)157 inline void set_class(compound_charset<Traits> &chset, typename Traits::char_class_type char_class, bool no, Traits const &)
158 {
159     chset.set_class(char_class, no);
160 }
161 
162 }}} // namespace boost::xpressive::detail
163 
164 #endif
165 
166