w32_regex_traits.hpp 24 KB

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