| /////////////////////////////////////////////////////////////////////////////// |
| // hash_peek_bitset.hpp |
| // |
| // Copyright 2008 Eric Niebler. Distributed under the Boost |
| // Software License, Version 1.0. (See accompanying file |
| // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005 |
| #define BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005 |
| |
| // MS compatible compilers support #pragma once |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| # pragma warning(push) |
| # pragma warning(disable : 4100) // unreferenced formal parameter |
| # pragma warning(disable : 4127) // conditional expression constant |
| #endif |
| |
| #include <bitset> |
| #include <string> // for std::char_traits |
| #include <boost/xpressive/detail/utility/chset/basic_chset.ipp> |
| |
| namespace boost { namespace xpressive { namespace detail |
| { |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // hash_peek_bitset |
| // |
| template<typename Char> |
| struct hash_peek_bitset |
| { |
| typedef Char char_type; |
| typedef typename std::char_traits<char_type>::int_type int_type; |
| |
| hash_peek_bitset() |
| : icase_(false) |
| , bset_() |
| { |
| } |
| |
| std::size_t count() const |
| { |
| return this->bset_.count(); |
| } |
| |
| void set_all() |
| { |
| this->icase_ = false; |
| this->bset_.set(); |
| } |
| |
| template<typename Traits> |
| void set_char(char_type ch, bool icase, Traits const &tr) |
| { |
| if(this->test_icase_(icase)) |
| { |
| ch = icase ? tr.translate_nocase(ch) : tr.translate(ch); |
| this->bset_.set(tr.hash(ch)); |
| } |
| } |
| |
| template<typename Traits> |
| void set_range(char_type from, char_type to, bool no, bool icase, Traits const &tr) |
| { |
| int_type ifrom = std::char_traits<char_type>::to_int_type(from); |
| int_type ito = std::char_traits<char_type>::to_int_type(to); |
| BOOST_ASSERT(ifrom <= ito); |
| // bound the computational complexity. BUGBUG could set the inverse range |
| if(no || 256 < (ito - ifrom)) |
| { |
| this->set_all(); |
| } |
| else if(this->test_icase_(icase)) |
| { |
| for(int_type i = ifrom; i <= ito; ++i) |
| { |
| char_type ch = std::char_traits<char_type>::to_char_type(i); |
| ch = icase ? tr.translate_nocase(ch) : tr.translate(ch); |
| this->bset_.set(tr.hash(ch)); |
| } |
| } |
| } |
| |
| template<typename Traits> |
| void set_class(typename Traits::char_class_type char_class, bool no, Traits const &tr) |
| { |
| if(1 != sizeof(char_type)) |
| { |
| // wide character set, no efficient way of filling in the bitset, so set them all to 1 |
| this->set_all(); |
| } |
| else |
| { |
| for(std::size_t i = 0; i <= UCHAR_MAX; ++i) |
| { |
| char_type ch = std::char_traits<char_type>::to_char_type(static_cast<int_type>(i)); |
| if(no != tr.isctype(ch, char_class)) |
| { |
| this->bset_.set(i); |
| } |
| } |
| } |
| } |
| |
| void set_bitset(hash_peek_bitset<Char> const &that) |
| { |
| if(this->test_icase_(that.icase())) |
| { |
| this->bset_ |= that.bset_; |
| } |
| } |
| |
| void set_charset(basic_chset_8bit<Char> const &that, bool icase) |
| { |
| if(this->test_icase_(icase)) |
| { |
| this->bset_ |= that.base(); |
| } |
| } |
| |
| bool icase() const |
| { |
| return this->icase_; |
| } |
| |
| template<typename Traits> |
| bool test(char_type ch, Traits const &tr) const |
| { |
| ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch); |
| return this->bset_.test(tr.hash(ch)); |
| } |
| |
| template<typename Traits> |
| bool test(char_type ch, Traits const &tr, mpl::false_) const |
| { |
| BOOST_ASSERT(!this->icase_); |
| return this->bset_.test(tr.hash(tr.translate(ch))); |
| } |
| |
| template<typename Traits> |
| bool test(char_type ch, Traits const &tr, mpl::true_) const |
| { |
| BOOST_ASSERT(this->icase_); |
| return this->bset_.test(tr.hash(tr.translate_nocase(ch))); |
| } |
| |
| private: |
| |
| // Make sure all sub-expressions being merged have the same case-sensitivity |
| bool test_icase_(bool icase) |
| { |
| std::size_t count = this->bset_.count(); |
| |
| if(256 == count) |
| { |
| return false; // all set already, nothing to do |
| } |
| else if(0 != count && this->icase_ != icase) |
| { |
| this->set_all(); // icase mismatch! set all and bail |
| return false; |
| } |
| |
| this->icase_ = icase; |
| return true; |
| } |
| |
| bool icase_; |
| std::bitset<256> bset_; |
| }; |
| |
| }}} // namespace boost::xpressive::detail |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma warning(pop) |
| #endif |
| |
| #endif |