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