Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 // hash_peek_bitset.hpp
|
Chris@16
|
3 //
|
Chris@16
|
4 // Copyright 2008 Eric Niebler. Distributed under the Boost
|
Chris@16
|
5 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
|
Chris@16
|
9 #define BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
|
Chris@16
|
10
|
Chris@16
|
11 // MS compatible compilers support #pragma once
|
Chris@101
|
12 #if defined(_MSC_VER)
|
Chris@16
|
13 # pragma once
|
Chris@16
|
14 # pragma warning(push)
|
Chris@16
|
15 # pragma warning(disable : 4100) // unreferenced formal parameter
|
Chris@16
|
16 # pragma warning(disable : 4127) // conditional expression constant
|
Chris@16
|
17 #endif
|
Chris@16
|
18
|
Chris@16
|
19 #include <bitset>
|
Chris@16
|
20 #include <string> // for std::char_traits
|
Chris@16
|
21 #include <boost/xpressive/detail/utility/chset/basic_chset.ipp>
|
Chris@16
|
22
|
Chris@16
|
23 namespace boost { namespace xpressive { namespace detail
|
Chris@16
|
24 {
|
Chris@16
|
25
|
Chris@16
|
26 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
27 // hash_peek_bitset
|
Chris@16
|
28 //
|
Chris@16
|
29 template<typename Char>
|
Chris@16
|
30 struct hash_peek_bitset
|
Chris@16
|
31 {
|
Chris@16
|
32 typedef Char char_type;
|
Chris@16
|
33 typedef typename std::char_traits<char_type>::int_type int_type;
|
Chris@16
|
34
|
Chris@16
|
35 hash_peek_bitset()
|
Chris@16
|
36 : icase_(false)
|
Chris@16
|
37 , bset_()
|
Chris@16
|
38 {
|
Chris@16
|
39 }
|
Chris@16
|
40
|
Chris@16
|
41 std::size_t count() const
|
Chris@16
|
42 {
|
Chris@16
|
43 return this->bset_.count();
|
Chris@16
|
44 }
|
Chris@16
|
45
|
Chris@16
|
46 void set_all()
|
Chris@16
|
47 {
|
Chris@16
|
48 this->icase_ = false;
|
Chris@16
|
49 this->bset_.set();
|
Chris@16
|
50 }
|
Chris@16
|
51
|
Chris@16
|
52 template<typename Traits>
|
Chris@16
|
53 void set_char(char_type ch, bool icase, Traits const &tr)
|
Chris@16
|
54 {
|
Chris@16
|
55 if(this->test_icase_(icase))
|
Chris@16
|
56 {
|
Chris@16
|
57 ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
|
Chris@16
|
58 this->bset_.set(tr.hash(ch));
|
Chris@16
|
59 }
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 template<typename Traits>
|
Chris@16
|
63 void set_range(char_type from, char_type to, bool no, bool icase, Traits const &tr)
|
Chris@16
|
64 {
|
Chris@16
|
65 int_type ifrom = std::char_traits<char_type>::to_int_type(from);
|
Chris@16
|
66 int_type ito = std::char_traits<char_type>::to_int_type(to);
|
Chris@16
|
67 BOOST_ASSERT(ifrom <= ito);
|
Chris@16
|
68 // bound the computational complexity. BUGBUG could set the inverse range
|
Chris@16
|
69 if(no || 256 < (ito - ifrom))
|
Chris@16
|
70 {
|
Chris@16
|
71 this->set_all();
|
Chris@16
|
72 }
|
Chris@16
|
73 else if(this->test_icase_(icase))
|
Chris@16
|
74 {
|
Chris@16
|
75 for(int_type i = ifrom; i <= ito; ++i)
|
Chris@16
|
76 {
|
Chris@16
|
77 char_type ch = std::char_traits<char_type>::to_char_type(i);
|
Chris@16
|
78 ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
|
Chris@16
|
79 this->bset_.set(tr.hash(ch));
|
Chris@16
|
80 }
|
Chris@16
|
81 }
|
Chris@16
|
82 }
|
Chris@16
|
83
|
Chris@16
|
84 template<typename Traits>
|
Chris@16
|
85 void set_class(typename Traits::char_class_type char_class, bool no, Traits const &tr)
|
Chris@16
|
86 {
|
Chris@16
|
87 if(1 != sizeof(char_type))
|
Chris@16
|
88 {
|
Chris@16
|
89 // wide character set, no efficient way of filling in the bitset, so set them all to 1
|
Chris@16
|
90 this->set_all();
|
Chris@16
|
91 }
|
Chris@16
|
92 else
|
Chris@16
|
93 {
|
Chris@16
|
94 for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
|
Chris@16
|
95 {
|
Chris@16
|
96 char_type ch = std::char_traits<char_type>::to_char_type(static_cast<int_type>(i));
|
Chris@16
|
97 if(no != tr.isctype(ch, char_class))
|
Chris@16
|
98 {
|
Chris@16
|
99 this->bset_.set(i);
|
Chris@16
|
100 }
|
Chris@16
|
101 }
|
Chris@16
|
102 }
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 void set_bitset(hash_peek_bitset<Char> const &that)
|
Chris@16
|
106 {
|
Chris@16
|
107 if(this->test_icase_(that.icase()))
|
Chris@16
|
108 {
|
Chris@16
|
109 this->bset_ |= that.bset_;
|
Chris@16
|
110 }
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113 void set_charset(basic_chset_8bit<Char> const &that, bool icase)
|
Chris@16
|
114 {
|
Chris@16
|
115 if(this->test_icase_(icase))
|
Chris@16
|
116 {
|
Chris@16
|
117 this->bset_ |= that.base();
|
Chris@16
|
118 }
|
Chris@16
|
119 }
|
Chris@16
|
120
|
Chris@16
|
121 bool icase() const
|
Chris@16
|
122 {
|
Chris@16
|
123 return this->icase_;
|
Chris@16
|
124 }
|
Chris@16
|
125
|
Chris@16
|
126 template<typename Traits>
|
Chris@16
|
127 bool test(char_type ch, Traits const &tr) const
|
Chris@16
|
128 {
|
Chris@16
|
129 ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch);
|
Chris@16
|
130 return this->bset_.test(tr.hash(ch));
|
Chris@16
|
131 }
|
Chris@16
|
132
|
Chris@16
|
133 template<typename Traits>
|
Chris@16
|
134 bool test(char_type ch, Traits const &tr, mpl::false_) const
|
Chris@16
|
135 {
|
Chris@16
|
136 BOOST_ASSERT(!this->icase_);
|
Chris@16
|
137 return this->bset_.test(tr.hash(tr.translate(ch)));
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@16
|
140 template<typename Traits>
|
Chris@16
|
141 bool test(char_type ch, Traits const &tr, mpl::true_) const
|
Chris@16
|
142 {
|
Chris@16
|
143 BOOST_ASSERT(this->icase_);
|
Chris@16
|
144 return this->bset_.test(tr.hash(tr.translate_nocase(ch)));
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 private:
|
Chris@16
|
148
|
Chris@16
|
149 // Make sure all sub-expressions being merged have the same case-sensitivity
|
Chris@16
|
150 bool test_icase_(bool icase)
|
Chris@16
|
151 {
|
Chris@16
|
152 std::size_t count = this->bset_.count();
|
Chris@16
|
153
|
Chris@16
|
154 if(256 == count)
|
Chris@16
|
155 {
|
Chris@16
|
156 return false; // all set already, nothing to do
|
Chris@16
|
157 }
|
Chris@16
|
158 else if(0 != count && this->icase_ != icase)
|
Chris@16
|
159 {
|
Chris@16
|
160 this->set_all(); // icase mismatch! set all and bail
|
Chris@16
|
161 return false;
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 this->icase_ = icase;
|
Chris@16
|
165 return true;
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 bool icase_;
|
Chris@16
|
169 std::bitset<256> bset_;
|
Chris@16
|
170 };
|
Chris@16
|
171
|
Chris@16
|
172 }}} // namespace boost::xpressive::detail
|
Chris@16
|
173
|
Chris@101
|
174 #if defined(_MSC_VER)
|
Chris@16
|
175 # pragma warning(pop)
|
Chris@16
|
176 #endif
|
Chris@16
|
177
|
Chris@16
|
178 #endif
|