boost/xpressive/detail/utility/hash_peek_bitset.hpp
///////////////////////////////////////////////////////////////////////////////
// hash_peek_bitset.hpp
//
// Copyright 2004 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 &traits)
{
if(this->test_icase_(icase))
{
ch = icase ? traits.translate_nocase(ch) : traits.translate(ch);
this->bset_.set(traits.hash(ch));
}
}
template<typename Traits>
void set_range(char_type from, char_type to, bool no, bool icase, Traits const &traits)
{
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 ? traits.translate_nocase(ch) : traits.translate(ch);
this->bset_.set(traits.hash(ch));
}
}
}
template<typename Traits>
void set_class(typename Traits::char_class_type char_class, bool no, Traits const &traits)
{
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 != traits.isctype(ch, char_class))
{
this->bset_.set(i);
}
}
}
}
void set_bitset(hash_peek_bitset<Char> const &that)
{
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 &traits) const
{
ch = this->icase_ ? traits.translate_nocase(ch) : traits.translate(ch);
return this->bset_.test(traits.hash(ch));
}
template<typename Traits>
bool test(char_type ch, Traits const &traits, mpl::false_) const
{
BOOST_ASSERT(!this->icase_);
return this->bset_.test(traits.hash(traits.translate(ch)));
}
template<typename Traits>
bool test(char_type ch, Traits const &traits, mpl::true_) const
{
BOOST_ASSERT(this->icase_);
return this->bset_.test(traits.hash(traits.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