You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
178 lines
4.7 KiB
178 lines
4.7 KiB
/////////////////////////////////////////////////////////////////////////////// |
|
// 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
|
|
|