/Src/Dependencies/Boost/boost/xpressive/traits/cpp_regex_traits.hpp

http://hadesmem.googlecode.com/ · C++ Header · 694 lines · 436 code · 82 blank · 176 comment · 64 complexity · 64a392aa162883f1b5304d1835f8e2e2 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file cpp_regex_traits.hpp
  3. /// Contains the definition of the cpp_regex_traits\<\> template, which is a
  4. /// wrapper for std::locale that can be used to customize the behavior of
  5. /// static and dynamic regexes.
  6. //
  7. // Copyright 2008 Eric Niebler. Distributed under the Boost
  8. // Software License, Version 1.0. (See accompanying file
  9. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_XPRESSIVE_TRAITS_CPP_REGEX_TRAITS_HPP_EAN_10_04_2005
  11. #define BOOST_XPRESSIVE_TRAITS_CPP_REGEX_TRAITS_HPP_EAN_10_04_2005
  12. // MS compatible compilers support #pragma once
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  14. # pragma once
  15. #endif
  16. #include <ios>
  17. #include <string>
  18. #include <locale>
  19. #include <sstream>
  20. #include <boost/config.hpp>
  21. #include <boost/assert.hpp>
  22. #include <boost/integer.hpp>
  23. #include <boost/mpl/assert.hpp>
  24. #include <boost/detail/workaround.hpp>
  25. #include <boost/type_traits/is_same.hpp>
  26. #include <boost/xpressive/detail/detail_fwd.hpp>
  27. #include <boost/xpressive/detail/utility/literals.hpp>
  28. // From John Maddock:
  29. // Fix for gcc prior to 3.4: std::ctype<wchar_t> doesn't allow masks to be combined, for example:
  30. // std::use_facet<std::ctype<wchar_t> >(locale()).is(std::ctype_base::lower|std::ctype_base::upper, L'a');
  31. // incorrectly returns false.
  32. // NOTE: later version of the gcc define __GLIBCXX__, not __GLIBCPP__
  33. #if BOOST_WORKAROUND(__GLIBCPP__, != 0)
  34. # define BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
  35. #endif
  36. namespace boost { namespace xpressive
  37. {
  38. namespace detail
  39. {
  40. // define an unsigned integral typedef of the same size as std::ctype_base::mask
  41. typedef boost::uint_t<sizeof(std::ctype_base::mask) * CHAR_BIT>::least umask_t;
  42. BOOST_MPL_ASSERT_RELATION(sizeof(std::ctype_base::mask), ==, sizeof(umask_t));
  43. // Calculate what the size of the umaskex_t type should be to fix the 3 extra bitmasks
  44. // 11 char categories in ctype_base
  45. // + 3 extra categories for xpressive
  46. // = 14 total bits needed
  47. int const umaskex_bits = (14 > (sizeof(umask_t) * CHAR_BIT)) ? 14 : sizeof(umask_t) * CHAR_BIT;
  48. // define an unsigned integral type with at least umaskex_bits
  49. typedef boost::uint_t<umaskex_bits>::fast umaskex_t;
  50. BOOST_MPL_ASSERT_RELATION(sizeof(umask_t), <=, sizeof(umaskex_t));
  51. // cast a ctype mask to a umaskex_t
  52. template<std::ctype_base::mask Mask>
  53. struct mask_cast
  54. {
  55. BOOST_STATIC_CONSTANT(umaskex_t, value = static_cast<umask_t>(Mask));
  56. };
  57. #ifdef __CYGWIN__
  58. // Work around a gcc warning on cygwin
  59. template<>
  60. struct mask_cast<std::ctype_base::print>
  61. {
  62. BOOST_MPL_ASSERT_RELATION('\227', ==, std::ctype_base::print);
  63. BOOST_STATIC_CONSTANT(umaskex_t, value = 0227);
  64. };
  65. #endif
  66. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  67. template<std::ctype_base::mask Mask>
  68. umaskex_t const mask_cast<Mask>::value;
  69. #endif
  70. #ifndef BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
  71. // an unsigned integer with the highest bit set
  72. umaskex_t const highest_bit = static_cast<umaskex_t>(1) << (sizeof(umaskex_t) * CHAR_BIT - 1);
  73. ///////////////////////////////////////////////////////////////////////////////
  74. // unused_mask
  75. // find a bit in an int that isn't set
  76. template<umaskex_t In, umaskex_t Out = highest_bit, bool Done = (0 == (Out & In))>
  77. struct unused_mask
  78. {
  79. BOOST_MPL_ASSERT_RELATION(1, !=, Out);
  80. BOOST_STATIC_CONSTANT(umaskex_t, value = (unused_mask<In, (Out >> 1)>::value));
  81. };
  82. template<umaskex_t In, umaskex_t Out>
  83. struct unused_mask<In, Out, true>
  84. {
  85. BOOST_STATIC_CONSTANT(umaskex_t, value = Out);
  86. };
  87. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  88. template<umaskex_t In, umaskex_t Out, bool Done>
  89. umaskex_t const unused_mask<In, Out, Done>::value;
  90. #endif
  91. umaskex_t const std_ctype_alnum = mask_cast<std::ctype_base::alnum>::value;
  92. umaskex_t const std_ctype_alpha = mask_cast<std::ctype_base::alpha>::value;
  93. umaskex_t const std_ctype_cntrl = mask_cast<std::ctype_base::cntrl>::value;
  94. umaskex_t const std_ctype_digit = mask_cast<std::ctype_base::digit>::value;
  95. umaskex_t const std_ctype_graph = mask_cast<std::ctype_base::graph>::value;
  96. umaskex_t const std_ctype_lower = mask_cast<std::ctype_base::lower>::value;
  97. umaskex_t const std_ctype_print = mask_cast<std::ctype_base::print>::value;
  98. umaskex_t const std_ctype_punct = mask_cast<std::ctype_base::punct>::value;
  99. umaskex_t const std_ctype_space = mask_cast<std::ctype_base::space>::value;
  100. umaskex_t const std_ctype_upper = mask_cast<std::ctype_base::upper>::value;
  101. umaskex_t const std_ctype_xdigit = mask_cast<std::ctype_base::xdigit>::value;
  102. // Reserve some bits for the implementation
  103. #if defined(__GLIBCXX__)
  104. umaskex_t const std_ctype_reserved = 0x8000;
  105. #elif defined(_CPPLIB_VER) && defined(BOOST_WINDOWS)
  106. umaskex_t const std_ctype_reserved = 0x8200;
  107. #else
  108. umaskex_t const std_ctype_reserved = 0;
  109. #endif
  110. // Bitwise-or all the ctype masks together
  111. umaskex_t const all_ctype_masks = std_ctype_reserved
  112. | std_ctype_alnum | std_ctype_alpha | std_ctype_cntrl | std_ctype_digit
  113. | std_ctype_graph | std_ctype_lower | std_ctype_print | std_ctype_punct
  114. | std_ctype_space | std_ctype_upper | std_ctype_xdigit;
  115. // define a new mask for "underscore" ("word" == alnum | underscore)
  116. umaskex_t const non_std_ctype_underscore = unused_mask<all_ctype_masks>::value;
  117. // define a new mask for "blank"
  118. umaskex_t const non_std_ctype_blank = unused_mask<all_ctype_masks | non_std_ctype_underscore>::value;
  119. // define a new mask for "newline"
  120. umaskex_t const non_std_ctype_newline = unused_mask<all_ctype_masks | non_std_ctype_underscore | non_std_ctype_blank>::value;
  121. #else
  122. ///////////////////////////////////////////////////////////////////////////////
  123. // Ugly work-around for buggy ctype facets.
  124. umaskex_t const std_ctype_alnum = 1 << 0;
  125. umaskex_t const std_ctype_alpha = 1 << 1;
  126. umaskex_t const std_ctype_cntrl = 1 << 2;
  127. umaskex_t const std_ctype_digit = 1 << 3;
  128. umaskex_t const std_ctype_graph = 1 << 4;
  129. umaskex_t const std_ctype_lower = 1 << 5;
  130. umaskex_t const std_ctype_print = 1 << 6;
  131. umaskex_t const std_ctype_punct = 1 << 7;
  132. umaskex_t const std_ctype_space = 1 << 8;
  133. umaskex_t const std_ctype_upper = 1 << 9;
  134. umaskex_t const std_ctype_xdigit = 1 << 10;
  135. umaskex_t const non_std_ctype_underscore = 1 << 11;
  136. umaskex_t const non_std_ctype_blank = 1 << 12;
  137. umaskex_t const non_std_ctype_newline = 1 << 13;
  138. static umaskex_t const std_masks[] =
  139. {
  140. mask_cast<std::ctype_base::alnum>::value
  141. , mask_cast<std::ctype_base::alpha>::value
  142. , mask_cast<std::ctype_base::cntrl>::value
  143. , mask_cast<std::ctype_base::digit>::value
  144. , mask_cast<std::ctype_base::graph>::value
  145. , mask_cast<std::ctype_base::lower>::value
  146. , mask_cast<std::ctype_base::print>::value
  147. , mask_cast<std::ctype_base::punct>::value
  148. , mask_cast<std::ctype_base::space>::value
  149. , mask_cast<std::ctype_base::upper>::value
  150. , mask_cast<std::ctype_base::xdigit>::value
  151. };
  152. inline int mylog2(umaskex_t i)
  153. {
  154. return "\0\0\1\0\2\0\0\0\3"[i & 0xf]
  155. + "\0\4\5\0\6\0\0\0\7"[(i & 0xf0) >> 04]
  156. + "\0\10\11\0\12\0\0\0\13"[(i & 0xf00) >> 010];
  157. }
  158. #endif
  159. // convenient constant for the extra masks
  160. umaskex_t const non_std_ctype_masks = non_std_ctype_underscore | non_std_ctype_blank | non_std_ctype_newline;
  161. ///////////////////////////////////////////////////////////////////////////////
  162. // cpp_regex_traits_base
  163. // BUGBUG this should be replaced with a regex facet that lets you query for
  164. // an array of underscore characters and an array of line separator characters.
  165. template<typename Char, std::size_t SizeOfChar = sizeof(Char)>
  166. struct cpp_regex_traits_base
  167. {
  168. protected:
  169. void imbue(std::locale const &)
  170. {
  171. }
  172. static bool is(std::ctype<Char> const &ct, Char ch, umaskex_t mask)
  173. {
  174. #ifndef BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
  175. if(ct.is((std::ctype_base::mask)(umask_t)mask, ch))
  176. {
  177. return true;
  178. }
  179. #else
  180. umaskex_t tmp = mask & ~non_std_ctype_masks;
  181. for(umaskex_t i; 0 != (i = (tmp & (~tmp+1))); tmp &= ~i)
  182. {
  183. std::ctype_base::mask m = (std::ctype_base::mask)(umask_t)std_masks[mylog2(i)];
  184. if(ct.is(m, ch))
  185. {
  186. return true;
  187. }
  188. }
  189. #endif
  190. return ((mask & non_std_ctype_blank) && cpp_regex_traits_base::is_blank(ch))
  191. || ((mask & non_std_ctype_underscore) && cpp_regex_traits_base::is_underscore(ch))
  192. || ((mask & non_std_ctype_newline) && cpp_regex_traits_base::is_newline(ch));
  193. }
  194. private:
  195. static bool is_blank(Char ch)
  196. {
  197. BOOST_MPL_ASSERT_RELATION('\t', ==, L'\t');
  198. BOOST_MPL_ASSERT_RELATION(' ', ==, L' ');
  199. return L' ' == ch || L'\t' == ch;
  200. }
  201. static bool is_underscore(Char ch)
  202. {
  203. BOOST_MPL_ASSERT_RELATION('_', ==, L'_');
  204. return L'_' == ch;
  205. }
  206. static bool is_newline(Char ch)
  207. {
  208. BOOST_MPL_ASSERT_RELATION('\r', ==, L'\r');
  209. BOOST_MPL_ASSERT_RELATION('\n', ==, L'\n');
  210. BOOST_MPL_ASSERT_RELATION('\f', ==, L'\f');
  211. return L'\r' == ch || L'\n' == ch || L'\f' == ch
  212. || (1 < SizeOfChar && (0x2028u == ch || 0x2029u == ch || 0x85u == ch));
  213. }
  214. };
  215. #ifndef BOOST_XPRESSIVE_BUGGY_CTYPE_FACET
  216. template<typename Char>
  217. struct cpp_regex_traits_base<Char, 1>
  218. {
  219. protected:
  220. void imbue(std::locale const &loc)
  221. {
  222. int i = 0;
  223. Char allchars[UCHAR_MAX + 1];
  224. for(i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
  225. {
  226. allchars[i] = static_cast<Char>(i);
  227. }
  228. std::ctype<Char> const &ct = BOOST_USE_FACET(std::ctype<Char>, loc);
  229. std::ctype_base::mask tmp[UCHAR_MAX + 1];
  230. ct.is(allchars, allchars + UCHAR_MAX + 1, tmp);
  231. for(i = 0; i <= static_cast<int>(UCHAR_MAX); ++i)
  232. {
  233. this->masks_[i] = static_cast<umask_t>(tmp[i]);
  234. BOOST_ASSERT(0 == (this->masks_[i] & non_std_ctype_masks));
  235. }
  236. this->masks_[static_cast<unsigned char>('_')] |= non_std_ctype_underscore;
  237. this->masks_[static_cast<unsigned char>(' ')] |= non_std_ctype_blank;
  238. this->masks_[static_cast<unsigned char>('\t')] |= non_std_ctype_blank;
  239. this->masks_[static_cast<unsigned char>('\n')] |= non_std_ctype_newline;
  240. this->masks_[static_cast<unsigned char>('\r')] |= non_std_ctype_newline;
  241. this->masks_[static_cast<unsigned char>('\f')] |= non_std_ctype_newline;
  242. }
  243. bool is(std::ctype<Char> const &, Char ch, umaskex_t mask) const
  244. {
  245. return 0 != (this->masks_[static_cast<unsigned char>(ch)] & mask);
  246. }
  247. private:
  248. umaskex_t masks_[UCHAR_MAX + 1];
  249. };
  250. #endif
  251. } // namespace detail
  252. ///////////////////////////////////////////////////////////////////////////////
  253. // cpp_regex_traits
  254. //
  255. /// \brief Encapsaulates a std::locale for use by the
  256. /// basic_regex\<\> class template.
  257. template<typename Char>
  258. struct cpp_regex_traits
  259. : detail::cpp_regex_traits_base<Char>
  260. {
  261. typedef Char char_type;
  262. typedef std::basic_string<char_type> string_type;
  263. typedef std::locale locale_type;
  264. typedef detail::umaskex_t char_class_type;
  265. typedef regex_traits_version_2_tag version_tag;
  266. typedef detail::cpp_regex_traits_base<Char> base_type;
  267. /// Initialize a cpp_regex_traits object to use the specified std::locale,
  268. /// or the global std::locale if none is specified.
  269. ///
  270. cpp_regex_traits(locale_type const &loc = locale_type())
  271. : base_type()
  272. , loc_()
  273. {
  274. this->imbue(loc);
  275. }
  276. /// Checks two cpp_regex_traits objects for equality
  277. ///
  278. /// \return this->getloc() == that.getloc().
  279. bool operator ==(cpp_regex_traits<char_type> const &that) const
  280. {
  281. return this->loc_ == that.loc_;
  282. }
  283. /// Checks two cpp_regex_traits objects for inequality
  284. ///
  285. /// \return this->getloc() != that.getloc().
  286. bool operator !=(cpp_regex_traits<char_type> const &that) const
  287. {
  288. return this->loc_ != that.loc_;
  289. }
  290. /// Convert a char to a Char
  291. ///
  292. /// \param ch The source character.
  293. /// \return std::use_facet\<std::ctype\<char_type\> \>(this->getloc()).widen(ch).
  294. char_type widen(char ch) const
  295. {
  296. return this->ctype_->widen(ch);
  297. }
  298. /// Returns a hash value for a Char in the range [0, UCHAR_MAX]
  299. ///
  300. /// \param ch The source character.
  301. /// \return a value between 0 and UCHAR_MAX, inclusive.
  302. static unsigned char hash(char_type ch)
  303. {
  304. return static_cast<unsigned char>(std::char_traits<Char>::to_int_type(ch));
  305. }
  306. /// No-op
  307. ///
  308. /// \param ch The source character.
  309. /// \return ch
  310. static char_type translate(char_type ch)
  311. {
  312. return ch;
  313. }
  314. /// Converts a character to lower-case using the internally-stored std::locale.
  315. ///
  316. /// \param ch The source character.
  317. /// \return std::tolower(ch, this->getloc()).
  318. char_type translate_nocase(char_type ch) const
  319. {
  320. return this->ctype_->tolower(ch);
  321. }
  322. /// Converts a character to lower-case using the internally-stored std::locale.
  323. ///
  324. /// \param ch The source character.
  325. /// \return std::tolower(ch, this->getloc()).
  326. char_type tolower(char_type ch) const
  327. {
  328. return this->ctype_->tolower(ch);
  329. }
  330. /// Converts a character to upper-case using the internally-stored std::locale.
  331. ///
  332. /// \param ch The source character.
  333. /// \return std::toupper(ch, this->getloc()).
  334. char_type toupper(char_type ch) const
  335. {
  336. return this->ctype_->toupper(ch);
  337. }
  338. /// Returns a string_type containing all the characters that compare equal
  339. /// disregrarding case to the one passed in. This function can only be called
  340. /// if has_fold_case\<cpp_regex_traits\<Char\> \>::value is true.
  341. ///
  342. /// \param ch The source character.
  343. /// \return string_type containing all chars which are equal to ch when disregarding
  344. /// case
  345. string_type fold_case(char_type ch) const
  346. {
  347. BOOST_MPL_ASSERT((is_same<char_type, char>));
  348. char_type ntcs[] = {
  349. this->ctype_->tolower(ch)
  350. , this->ctype_->toupper(ch)
  351. , 0
  352. };
  353. if(ntcs[1] == ntcs[0])
  354. ntcs[1] = 0;
  355. return string_type(ntcs);
  356. }
  357. /// Checks to see if a character is within a character range.
  358. ///
  359. /// \param first The bottom of the range, inclusive.
  360. /// \param last The top of the range, inclusive.
  361. /// \param ch The source character.
  362. /// \return first <= ch && ch <= last.
  363. static bool in_range(char_type first, char_type last, char_type ch)
  364. {
  365. return first <= ch && ch <= last;
  366. }
  367. /// Checks to see if a character is within a character range, irregardless of case.
  368. ///
  369. /// \param first The bottom of the range, inclusive.
  370. /// \param last The top of the range, inclusive.
  371. /// \param ch The source character.
  372. /// \return in_range(first, last, ch) || in_range(first, last, tolower(ch, this->getloc())) ||
  373. /// in_range(first, last, toupper(ch, this->getloc()))
  374. /// \attention The default implementation doesn't do proper Unicode
  375. /// case folding, but this is the best we can do with the standard
  376. /// ctype facet.
  377. bool in_range_nocase(char_type first, char_type last, char_type ch) const
  378. {
  379. // NOTE: this default implementation doesn't do proper Unicode
  380. // case folding, but this is the best we can do with the standard
  381. // std::ctype facet.
  382. return this->in_range(first, last, ch)
  383. || this->in_range(first, last, this->ctype_->toupper(ch))
  384. || this->in_range(first, last, this->ctype_->tolower(ch));
  385. }
  386. /// INTERNAL ONLY
  387. //string_type transform(char_type const *begin, char_type const *end) const
  388. //{
  389. // return this->collate_->transform(begin, end);
  390. //}
  391. /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
  392. /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
  393. /// then v.transform(G1, G2) \< v.transform(H1, H2).
  394. ///
  395. /// \attention Not currently used
  396. template<typename FwdIter>
  397. string_type transform(FwdIter begin, FwdIter end) const
  398. {
  399. //string_type str(begin, end);
  400. //return this->transform(str.data(), str.data() + str.size());
  401. BOOST_ASSERT(false);
  402. return string_type();
  403. }
  404. /// Returns a sort key for the character sequence designated by the iterator range [F1, F2)
  405. /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2)
  406. /// when character case is not considered then
  407. /// v.transform_primary(G1, G2) \< v.transform_primary(H1, H2).
  408. ///
  409. /// \attention Not currently used
  410. template<typename FwdIter>
  411. string_type transform_primary(FwdIter begin, FwdIter end) const
  412. {
  413. BOOST_ASSERT(false); // TODO implement me
  414. return string_type();
  415. }
  416. /// Returns a sequence of characters that represents the collating element
  417. /// consisting of the character sequence designated by the iterator range [F1, F2).
  418. /// Returns an empty string if the character sequence is not a valid collating element.
  419. ///
  420. /// \attention Not currently used
  421. template<typename FwdIter>
  422. string_type lookup_collatename(FwdIter begin, FwdIter end) const
  423. {
  424. BOOST_ASSERT(false); // TODO implement me
  425. return string_type();
  426. }
  427. /// For the character class name represented by the specified character sequence,
  428. /// return the corresponding bitmask representation.
  429. ///
  430. /// \param begin A forward iterator to the start of the character sequence representing
  431. /// the name of the character class.
  432. /// \param end The end of the character sequence.
  433. /// \param icase Specifies whether the returned bitmask should represent the case-insensitive
  434. /// version of the character class.
  435. /// \return A bitmask representing the character class.
  436. template<typename FwdIter>
  437. char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase) const
  438. {
  439. static detail::umaskex_t const icase_masks =
  440. detail::std_ctype_lower | detail::std_ctype_upper;
  441. BOOST_ASSERT(begin != end);
  442. char_class_type char_class = this->lookup_classname_impl_(begin, end);
  443. if(0 == char_class)
  444. {
  445. // convert the string to lowercase
  446. string_type classname(begin, end);
  447. for(typename string_type::size_type i = 0, len = classname.size(); i < len; ++i)
  448. {
  449. classname[i] = this->translate_nocase(classname[i]);
  450. }
  451. char_class = this->lookup_classname_impl_(classname.begin(), classname.end());
  452. }
  453. // erase case-sensitivity if icase==true
  454. if(icase && 0 != (char_class & icase_masks))
  455. {
  456. char_class |= icase_masks;
  457. }
  458. return char_class;
  459. }
  460. /// Tests a character against a character class bitmask.
  461. ///
  462. /// \param ch The character to test.
  463. /// \param mask The character class bitmask against which to test.
  464. /// \pre mask is a bitmask returned by lookup_classname, or is several such masks bit-or'ed
  465. /// together.
  466. /// \return true if the character is a member of any of the specified character classes, false
  467. /// otherwise.
  468. bool isctype(char_type ch, char_class_type mask) const
  469. {
  470. return this->base_type::is(*this->ctype_, ch, mask);
  471. }
  472. /// Convert a digit character into the integer it represents.
  473. ///
  474. /// \param ch The digit character.
  475. /// \param radix The radix to use for the conversion.
  476. /// \pre radix is one of 8, 10, or 16.
  477. /// \return -1 if ch is not a digit character, the integer value of the character otherwise.
  478. /// The conversion is performed by imbueing a std::stringstream with this-\>getloc();
  479. /// setting the radix to one of oct, hex or dec; inserting ch into the stream; and
  480. /// extracting an int.
  481. int value(char_type ch, int radix) const
  482. {
  483. BOOST_ASSERT(8 == radix || 10 == radix || 16 == radix);
  484. int val = -1;
  485. std::basic_stringstream<char_type> str;
  486. str.imbue(this->getloc());
  487. str << (8 == radix ? std::oct : (16 == radix ? std::hex : std::dec));
  488. str.put(ch);
  489. str >> val;
  490. return str.fail() ? -1 : val;
  491. }
  492. /// Imbues *this with loc
  493. ///
  494. /// \param loc A std::locale.
  495. /// \return the previous std::locale used by *this.
  496. locale_type imbue(locale_type loc)
  497. {
  498. locale_type old_loc = this->loc_;
  499. this->loc_ = loc;
  500. this->ctype_ = &BOOST_USE_FACET(std::ctype<char_type>, this->loc_);
  501. //this->collate_ = &BOOST_USE_FACET(std::collate<char_type>, this->loc_);
  502. this->base_type::imbue(this->loc_);
  503. return old_loc;
  504. }
  505. /// Returns the current std::locale used by *this.
  506. ///
  507. locale_type getloc() const
  508. {
  509. return this->loc_;
  510. }
  511. private:
  512. ///////////////////////////////////////////////////////////////////////////////
  513. // char_class_pair
  514. /// INTERNAL ONLY
  515. struct char_class_pair
  516. {
  517. char_type const *class_name_;
  518. char_class_type class_type_;
  519. };
  520. ///////////////////////////////////////////////////////////////////////////////
  521. // char_class
  522. /// INTERNAL ONLY
  523. static char_class_pair const &char_class(std::size_t j)
  524. {
  525. static char_class_pair const s_char_class_map[] =
  526. {
  527. { BOOST_XPR_CSTR_(char_type, "alnum"), detail::std_ctype_alnum }
  528. , { BOOST_XPR_CSTR_(char_type, "alpha"), detail::std_ctype_alpha }
  529. , { BOOST_XPR_CSTR_(char_type, "blank"), detail::non_std_ctype_blank }
  530. , { BOOST_XPR_CSTR_(char_type, "cntrl"), detail::std_ctype_cntrl }
  531. , { BOOST_XPR_CSTR_(char_type, "d"), detail::std_ctype_digit }
  532. , { BOOST_XPR_CSTR_(char_type, "digit"), detail::std_ctype_digit }
  533. , { BOOST_XPR_CSTR_(char_type, "graph"), detail::std_ctype_graph }
  534. , { BOOST_XPR_CSTR_(char_type, "lower"), detail::std_ctype_lower }
  535. , { BOOST_XPR_CSTR_(char_type, "newline"),detail::non_std_ctype_newline }
  536. , { BOOST_XPR_CSTR_(char_type, "print"), detail::std_ctype_print }
  537. , { BOOST_XPR_CSTR_(char_type, "punct"), detail::std_ctype_punct }
  538. , { BOOST_XPR_CSTR_(char_type, "s"), detail::std_ctype_space }
  539. , { BOOST_XPR_CSTR_(char_type, "space"), detail::std_ctype_space }
  540. , { BOOST_XPR_CSTR_(char_type, "upper"), detail::std_ctype_upper }
  541. , { BOOST_XPR_CSTR_(char_type, "w"), detail::std_ctype_alnum | detail::non_std_ctype_underscore }
  542. , { BOOST_XPR_CSTR_(char_type, "xdigit"), detail::std_ctype_xdigit }
  543. , { 0, 0 }
  544. };
  545. return s_char_class_map[j];
  546. }
  547. ///////////////////////////////////////////////////////////////////////////////
  548. // lookup_classname_impl
  549. /// INTERNAL ONLY
  550. template<typename FwdIter>
  551. static char_class_type lookup_classname_impl_(FwdIter begin, FwdIter end)
  552. {
  553. // find the classname
  554. typedef cpp_regex_traits<Char> this_t;
  555. for(std::size_t j = 0; 0 != this_t::char_class(j).class_name_; ++j)
  556. {
  557. if(this_t::compare_(this_t::char_class(j).class_name_, begin, end))
  558. {
  559. return this_t::char_class(j).class_type_;
  560. }
  561. }
  562. return 0;
  563. }
  564. /// INTERNAL ONLY
  565. template<typename FwdIter>
  566. static bool compare_(char_type const *name, FwdIter begin, FwdIter end)
  567. {
  568. for(; *name && begin != end; ++name, ++begin)
  569. {
  570. if(*name != *begin)
  571. {
  572. return false;
  573. }
  574. }
  575. return !*name && begin == end;
  576. }
  577. locale_type loc_;
  578. std::ctype<char_type> const *ctype_;
  579. //std::collate<char_type> const *collate_;
  580. };
  581. ///////////////////////////////////////////////////////////////////////////////
  582. // cpp_regex_traits<>::hash specializations
  583. template<>
  584. inline unsigned char cpp_regex_traits<unsigned char>::hash(unsigned char ch)
  585. {
  586. return ch;
  587. }
  588. template<>
  589. inline unsigned char cpp_regex_traits<char>::hash(char ch)
  590. {
  591. return static_cast<unsigned char>(ch);
  592. }
  593. template<>
  594. inline unsigned char cpp_regex_traits<signed char>::hash(signed char ch)
  595. {
  596. return static_cast<unsigned char>(ch);
  597. }
  598. #ifndef BOOST_XPRESSIVE_NO_WREGEX
  599. template<>
  600. inline unsigned char cpp_regex_traits<wchar_t>::hash(wchar_t ch)
  601. {
  602. return static_cast<unsigned char>(ch);
  603. }
  604. #endif
  605. // Narrow C++ traits has fold_case() member function.
  606. template<>
  607. struct has_fold_case<cpp_regex_traits<char> >
  608. : mpl::true_
  609. {
  610. };
  611. }}
  612. #endif