Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:52

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // hash_peek_bitset.hpp
0003 //
0004 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
0009 #define BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
0010 
0011 // MS compatible compilers support #pragma once
0012 #if defined(_MSC_VER)
0013 # pragma once
0014 # pragma warning(push)
0015 # pragma warning(disable : 4100) // unreferenced formal parameter
0016 # pragma warning(disable : 4127) // conditional expression constant
0017 #endif
0018 
0019 #include <bitset>
0020 #include <string> // for std::char_traits
0021 #include <boost/xpressive/detail/utility/chset/basic_chset.ipp>
0022 
0023 namespace boost { namespace xpressive { namespace detail
0024 {
0025 
0026 ///////////////////////////////////////////////////////////////////////////////
0027 // hash_peek_bitset
0028 //
0029 template<typename Char>
0030 struct hash_peek_bitset
0031 {
0032     typedef Char char_type;
0033     typedef typename std::char_traits<char_type>::int_type int_type;
0034 
0035     hash_peek_bitset()
0036       : icase_(false)
0037       , bset_()
0038     {
0039     }
0040 
0041     std::size_t count() const
0042     {
0043         return this->bset_.count();
0044     }
0045 
0046     void set_all()
0047     {
0048         this->icase_ = false;
0049         this->bset_.set();
0050     }
0051 
0052     template<typename Traits>
0053     void set_char(char_type ch, bool icase, Traits const &tr)
0054     {
0055         if(this->test_icase_(icase))
0056         {
0057             ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
0058             this->bset_.set(tr.hash(ch));
0059         }
0060     }
0061 
0062     template<typename Traits>
0063     void set_range(char_type from, char_type to, bool no, bool icase, Traits const &tr)
0064     {
0065         int_type ifrom = std::char_traits<char_type>::to_int_type(from);
0066         int_type ito = std::char_traits<char_type>::to_int_type(to);
0067         BOOST_ASSERT(ifrom <= ito);
0068         // bound the computational complexity. BUGBUG could set the inverse range
0069         if(no || 256 < (ito - ifrom))
0070         {
0071             this->set_all();
0072         }
0073         else if(this->test_icase_(icase))
0074         {
0075             for(int_type i = ifrom; i <= ito; ++i)
0076             {
0077                 char_type ch = std::char_traits<char_type>::to_char_type(i);
0078                 ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
0079                 this->bset_.set(tr.hash(ch));
0080             }
0081         }
0082     }
0083 
0084     template<typename Traits>
0085     void set_class(typename Traits::char_class_type char_class, bool no, Traits const &tr)
0086     {
0087         if(1 != sizeof(char_type))
0088         {
0089             // wide character set, no efficient way of filling in the bitset, so set them all to 1
0090             this->set_all();
0091         }
0092         else
0093         {
0094             for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
0095             {
0096                 char_type ch = std::char_traits<char_type>::to_char_type(static_cast<int_type>(i));
0097                 if(no != tr.isctype(ch, char_class))
0098                 {
0099                     this->bset_.set(i);
0100                 }
0101             }
0102         }
0103     }
0104 
0105     void set_bitset(hash_peek_bitset<Char> const &that)
0106     {
0107         if(this->test_icase_(that.icase()))
0108         {
0109             this->bset_ |= that.bset_;
0110         }
0111     }
0112 
0113     void set_charset(basic_chset_8bit<Char> const &that, bool icase)
0114     {
0115         if(this->test_icase_(icase))
0116         {
0117             this->bset_ |= that.base();
0118         }
0119     }
0120 
0121     bool icase() const
0122     {
0123         return this->icase_;
0124     }
0125 
0126     template<typename Traits>
0127     bool test(char_type ch, Traits const &tr) const
0128     {
0129         ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch);
0130         return this->bset_.test(tr.hash(ch));
0131     }
0132 
0133     template<typename Traits>
0134     bool test(char_type ch, Traits const &tr, mpl::false_) const
0135     {
0136         BOOST_ASSERT(!this->icase_);
0137         return this->bset_.test(tr.hash(tr.translate(ch)));
0138     }
0139 
0140     template<typename Traits>
0141     bool test(char_type ch, Traits const &tr, mpl::true_) const
0142     {
0143         BOOST_ASSERT(this->icase_);
0144         return this->bset_.test(tr.hash(tr.translate_nocase(ch)));
0145     }
0146 
0147 private:
0148 
0149     // Make sure all sub-expressions being merged have the same case-sensitivity
0150     bool test_icase_(bool icase)
0151     {
0152         std::size_t count = this->bset_.count();
0153 
0154         if(256 == count)
0155         {
0156             return false; // all set already, nothing to do
0157         }
0158         else if(0 != count && this->icase_ != icase)
0159         {
0160             this->set_all(); // icase mismatch! set all and bail
0161             return false;
0162         }
0163 
0164         this->icase_ = icase;
0165         return true;
0166     }
0167 
0168     bool icase_;
0169     std::bitset<256> bset_;
0170 };
0171 
0172 }}} // namespace boost::xpressive::detail
0173 
0174 #if defined(_MSC_VER)
0175 # pragma warning(pop)
0176 #endif
0177 
0178 #endif