hash_peek_bitset.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // hash_peek_bitset.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_HASH_PEEK_BITSET_HPP_EAN_10_04_2005
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. # pragma warning(push)
  13. # pragma warning(disable : 4100) // unreferenced formal parameter
  14. # pragma warning(disable : 4127) // conditional expression constant
  15. #endif
  16. #include <bitset>
  17. #include <string> // for std::char_traits
  18. #include <boost/xpressive/detail/utility/chset/basic_chset.ipp>
  19. namespace boost { namespace xpressive { namespace detail
  20. {
  21. ///////////////////////////////////////////////////////////////////////////////
  22. // hash_peek_bitset
  23. //
  24. template<typename Char>
  25. struct hash_peek_bitset
  26. {
  27. typedef Char char_type;
  28. typedef typename std::char_traits<char_type>::int_type int_type;
  29. hash_peek_bitset()
  30. : icase_(false)
  31. , bset_()
  32. {
  33. }
  34. std::size_t count() const
  35. {
  36. return this->bset_.count();
  37. }
  38. void set_all()
  39. {
  40. this->icase_ = false;
  41. this->bset_.set();
  42. }
  43. template<typename Traits>
  44. void set_char(char_type ch, bool icase, Traits const &tr)
  45. {
  46. if(this->test_icase_(icase))
  47. {
  48. ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
  49. this->bset_.set(tr.hash(ch));
  50. }
  51. }
  52. template<typename Traits>
  53. void set_range(char_type from, char_type to, bool no, bool icase, Traits const &tr)
  54. {
  55. int_type ifrom = std::char_traits<char_type>::to_int_type(from);
  56. int_type ito = std::char_traits<char_type>::to_int_type(to);
  57. BOOST_ASSERT(ifrom <= ito);
  58. // bound the computational complexity. BUGBUG could set the inverse range
  59. if(no || 256 < (ito - ifrom))
  60. {
  61. this->set_all();
  62. }
  63. else if(this->test_icase_(icase))
  64. {
  65. for(int_type i = ifrom; i <= ito; ++i)
  66. {
  67. char_type ch = std::char_traits<char_type>::to_char_type(i);
  68. ch = icase ? tr.translate_nocase(ch) : tr.translate(ch);
  69. this->bset_.set(tr.hash(ch));
  70. }
  71. }
  72. }
  73. template<typename Traits>
  74. void set_class(typename Traits::char_class_type char_class, bool no, Traits const &tr)
  75. {
  76. if(1 != sizeof(char_type))
  77. {
  78. // wide character set, no efficient way of filling in the bitset, so set them all to 1
  79. this->set_all();
  80. }
  81. else
  82. {
  83. for(std::size_t i = 0; i <= UCHAR_MAX; ++i)
  84. {
  85. char_type ch = std::char_traits<char_type>::to_char_type(static_cast<int_type>(i));
  86. if(no != tr.isctype(ch, char_class))
  87. {
  88. this->bset_.set(i);
  89. }
  90. }
  91. }
  92. }
  93. void set_bitset(hash_peek_bitset<Char> const &that)
  94. {
  95. if(this->test_icase_(that.icase()))
  96. {
  97. this->bset_ |= that.bset_;
  98. }
  99. }
  100. void set_charset(basic_chset_8bit<Char> const &that, bool icase)
  101. {
  102. if(this->test_icase_(icase))
  103. {
  104. this->bset_ |= that.base();
  105. }
  106. }
  107. bool icase() const
  108. {
  109. return this->icase_;
  110. }
  111. template<typename Traits>
  112. bool test(char_type ch, Traits const &tr) const
  113. {
  114. ch = this->icase_ ? tr.translate_nocase(ch) : tr.translate(ch);
  115. return this->bset_.test(tr.hash(ch));
  116. }
  117. template<typename Traits>
  118. bool test(char_type ch, Traits const &tr, mpl::false_) const
  119. {
  120. BOOST_ASSERT(!this->icase_);
  121. return this->bset_.test(tr.hash(tr.translate(ch)));
  122. }
  123. template<typename Traits>
  124. bool test(char_type ch, Traits const &tr, mpl::true_) const
  125. {
  126. BOOST_ASSERT(this->icase_);
  127. return this->bset_.test(tr.hash(tr.translate_nocase(ch)));
  128. }
  129. private:
  130. // Make sure all sub-expressions being merged have the same case-sensitivity
  131. bool test_icase_(bool icase)
  132. {
  133. std::size_t count = this->bset_.count();
  134. if(256 == count)
  135. {
  136. return false; // all set already, nothing to do
  137. }
  138. else if(0 != count && this->icase_ != icase)
  139. {
  140. this->set_all(); // icase mismatch! set all and bail
  141. return false;
  142. }
  143. this->icase_ = icase;
  144. return true;
  145. }
  146. bool icase_;
  147. std::bitset<256> bset_;
  148. };
  149. }}} // namespace boost::xpressive::detail
  150. #if defined(_MSC_VER)
  151. # pragma warning(pop)
  152. #endif
  153. #endif