w32_regex_traits.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /*
  2. *
  3. * Copyright (c) 2004
  4. * John Maddock
  5. *
  6. * Use, modification and distribution are subject to the
  7. * Boost Software License, Version 1.0. (See accompanying file
  8. * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. */
  11. /*
  12. * LOCATION: see http://www.boost.org for most recent version.
  13. * FILE w32_regex_traits.hpp
  14. * VERSION see <boost/version.hpp>
  15. * DESCRIPTION: Declares regular expression traits class w32_regex_traits.
  16. */
  17. #ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
  18. #define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
  19. #ifndef BOOST_RE_PAT_EXCEPT_HPP
  20. #include <boost/regex/pattern_except.hpp>
  21. #endif
  22. #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
  23. #include <boost/regex/v4/regex_traits_defaults.hpp>
  24. #endif
  25. #ifdef BOOST_HAS_THREADS
  26. #include <boost/regex/pending/static_mutex.hpp>
  27. #endif
  28. #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
  29. #include <boost/regex/v4/primary_transform.hpp>
  30. #endif
  31. #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
  32. #include <boost/regex/pending/object_cache.hpp>
  33. #endif
  34. #ifdef BOOST_MSVC
  35. #pragma warning(push)
  36. #pragma warning(disable: 4103)
  37. #endif
  38. #ifdef BOOST_HAS_ABI_HEADERS
  39. # include BOOST_ABI_PREFIX
  40. #endif
  41. #ifdef BOOST_MSVC
  42. #pragma warning(pop)
  43. #endif
  44. #ifdef BOOST_MSVC
  45. #pragma warning(push)
  46. #pragma warning(disable:4786)
  47. #pragma warning(disable:4800)
  48. #endif
  49. namespace boost{
  50. //
  51. // forward declaration is needed by some compilers:
  52. //
  53. template <class charT>
  54. class w32_regex_traits;
  55. namespace re_detail{
  56. //
  57. // start by typedeffing the types we'll need:
  58. //
  59. typedef ::boost::uint32_t lcid_type; // placeholder for LCID.
  60. typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE.
  61. //
  62. // then add wrappers around the actual Win32 API's (ie implementation hiding):
  63. //
  64. BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale();
  65. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
  66. #ifndef BOOST_NO_WREGEX
  67. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
  68. #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
  69. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(unsigned short ca, lcid_type state_id);
  70. #endif
  71. #endif
  72. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
  73. #ifndef BOOST_NO_WREGEX
  74. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
  75. #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
  76. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(unsigned short ca, lcid_type state_id);
  77. #endif
  78. #endif
  79. BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
  80. BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
  81. #ifndef BOOST_NO_WREGEX
  82. BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
  83. #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
  84. BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::basic_string<unsigned short>& def);
  85. #endif
  86. #endif
  87. BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
  88. #ifndef BOOST_NO_WREGEX
  89. BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
  90. #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
  91. BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transform(lcid_type state_id, const unsigned short* p1, const unsigned short* p2);
  92. #endif
  93. #endif
  94. BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
  95. #ifndef BOOST_NO_WREGEX
  96. BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
  97. #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
  98. BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_tolower(unsigned short c, lcid_type state_id);
  99. #endif
  100. #endif
  101. BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
  102. #ifndef BOOST_NO_WREGEX
  103. BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
  104. #endif
  105. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
  106. #ifndef BOOST_NO_WREGEX
  107. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
  108. #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
  109. BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type state_id, boost::uint32_t m, unsigned short c);
  110. #endif
  111. #endif
  112. //
  113. // class w32_regex_traits_base:
  114. // acts as a container for locale and the facets we are using.
  115. //
  116. template <class charT>
  117. struct w32_regex_traits_base
  118. {
  119. w32_regex_traits_base(lcid_type l)
  120. { imbue(l); }
  121. lcid_type imbue(lcid_type l);
  122. lcid_type m_locale;
  123. };
  124. template <class charT>
  125. inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l)
  126. {
  127. lcid_type result(m_locale);
  128. m_locale = l;
  129. return result;
  130. }
  131. //
  132. // class w32_regex_traits_char_layer:
  133. // implements methods that require specialisation for narrow characters:
  134. //
  135. template <class charT>
  136. class w32_regex_traits_char_layer : public w32_regex_traits_base<charT>
  137. {
  138. typedef std::basic_string<charT> string_type;
  139. typedef std::map<charT, regex_constants::syntax_type> map_type;
  140. typedef typename map_type::const_iterator map_iterator_type;
  141. public:
  142. w32_regex_traits_char_layer(const lcid_type l);
  143. regex_constants::syntax_type syntax_type(charT c)const
  144. {
  145. map_iterator_type i = m_char_map.find(c);
  146. return ((i == m_char_map.end()) ? 0 : i->second);
  147. }
  148. regex_constants::escape_syntax_type escape_syntax_type(charT c) const
  149. {
  150. map_iterator_type i = m_char_map.find(c);
  151. if(i == m_char_map.end())
  152. {
  153. if(::boost::re_detail::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class;
  154. if(::boost::re_detail::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class;
  155. return 0;
  156. }
  157. return i->second;
  158. }
  159. charT tolower(charT c)const
  160. {
  161. return ::boost::re_detail::w32_tolower(c, this->m_locale);
  162. }
  163. bool isctype(boost::uint32_t mask, charT c)const
  164. {
  165. return ::boost::re_detail::w32_is(this->m_locale, mask, c);
  166. }
  167. private:
  168. string_type get_default_message(regex_constants::syntax_type);
  169. // TODO: use a hash table when available!
  170. map_type m_char_map;
  171. };
  172. template <class charT>
  173. w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::re_detail::lcid_type l)
  174. : w32_regex_traits_base<charT>(l)
  175. {
  176. // we need to start by initialising our syntax map so we know which
  177. // character is used for which purpose:
  178. cat_type cat;
  179. std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
  180. if(cat_name.size())
  181. {
  182. cat = ::boost::re_detail::w32_cat_open(cat_name);
  183. if(!cat)
  184. {
  185. std::string m("Unable to open message catalog: ");
  186. std::runtime_error err(m + cat_name);
  187. boost::re_detail::raise_runtime_error(err);
  188. }
  189. }
  190. //
  191. // if we have a valid catalog then load our messages:
  192. //
  193. if(cat)
  194. {
  195. for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
  196. {
  197. string_type mss = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i, get_default_message(i));
  198. for(typename string_type::size_type j = 0; j < mss.size(); ++j)
  199. {
  200. this->m_char_map[mss[j]] = i;
  201. }
  202. }
  203. }
  204. else
  205. {
  206. for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
  207. {
  208. const char* ptr = get_default_syntax(i);
  209. while(ptr && *ptr)
  210. {
  211. this->m_char_map[static_cast<charT>(*ptr)] = i;
  212. ++ptr;
  213. }
  214. }
  215. }
  216. }
  217. template <class charT>
  218. typename w32_regex_traits_char_layer<charT>::string_type
  219. w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
  220. {
  221. const char* ptr = get_default_syntax(i);
  222. string_type result;
  223. while(ptr && *ptr)
  224. {
  225. result.append(1, static_cast<charT>(*ptr));
  226. ++ptr;
  227. }
  228. return result;
  229. }
  230. //
  231. // specialised version for narrow characters:
  232. //
  233. template <>
  234. class BOOST_REGEX_DECL w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
  235. {
  236. typedef std::string string_type;
  237. public:
  238. w32_regex_traits_char_layer(::boost::re_detail::lcid_type l)
  239. : w32_regex_traits_base<char>(l)
  240. {
  241. init();
  242. }
  243. regex_constants::syntax_type syntax_type(char c)const
  244. {
  245. return m_char_map[static_cast<unsigned char>(c)];
  246. }
  247. regex_constants::escape_syntax_type escape_syntax_type(char c) const
  248. {
  249. return m_char_map[static_cast<unsigned char>(c)];
  250. }
  251. char tolower(char c)const
  252. {
  253. return m_lower_map[static_cast<unsigned char>(c)];
  254. }
  255. bool isctype(boost::uint32_t mask, char c)const
  256. {
  257. return m_type_map[static_cast<unsigned char>(c)] & mask;
  258. }
  259. private:
  260. regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
  261. char m_lower_map[1u << CHAR_BIT];
  262. boost::uint16_t m_type_map[1u << CHAR_BIT];
  263. void init();
  264. };
  265. //
  266. // class w32_regex_traits_implementation:
  267. // provides pimpl implementation for w32_regex_traits.
  268. //
  269. template <class charT>
  270. class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT>
  271. {
  272. public:
  273. typedef typename w32_regex_traits<charT>::char_class_type char_class_type;
  274. BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1
  275. BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2
  276. BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3
  277. BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4
  278. BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff); // all the masks used by the CT_CTYPE1 group
  279. typedef std::basic_string<charT> string_type;
  280. typedef charT char_type;
  281. w32_regex_traits_implementation(::boost::re_detail::lcid_type l);
  282. std::string error_string(regex_constants::error_type n) const
  283. {
  284. if(!m_error_strings.empty())
  285. {
  286. std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
  287. return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
  288. }
  289. return get_default_error_string(n);
  290. }
  291. char_class_type lookup_classname(const charT* p1, const charT* p2) const
  292. {
  293. char_class_type result = lookup_classname_imp(p1, p2);
  294. if(result == 0)
  295. {
  296. typedef typename string_type::size_type size_type;
  297. string_type temp(p1, p2);
  298. for(size_type i = 0; i < temp.size(); ++i)
  299. temp[i] = this->tolower(temp[i]);
  300. result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
  301. }
  302. return result;
  303. }
  304. string_type lookup_collatename(const charT* p1, const charT* p2) const;
  305. string_type transform_primary(const charT* p1, const charT* p2) const;
  306. string_type transform(const charT* p1, const charT* p2) const
  307. {
  308. return ::boost::re_detail::w32_transform(this->m_locale, p1, p2);
  309. }
  310. private:
  311. std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID
  312. std::map<string_type, char_class_type> m_custom_class_names; // character class names
  313. std::map<string_type, string_type> m_custom_collate_names; // collating element names
  314. unsigned m_collate_type; // the form of the collation string
  315. charT m_collate_delim; // the collation group delimiter
  316. //
  317. // helpers:
  318. //
  319. char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
  320. };
  321. template <class charT>
  322. typename w32_regex_traits_implementation<charT>::string_type
  323. w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
  324. {
  325. string_type result;
  326. //
  327. // What we do here depends upon the format of the sort key returned by
  328. // sort key returned by this->transform:
  329. //
  330. switch(m_collate_type)
  331. {
  332. case sort_C:
  333. case sort_unknown:
  334. // the best we can do is translate to lower case, then get a regular sort key:
  335. {
  336. result.assign(p1, p2);
  337. typedef typename string_type::size_type size_type;
  338. for(size_type i = 0; i < result.size(); ++i)
  339. result[i] = this->tolower(result[i]);
  340. result = this->transform(&*result.begin(), &*result.begin() + result.size());
  341. break;
  342. }
  343. case sort_fixed:
  344. {
  345. // get a regular sort key, and then truncate it:
  346. result.assign(this->transform(p1, p2));
  347. result.erase(this->m_collate_delim);
  348. break;
  349. }
  350. case sort_delim:
  351. // get a regular sort key, and then truncate everything after the delim:
  352. result.assign(this->transform(p1, p2));
  353. std::size_t i;
  354. for(i = 0; i < result.size(); ++i)
  355. {
  356. if(result[i] == m_collate_delim)
  357. break;
  358. }
  359. result.erase(i);
  360. break;
  361. }
  362. if(result.empty())
  363. result = string_type(1, charT(0));
  364. return result;
  365. }
  366. template <class charT>
  367. typename w32_regex_traits_implementation<charT>::string_type
  368. w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
  369. {
  370. typedef typename std::map<string_type, string_type>::const_iterator iter_type;
  371. if(m_custom_collate_names.size())
  372. {
  373. iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
  374. if(pos != m_custom_collate_names.end())
  375. return pos->second;
  376. }
  377. #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
  378. && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
  379. && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
  380. std::string name(p1, p2);
  381. #else
  382. std::string name;
  383. const charT* p0 = p1;
  384. while(p0 != p2)
  385. name.append(1, char(*p0++));
  386. #endif
  387. name = lookup_default_collate_name(name);
  388. #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
  389. && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
  390. && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
  391. if(name.size())
  392. return string_type(name.begin(), name.end());
  393. #else
  394. if(name.size())
  395. {
  396. string_type result;
  397. typedef std::string::const_iterator iter;
  398. iter b = name.begin();
  399. iter e = name.end();
  400. while(b != e)
  401. result.append(1, charT(*b++));
  402. return result;
  403. }
  404. #endif
  405. if(p2 - p1 == 1)
  406. return string_type(1, *p1);
  407. return string_type();
  408. }
  409. template <class charT>
  410. w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::re_detail::lcid_type l)
  411. : w32_regex_traits_char_layer<charT>(l)
  412. {
  413. cat_type cat;
  414. std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
  415. if(cat_name.size())
  416. {
  417. cat = ::boost::re_detail::w32_cat_open(cat_name);
  418. if(!cat)
  419. {
  420. std::string m("Unable to open message catalog: ");
  421. std::runtime_error err(m + cat_name);
  422. boost::re_detail::raise_runtime_error(err);
  423. }
  424. }
  425. //
  426. // if we have a valid catalog then load our messages:
  427. //
  428. if(cat)
  429. {
  430. //
  431. // Error messages:
  432. //
  433. for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
  434. i <= boost::regex_constants::error_unknown;
  435. i = static_cast<boost::regex_constants::error_type>(i + 1))
  436. {
  437. const char* p = get_default_error_string(i);
  438. string_type default_message;
  439. while(*p)
  440. {
  441. default_message.append(1, static_cast<charT>(*p));
  442. ++p;
  443. }
  444. string_type s = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i+200, default_message);
  445. std::string result;
  446. for(std::string::size_type j = 0; j < s.size(); ++j)
  447. {
  448. result.append(1, static_cast<char>(s[j]));
  449. }
  450. m_error_strings[i] = result;
  451. }
  452. //
  453. // Custom class names:
  454. //
  455. static const char_class_type masks[14] =
  456. {
  457. 0x0104u, // C1_ALPHA | C1_DIGIT
  458. 0x0100u, // C1_ALPHA
  459. 0x0020u, // C1_CNTRL
  460. 0x0004u, // C1_DIGIT
  461. (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE
  462. 0x0002u, // C1_LOWER
  463. (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
  464. 0x0010u, // C1_PUNCT
  465. 0x0008u, // C1_SPACE
  466. 0x0001u, // C1_UPPER
  467. 0x0080u, // C1_XDIGIT
  468. 0x0040u, // C1_BLANK
  469. w32_regex_traits_implementation<charT>::mask_word,
  470. w32_regex_traits_implementation<charT>::mask_unicode,
  471. };
  472. static const string_type null_string;
  473. for(unsigned int j = 0; j <= 13; ++j)
  474. {
  475. string_type s(::boost::re_detail::w32_cat_get(cat, this->m_locale, j+300, null_string));
  476. if(s.size())
  477. this->m_custom_class_names[s] = masks[j];
  478. }
  479. }
  480. //
  481. // get the collation format used by m_pcollate:
  482. //
  483. m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim);
  484. }
  485. template <class charT>
  486. typename w32_regex_traits_implementation<charT>::char_class_type
  487. w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
  488. {
  489. static const char_class_type masks[22] =
  490. {
  491. 0,
  492. 0x0104u, // C1_ALPHA | C1_DIGIT
  493. 0x0100u, // C1_ALPHA
  494. 0x0040u, // C1_BLANK
  495. 0x0020u, // C1_CNTRL
  496. 0x0004u, // C1_DIGIT
  497. 0x0004u, // C1_DIGIT
  498. (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK
  499. w32_regex_traits_implementation<charT>::mask_horizontal,
  500. 0x0002u, // C1_LOWER
  501. 0x0002u, // C1_LOWER
  502. (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
  503. 0x0010u, // C1_PUNCT
  504. 0x0008u, // C1_SPACE
  505. 0x0008u, // C1_SPACE
  506. 0x0001u, // C1_UPPER
  507. w32_regex_traits_implementation<charT>::mask_unicode,
  508. 0x0001u, // C1_UPPER
  509. w32_regex_traits_implementation<charT>::mask_vertical,
  510. 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
  511. 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
  512. 0x0080u, // C1_XDIGIT
  513. };
  514. if(m_custom_class_names.size())
  515. {
  516. typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
  517. map_iter pos = m_custom_class_names.find(string_type(p1, p2));
  518. if(pos != m_custom_class_names.end())
  519. return pos->second;
  520. }
  521. std::size_t state_id = 1 + re_detail::get_default_class_id(p1, p2);
  522. if(state_id < sizeof(masks) / sizeof(masks[0]))
  523. return masks[state_id];
  524. return masks[0];
  525. }
  526. template <class charT>
  527. boost::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::re_detail::lcid_type l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT))
  528. {
  529. // TODO: create a cache for previously constructed objects.
  530. return boost::object_cache< ::boost::re_detail::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
  531. }
  532. } // re_detail
  533. template <class charT>
  534. class w32_regex_traits
  535. {
  536. public:
  537. typedef charT char_type;
  538. typedef std::size_t size_type;
  539. typedef std::basic_string<char_type> string_type;
  540. typedef ::boost::re_detail::lcid_type locale_type;
  541. typedef boost::uint_least32_t char_class_type;
  542. struct boost_extensions_tag{};
  543. w32_regex_traits()
  544. : m_pimpl(re_detail::create_w32_regex_traits<charT>(::boost::re_detail::w32_get_default_locale()))
  545. { }
  546. static size_type length(const char_type* p)
  547. {
  548. return std::char_traits<charT>::length(p);
  549. }
  550. regex_constants::syntax_type syntax_type(charT c)const
  551. {
  552. return m_pimpl->syntax_type(c);
  553. }
  554. regex_constants::escape_syntax_type escape_syntax_type(charT c) const
  555. {
  556. return m_pimpl->escape_syntax_type(c);
  557. }
  558. charT translate(charT c) const
  559. {
  560. return c;
  561. }
  562. charT translate_nocase(charT c) const
  563. {
  564. return this->m_pimpl->tolower(c);
  565. }
  566. charT translate(charT c, bool icase) const
  567. {
  568. return icase ? this->m_pimpl->tolower(c) : c;
  569. }
  570. charT tolower(charT c) const
  571. {
  572. return this->m_pimpl->tolower(c);
  573. }
  574. charT toupper(charT c) const
  575. {
  576. return ::boost::re_detail::w32_toupper(c, this->m_pimpl->m_locale);
  577. }
  578. string_type transform(const charT* p1, const charT* p2) const
  579. {
  580. return ::boost::re_detail::w32_transform(this->m_pimpl->m_locale, p1, p2);
  581. }
  582. string_type transform_primary(const charT* p1, const charT* p2) const
  583. {
  584. return m_pimpl->transform_primary(p1, p2);
  585. }
  586. char_class_type lookup_classname(const charT* p1, const charT* p2) const
  587. {
  588. return m_pimpl->lookup_classname(p1, p2);
  589. }
  590. string_type lookup_collatename(const charT* p1, const charT* p2) const
  591. {
  592. return m_pimpl->lookup_collatename(p1, p2);
  593. }
  594. bool isctype(charT c, char_class_type f) const
  595. {
  596. if((f & re_detail::w32_regex_traits_implementation<charT>::mask_base)
  597. && (this->m_pimpl->isctype(f & re_detail::w32_regex_traits_implementation<charT>::mask_base, c)))
  598. return true;
  599. else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c))
  600. return true;
  601. else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_word) && (c == '_'))
  602. return true;
  603. else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_vertical)
  604. && (::boost::re_detail::is_separator(c) || (c == '\v')))
  605. return true;
  606. else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_horizontal)
  607. && this->isctype(c, 0x0008u) && !this->isctype(c, re_detail::w32_regex_traits_implementation<charT>::mask_vertical))
  608. return true;
  609. return false;
  610. }
  611. int toi(const charT*& p1, const charT* p2, int radix)const
  612. {
  613. return ::boost::re_detail::global_toi(p1, p2, radix, *this);
  614. }
  615. int value(charT c, int radix)const
  616. {
  617. int result = ::boost::re_detail::global_value(c);
  618. return result < radix ? result : -1;
  619. }
  620. locale_type imbue(locale_type l)
  621. {
  622. ::boost::re_detail::lcid_type result(getloc());
  623. m_pimpl = re_detail::create_w32_regex_traits<charT>(l);
  624. return result;
  625. }
  626. locale_type getloc()const
  627. {
  628. return m_pimpl->m_locale;
  629. }
  630. std::string error_string(regex_constants::error_type n) const
  631. {
  632. return m_pimpl->error_string(n);
  633. }
  634. //
  635. // extension:
  636. // set the name of the message catalog in use (defaults to "boost_regex").
  637. //
  638. static std::string catalog_name(const std::string& name);
  639. static std::string get_catalog_name();
  640. private:
  641. boost::shared_ptr<const re_detail::w32_regex_traits_implementation<charT> > m_pimpl;
  642. //
  643. // catalog name handler:
  644. //
  645. static std::string& get_catalog_name_inst();
  646. #ifdef BOOST_HAS_THREADS
  647. static static_mutex& get_mutex_inst();
  648. #endif
  649. };
  650. template <class charT>
  651. std::string w32_regex_traits<charT>::catalog_name(const std::string& name)
  652. {
  653. #ifdef BOOST_HAS_THREADS
  654. static_mutex::scoped_lock lk(get_mutex_inst());
  655. #endif
  656. std::string result(get_catalog_name_inst());
  657. get_catalog_name_inst() = name;
  658. return result;
  659. }
  660. template <class charT>
  661. std::string& w32_regex_traits<charT>::get_catalog_name_inst()
  662. {
  663. static std::string s_name;
  664. return s_name;
  665. }
  666. template <class charT>
  667. std::string w32_regex_traits<charT>::get_catalog_name()
  668. {
  669. #ifdef BOOST_HAS_THREADS
  670. static_mutex::scoped_lock lk(get_mutex_inst());
  671. #endif
  672. std::string result(get_catalog_name_inst());
  673. return result;
  674. }
  675. #ifdef BOOST_HAS_THREADS
  676. template <class charT>
  677. static_mutex& w32_regex_traits<charT>::get_mutex_inst()
  678. {
  679. static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
  680. return s_mutex;
  681. }
  682. #endif
  683. } // boost
  684. #ifdef BOOST_MSVC
  685. #pragma warning(pop)
  686. #endif
  687. #ifdef BOOST_MSVC
  688. #pragma warning(push)
  689. #pragma warning(disable: 4103)
  690. #endif
  691. #ifdef BOOST_HAS_ABI_HEADERS
  692. # include BOOST_ABI_SUFFIX
  693. #endif
  694. #ifdef BOOST_MSVC
  695. #pragma warning(pop)
  696. #endif
  697. #endif