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