w32_regex_traits.hpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  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/v4/object_cache.hpp>
  34. #endif
  35. #define VC_EXTRALEAN
  36. #define WIN32_LEAN_AND_MEAN
  37. #include <windows.h>
  38. #if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
  39. #pragma comment(lib, "user32.lib")
  40. #endif
  41. #ifdef BOOST_MSVC
  42. #pragma warning(push)
  43. #pragma warning(disable: 4103)
  44. #endif
  45. #ifdef BOOST_HAS_ABI_HEADERS
  46. # include BOOST_ABI_PREFIX
  47. #endif
  48. #ifdef BOOST_MSVC
  49. #pragma warning(pop)
  50. #endif
  51. #ifdef BOOST_MSVC
  52. #pragma warning(push)
  53. #pragma warning(disable:4786)
  54. #if BOOST_MSVC < 1910
  55. #pragma warning(disable:4800)
  56. #endif
  57. #endif
  58. namespace boost{
  59. //
  60. // forward declaration is needed by some compilers:
  61. //
  62. template <class charT>
  63. class w32_regex_traits;
  64. namespace BOOST_REGEX_DETAIL_NS{
  65. //
  66. // start by typedeffing the types we'll need:
  67. //
  68. typedef ::boost::uint32_t lcid_type; // placeholder for LCID.
  69. typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE.
  70. //
  71. // then add wrappers around the actual Win32 API's (ie implementation hiding):
  72. //
  73. lcid_type BOOST_REGEX_CALL w32_get_default_locale();
  74. bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
  75. #ifndef BOOST_NO_WREGEX
  76. bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
  77. #endif
  78. bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
  79. #ifndef BOOST_NO_WREGEX
  80. bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
  81. #endif
  82. cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
  83. std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
  84. #ifndef BOOST_NO_WREGEX
  85. std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
  86. #endif
  87. std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
  88. #ifndef BOOST_NO_WREGEX
  89. std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
  90. #endif
  91. char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
  92. #ifndef BOOST_NO_WREGEX
  93. wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
  94. #endif
  95. char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
  96. #ifndef BOOST_NO_WREGEX
  97. wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
  98. #endif
  99. bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
  100. #ifndef BOOST_NO_WREGEX
  101. bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
  102. #endif
  103. //
  104. // class w32_regex_traits_base:
  105. // acts as a container for locale and the facets we are using.
  106. //
  107. template <class charT>
  108. struct w32_regex_traits_base
  109. {
  110. w32_regex_traits_base(lcid_type l)
  111. { imbue(l); }
  112. lcid_type imbue(lcid_type l);
  113. lcid_type m_locale;
  114. };
  115. template <class charT>
  116. inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l)
  117. {
  118. lcid_type result(m_locale);
  119. m_locale = l;
  120. return result;
  121. }
  122. //
  123. // class w32_regex_traits_char_layer:
  124. // implements methods that require specialisation for narrow characters:
  125. //
  126. template <class charT>
  127. class w32_regex_traits_char_layer : public w32_regex_traits_base<charT>
  128. {
  129. typedef std::basic_string<charT> string_type;
  130. typedef std::map<charT, regex_constants::syntax_type> map_type;
  131. typedef typename map_type::const_iterator map_iterator_type;
  132. public:
  133. w32_regex_traits_char_layer(const lcid_type l);
  134. regex_constants::syntax_type syntax_type(charT c)const
  135. {
  136. map_iterator_type i = m_char_map.find(c);
  137. return ((i == m_char_map.end()) ? 0 : i->second);
  138. }
  139. regex_constants::escape_syntax_type escape_syntax_type(charT c) const
  140. {
  141. map_iterator_type i = m_char_map.find(c);
  142. if(i == m_char_map.end())
  143. {
  144. if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class;
  145. if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class;
  146. return 0;
  147. }
  148. return i->second;
  149. }
  150. charT tolower(charT c)const
  151. {
  152. return ::boost::BOOST_REGEX_DETAIL_NS::w32_tolower(c, this->m_locale);
  153. }
  154. bool isctype(boost::uint32_t mask, charT c)const
  155. {
  156. return ::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, mask, c);
  157. }
  158. private:
  159. string_type get_default_message(regex_constants::syntax_type);
  160. // TODO: use a hash table when available!
  161. map_type m_char_map;
  162. };
  163. template <class charT>
  164. w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
  165. : w32_regex_traits_base<charT>(l)
  166. {
  167. // we need to start by initialising our syntax map so we know which
  168. // character is used for which purpose:
  169. cat_type cat;
  170. std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
  171. if(cat_name.size())
  172. {
  173. cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
  174. if(!cat)
  175. {
  176. std::string m("Unable to open message catalog: ");
  177. std::runtime_error err(m + cat_name);
  178. boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
  179. }
  180. }
  181. //
  182. // if we have a valid catalog then load our messages:
  183. //
  184. if(cat)
  185. {
  186. for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
  187. {
  188. string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_message(i));
  189. for(typename string_type::size_type j = 0; j < mss.size(); ++j)
  190. {
  191. this->m_char_map[mss[j]] = i;
  192. }
  193. }
  194. }
  195. else
  196. {
  197. for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
  198. {
  199. const char* ptr = get_default_syntax(i);
  200. while(ptr && *ptr)
  201. {
  202. this->m_char_map[static_cast<charT>(*ptr)] = i;
  203. ++ptr;
  204. }
  205. }
  206. }
  207. }
  208. template <class charT>
  209. typename w32_regex_traits_char_layer<charT>::string_type
  210. w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
  211. {
  212. const char* ptr = get_default_syntax(i);
  213. string_type result;
  214. while(ptr && *ptr)
  215. {
  216. result.append(1, static_cast<charT>(*ptr));
  217. ++ptr;
  218. }
  219. return result;
  220. }
  221. //
  222. // specialised version for narrow characters:
  223. //
  224. template <>
  225. class w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
  226. {
  227. typedef std::string string_type;
  228. public:
  229. w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
  230. : w32_regex_traits_base<char>(l)
  231. {
  232. init<char>();
  233. }
  234. regex_constants::syntax_type syntax_type(char c)const
  235. {
  236. return m_char_map[static_cast<unsigned char>(c)];
  237. }
  238. regex_constants::escape_syntax_type escape_syntax_type(char c) const
  239. {
  240. return m_char_map[static_cast<unsigned char>(c)];
  241. }
  242. char tolower(char c)const
  243. {
  244. return m_lower_map[static_cast<unsigned char>(c)];
  245. }
  246. bool isctype(boost::uint32_t mask, char c)const
  247. {
  248. return m_type_map[static_cast<unsigned char>(c)] & mask;
  249. }
  250. private:
  251. regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
  252. char m_lower_map[1u << CHAR_BIT];
  253. boost::uint16_t m_type_map[1u << CHAR_BIT];
  254. template <class U>
  255. void init();
  256. };
  257. //
  258. // class w32_regex_traits_implementation:
  259. // provides pimpl implementation for w32_regex_traits.
  260. //
  261. template <class charT>
  262. class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT>
  263. {
  264. public:
  265. typedef typename w32_regex_traits<charT>::char_class_type char_class_type;
  266. BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1
  267. BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2
  268. BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3
  269. BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4
  270. BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff); // all the masks used by the CT_CTYPE1 group
  271. typedef std::basic_string<charT> string_type;
  272. typedef charT char_type;
  273. w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l);
  274. std::string error_string(regex_constants::error_type n) const
  275. {
  276. if(!m_error_strings.empty())
  277. {
  278. std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
  279. return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
  280. }
  281. return get_default_error_string(n);
  282. }
  283. char_class_type lookup_classname(const charT* p1, const charT* p2) const
  284. {
  285. char_class_type result = lookup_classname_imp(p1, p2);
  286. if(result == 0)
  287. {
  288. typedef typename string_type::size_type size_type;
  289. string_type temp(p1, p2);
  290. for(size_type i = 0; i < temp.size(); ++i)
  291. temp[i] = this->tolower(temp[i]);
  292. result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
  293. }
  294. return result;
  295. }
  296. string_type lookup_collatename(const charT* p1, const charT* p2) const;
  297. string_type transform_primary(const charT* p1, const charT* p2) const;
  298. string_type transform(const charT* p1, const charT* p2) const
  299. {
  300. return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_locale, p1, p2);
  301. }
  302. private:
  303. std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID
  304. std::map<string_type, char_class_type> m_custom_class_names; // character class names
  305. std::map<string_type, string_type> m_custom_collate_names; // collating element names
  306. unsigned m_collate_type; // the form of the collation string
  307. charT m_collate_delim; // the collation group delimiter
  308. //
  309. // helpers:
  310. //
  311. char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
  312. };
  313. template <class charT>
  314. typename w32_regex_traits_implementation<charT>::string_type
  315. w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
  316. {
  317. string_type result;
  318. //
  319. // What we do here depends upon the format of the sort key returned by
  320. // sort key returned by this->transform:
  321. //
  322. switch(m_collate_type)
  323. {
  324. case sort_C:
  325. case sort_unknown:
  326. // the best we can do is translate to lower case, then get a regular sort key:
  327. {
  328. result.assign(p1, p2);
  329. typedef typename string_type::size_type size_type;
  330. for(size_type i = 0; i < result.size(); ++i)
  331. result[i] = this->tolower(result[i]);
  332. result = this->transform(&*result.begin(), &*result.begin() + result.size());
  333. break;
  334. }
  335. case sort_fixed:
  336. {
  337. // get a regular sort key, and then truncate it:
  338. result.assign(this->transform(p1, p2));
  339. result.erase(this->m_collate_delim);
  340. break;
  341. }
  342. case sort_delim:
  343. // get a regular sort key, and then truncate everything after the delim:
  344. result.assign(this->transform(p1, p2));
  345. std::size_t i;
  346. for(i = 0; i < result.size(); ++i)
  347. {
  348. if(result[i] == m_collate_delim)
  349. break;
  350. }
  351. result.erase(i);
  352. break;
  353. }
  354. if(result.empty())
  355. result = string_type(1, charT(0));
  356. return result;
  357. }
  358. template <class charT>
  359. typename w32_regex_traits_implementation<charT>::string_type
  360. w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
  361. {
  362. typedef typename std::map<string_type, string_type>::const_iterator iter_type;
  363. if(m_custom_collate_names.size())
  364. {
  365. iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
  366. if(pos != m_custom_collate_names.end())
  367. return pos->second;
  368. }
  369. #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
  370. && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
  371. std::string name(p1, p2);
  372. #else
  373. std::string name;
  374. const charT* p0 = p1;
  375. while(p0 != p2)
  376. name.append(1, char(*p0++));
  377. #endif
  378. name = lookup_default_collate_name(name);
  379. #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
  380. && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
  381. if(name.size())
  382. return string_type(name.begin(), name.end());
  383. #else
  384. if(name.size())
  385. {
  386. string_type result;
  387. typedef std::string::const_iterator iter;
  388. iter b = name.begin();
  389. iter e = name.end();
  390. while(b != e)
  391. result.append(1, charT(*b++));
  392. return result;
  393. }
  394. #endif
  395. if(p2 - p1 == 1)
  396. return string_type(1, *p1);
  397. return string_type();
  398. }
  399. template <class charT>
  400. w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
  401. : w32_regex_traits_char_layer<charT>(l)
  402. {
  403. cat_type cat;
  404. std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
  405. if(cat_name.size())
  406. {
  407. cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
  408. if(!cat)
  409. {
  410. std::string m("Unable to open message catalog: ");
  411. std::runtime_error err(m + cat_name);
  412. boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
  413. }
  414. }
  415. //
  416. // if we have a valid catalog then load our messages:
  417. //
  418. if(cat)
  419. {
  420. //
  421. // Error messages:
  422. //
  423. for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
  424. i <= boost::regex_constants::error_unknown;
  425. i = static_cast<boost::regex_constants::error_type>(i + 1))
  426. {
  427. const char* p = get_default_error_string(i);
  428. string_type default_message;
  429. while(*p)
  430. {
  431. default_message.append(1, static_cast<charT>(*p));
  432. ++p;
  433. }
  434. string_type s = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i+200, default_message);
  435. std::string result;
  436. for(std::string::size_type j = 0; j < s.size(); ++j)
  437. {
  438. result.append(1, static_cast<char>(s[j]));
  439. }
  440. m_error_strings[i] = result;
  441. }
  442. //
  443. // Custom class names:
  444. //
  445. static const char_class_type masks[14] =
  446. {
  447. 0x0104u, // C1_ALPHA | C1_DIGIT
  448. 0x0100u, // C1_ALPHA
  449. 0x0020u, // C1_CNTRL
  450. 0x0004u, // C1_DIGIT
  451. (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE
  452. 0x0002u, // C1_LOWER
  453. (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
  454. 0x0010u, // C1_PUNCT
  455. 0x0008u, // C1_SPACE
  456. 0x0001u, // C1_UPPER
  457. 0x0080u, // C1_XDIGIT
  458. 0x0040u, // C1_BLANK
  459. w32_regex_traits_implementation<charT>::mask_word,
  460. w32_regex_traits_implementation<charT>::mask_unicode,
  461. };
  462. static const string_type null_string;
  463. for(unsigned int j = 0; j <= 13; ++j)
  464. {
  465. string_type s(::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, j+300, null_string));
  466. if(s.size())
  467. this->m_custom_class_names[s] = masks[j];
  468. }
  469. }
  470. //
  471. // get the collation format used by m_pcollate:
  472. //
  473. m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim);
  474. }
  475. template <class charT>
  476. typename w32_regex_traits_implementation<charT>::char_class_type
  477. w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
  478. {
  479. static const char_class_type masks[22] =
  480. {
  481. 0,
  482. 0x0104u, // C1_ALPHA | C1_DIGIT
  483. 0x0100u, // C1_ALPHA
  484. 0x0040u, // C1_BLANK
  485. 0x0020u, // C1_CNTRL
  486. 0x0004u, // C1_DIGIT
  487. 0x0004u, // C1_DIGIT
  488. (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK
  489. w32_regex_traits_implementation<charT>::mask_horizontal,
  490. 0x0002u, // C1_LOWER
  491. 0x0002u, // C1_LOWER
  492. (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
  493. 0x0010u, // C1_PUNCT
  494. 0x0008u, // C1_SPACE
  495. 0x0008u, // C1_SPACE
  496. 0x0001u, // C1_UPPER
  497. w32_regex_traits_implementation<charT>::mask_unicode,
  498. 0x0001u, // C1_UPPER
  499. w32_regex_traits_implementation<charT>::mask_vertical,
  500. 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
  501. 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
  502. 0x0080u, // C1_XDIGIT
  503. };
  504. if(m_custom_class_names.size())
  505. {
  506. typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
  507. map_iter pos = m_custom_class_names.find(string_type(p1, p2));
  508. if(pos != m_custom_class_names.end())
  509. return pos->second;
  510. }
  511. std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
  512. if(state_id < sizeof(masks) / sizeof(masks[0]))
  513. return masks[state_id];
  514. return masks[0];
  515. }
  516. template <class charT>
  517. boost::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
  518. {
  519. // TODO: create a cache for previously constructed objects.
  520. return boost::object_cache< ::boost::BOOST_REGEX_DETAIL_NS::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
  521. }
  522. } // BOOST_REGEX_DETAIL_NS
  523. template <class charT>
  524. class w32_regex_traits
  525. {
  526. public:
  527. typedef charT char_type;
  528. typedef std::size_t size_type;
  529. typedef std::basic_string<char_type> string_type;
  530. typedef ::boost::BOOST_REGEX_DETAIL_NS::lcid_type locale_type;
  531. typedef boost::uint_least32_t char_class_type;
  532. struct boost_extensions_tag{};
  533. w32_regex_traits()
  534. : m_pimpl(BOOST_REGEX_DETAIL_NS::create_w32_regex_traits<charT>(::boost::BOOST_REGEX_DETAIL_NS::w32_get_default_locale()))
  535. { }
  536. static size_type length(const char_type* p)
  537. {
  538. return std::char_traits<charT>::length(p);
  539. }
  540. regex_constants::syntax_type syntax_type(charT c)const
  541. {
  542. return m_pimpl->syntax_type(c);
  543. }
  544. regex_constants::escape_syntax_type escape_syntax_type(charT c) const
  545. {
  546. return m_pimpl->escape_syntax_type(c);
  547. }
  548. charT translate(charT c) const
  549. {
  550. return c;
  551. }
  552. charT translate_nocase(charT c) const
  553. {
  554. return this->m_pimpl->tolower(c);
  555. }
  556. charT translate(charT c, bool icase) const
  557. {
  558. return icase ? this->m_pimpl->tolower(c) : c;
  559. }
  560. charT tolower(charT c) const
  561. {
  562. return this->m_pimpl->tolower(c);
  563. }
  564. charT toupper(charT c) const
  565. {
  566. return ::boost::BOOST_REGEX_DETAIL_NS::w32_toupper(c, this->m_pimpl->m_locale);
  567. }
  568. string_type transform(const charT* p1, const charT* p2) const
  569. {
  570. return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_pimpl->m_locale, p1, p2);
  571. }
  572. string_type transform_primary(const charT* p1, const charT* p2) const
  573. {
  574. return m_pimpl->transform_primary(p1, p2);
  575. }
  576. char_class_type lookup_classname(const charT* p1, const charT* p2) const
  577. {
  578. return m_pimpl->lookup_classname(p1, p2);
  579. }
  580. string_type lookup_collatename(const charT* p1, const charT* p2) const
  581. {
  582. return m_pimpl->lookup_collatename(p1, p2);
  583. }
  584. bool isctype(charT c, char_class_type f) const
  585. {
  586. if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_base)
  587. && (this->m_pimpl->isctype(f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_base, c)))
  588. return true;
  589. else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c))
  590. return true;
  591. else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_word) && (c == '_'))
  592. return true;
  593. else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_vertical)
  594. && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
  595. return true;
  596. else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_horizontal)
  597. && this->isctype(c, 0x0008u) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_vertical))
  598. return true;
  599. return false;
  600. }
  601. boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const
  602. {
  603. return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
  604. }
  605. int value(charT c, int radix)const
  606. {
  607. int result = (int)::boost::BOOST_REGEX_DETAIL_NS::global_value(c);
  608. return result < radix ? result : -1;
  609. }
  610. locale_type imbue(locale_type l)
  611. {
  612. ::boost::BOOST_REGEX_DETAIL_NS::lcid_type result(getloc());
  613. m_pimpl = BOOST_REGEX_DETAIL_NS::create_w32_regex_traits<charT>(l);
  614. return result;
  615. }
  616. locale_type getloc()const
  617. {
  618. return m_pimpl->m_locale;
  619. }
  620. std::string error_string(regex_constants::error_type n) const
  621. {
  622. return m_pimpl->error_string(n);
  623. }
  624. //
  625. // extension:
  626. // set the name of the message catalog in use (defaults to "boost_regex").
  627. //
  628. static std::string catalog_name(const std::string& name);
  629. static std::string get_catalog_name();
  630. private:
  631. boost::shared_ptr<const BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT> > m_pimpl;
  632. //
  633. // catalog name handler:
  634. //
  635. static std::string& get_catalog_name_inst();
  636. #ifdef BOOST_HAS_THREADS
  637. static static_mutex& get_mutex_inst();
  638. #endif
  639. };
  640. template <class charT>
  641. std::string w32_regex_traits<charT>::catalog_name(const std::string& name)
  642. {
  643. #ifdef BOOST_HAS_THREADS
  644. static_mutex::scoped_lock lk(get_mutex_inst());
  645. #endif
  646. std::string result(get_catalog_name_inst());
  647. get_catalog_name_inst() = name;
  648. return result;
  649. }
  650. template <class charT>
  651. std::string& w32_regex_traits<charT>::get_catalog_name_inst()
  652. {
  653. static std::string s_name;
  654. return s_name;
  655. }
  656. template <class charT>
  657. std::string w32_regex_traits<charT>::get_catalog_name()
  658. {
  659. #ifdef BOOST_HAS_THREADS
  660. static_mutex::scoped_lock lk(get_mutex_inst());
  661. #endif
  662. std::string result(get_catalog_name_inst());
  663. return result;
  664. }
  665. #ifdef BOOST_HAS_THREADS
  666. template <class charT>
  667. static_mutex& w32_regex_traits<charT>::get_mutex_inst()
  668. {
  669. static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
  670. return s_mutex;
  671. }
  672. #endif
  673. namespace BOOST_REGEX_DETAIL_NS {
  674. #ifdef BOOST_NO_ANSI_APIS
  675. inline UINT get_code_page_for_locale_id(lcid_type idx)
  676. {
  677. WCHAR code_page_string[7];
  678. if (::GetLocaleInfoW(idx, LOCALE_IDEFAULTANSICODEPAGE, code_page_string, 7) == 0)
  679. return 0;
  680. return static_cast<UINT>(_wtol(code_page_string));
  681. }
  682. #endif
  683. template <class U>
  684. inline void w32_regex_traits_char_layer<char>::init()
  685. {
  686. // we need to start by initialising our syntax map so we know which
  687. // character is used for which purpose:
  688. std::memset(m_char_map, 0, sizeof(m_char_map));
  689. cat_type cat;
  690. std::string cat_name(w32_regex_traits<char>::get_catalog_name());
  691. if (cat_name.size())
  692. {
  693. cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
  694. if (!cat)
  695. {
  696. std::string m("Unable to open message catalog: ");
  697. std::runtime_error err(m + cat_name);
  698. ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
  699. }
  700. }
  701. //
  702. // if we have a valid catalog then load our messages:
  703. //
  704. if (cat)
  705. {
  706. for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
  707. {
  708. string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i));
  709. for (string_type::size_type j = 0; j < mss.size(); ++j)
  710. {
  711. m_char_map[static_cast<unsigned char>(mss[j])] = i;
  712. }
  713. }
  714. }
  715. else
  716. {
  717. for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
  718. {
  719. const char* ptr = get_default_syntax(i);
  720. while (ptr && *ptr)
  721. {
  722. m_char_map[static_cast<unsigned char>(*ptr)] = i;
  723. ++ptr;
  724. }
  725. }
  726. }
  727. //
  728. // finish off by calculating our escape types:
  729. //
  730. unsigned char i = 'A';
  731. do
  732. {
  733. if (m_char_map[i] == 0)
  734. {
  735. if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0002u, (char)i))
  736. m_char_map[i] = regex_constants::escape_type_class;
  737. else if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0001u, (char)i))
  738. m_char_map[i] = regex_constants::escape_type_not_class;
  739. }
  740. } while (0xFF != i++);
  741. //
  742. // fill in lower case map:
  743. //
  744. char char_map[1 << CHAR_BIT];
  745. for (int ii = 0; ii < (1 << CHAR_BIT); ++ii)
  746. char_map[ii] = static_cast<char>(ii);
  747. #ifndef BOOST_NO_ANSI_APIS
  748. int r = ::LCMapStringA(this->m_locale, LCMAP_LOWERCASE, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT);
  749. BOOST_REGEX_ASSERT(r != 0);
  750. #else
  751. UINT code_page = get_code_page_for_locale_id(this->m_locale);
  752. BOOST_REGEX_ASSERT(code_page != 0);
  753. WCHAR wide_char_map[1 << CHAR_BIT];
  754. int conv_r = ::MultiByteToWideChar(code_page, 0, char_map, 1 << CHAR_BIT, wide_char_map, 1 << CHAR_BIT);
  755. BOOST_REGEX_ASSERT(conv_r != 0);
  756. WCHAR wide_lower_map[1 << CHAR_BIT];
  757. int r = ::LCMapStringW(this->m_locale, LCMAP_LOWERCASE, wide_char_map, 1 << CHAR_BIT, wide_lower_map, 1 << CHAR_BIT);
  758. BOOST_REGEX_ASSERT(r != 0);
  759. conv_r = ::WideCharToMultiByte(code_page, 0, wide_lower_map, r, this->m_lower_map, 1 << CHAR_BIT, NULL, NULL);
  760. BOOST_REGEX_ASSERT(conv_r != 0);
  761. #endif
  762. if (r < (1 << CHAR_BIT))
  763. {
  764. // if we have multibyte characters then not all may have been given
  765. // a lower case mapping:
  766. for (int jj = r; jj < (1 << CHAR_BIT); ++jj)
  767. this->m_lower_map[jj] = static_cast<char>(jj);
  768. }
  769. #ifndef BOOST_NO_ANSI_APIS
  770. r = ::GetStringTypeExA(this->m_locale, CT_CTYPE1, char_map, 1 << CHAR_BIT, this->m_type_map);
  771. #else
  772. r = ::GetStringTypeExW(this->m_locale, CT_CTYPE1, wide_char_map, 1 << CHAR_BIT, this->m_type_map);
  773. #endif
  774. BOOST_REGEX_ASSERT(0 != r);
  775. }
  776. inline lcid_type BOOST_REGEX_CALL w32_get_default_locale()
  777. {
  778. return ::GetUserDefaultLCID();
  779. }
  780. inline bool BOOST_REGEX_CALL w32_is_lower(char c, lcid_type idx)
  781. {
  782. #ifndef BOOST_NO_ANSI_APIS
  783. WORD mask;
  784. if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
  785. return true;
  786. return false;
  787. #else
  788. UINT code_page = get_code_page_for_locale_id(idx);
  789. if (code_page == 0)
  790. return false;
  791. WCHAR wide_c;
  792. if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
  793. return false;
  794. WORD mask;
  795. if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_LOWER))
  796. return true;
  797. return false;
  798. #endif
  799. }
  800. inline bool BOOST_REGEX_CALL w32_is_lower(wchar_t c, lcid_type idx)
  801. {
  802. WORD mask;
  803. if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
  804. return true;
  805. return false;
  806. }
  807. inline bool BOOST_REGEX_CALL w32_is_upper(char c, lcid_type idx)
  808. {
  809. #ifndef BOOST_NO_ANSI_APIS
  810. WORD mask;
  811. if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
  812. return true;
  813. return false;
  814. #else
  815. UINT code_page = get_code_page_for_locale_id(idx);
  816. if (code_page == 0)
  817. return false;
  818. WCHAR wide_c;
  819. if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
  820. return false;
  821. WORD mask;
  822. if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_UPPER))
  823. return true;
  824. return false;
  825. #endif
  826. }
  827. inline bool BOOST_REGEX_CALL w32_is_upper(wchar_t c, lcid_type idx)
  828. {
  829. WORD mask;
  830. if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
  831. return true;
  832. return false;
  833. }
  834. inline void free_module(void* mod)
  835. {
  836. ::FreeLibrary(static_cast<HMODULE>(mod));
  837. }
  838. inline cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name)
  839. {
  840. #ifndef BOOST_NO_ANSI_APIS
  841. cat_type result(::LoadLibraryA(name.c_str()), &free_module);
  842. return result;
  843. #else
  844. LPWSTR wide_name = (LPWSTR)_alloca((name.size() + 1) * sizeof(WCHAR));
  845. if (::MultiByteToWideChar(CP_ACP, 0, name.c_str(), name.size(), wide_name, name.size() + 1) == 0)
  846. return cat_type();
  847. cat_type result(::LoadLibraryW(wide_name), &free_module);
  848. return result;
  849. #endif
  850. }
  851. inline std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def)
  852. {
  853. #ifndef BOOST_NO_ANSI_APIS
  854. char buf[256];
  855. if (0 == ::LoadStringA(
  856. static_cast<HMODULE>(cat.get()),
  857. i,
  858. buf,
  859. 256
  860. ))
  861. {
  862. return def;
  863. }
  864. #else
  865. WCHAR wbuf[256];
  866. int r = ::LoadStringW(
  867. static_cast<HMODULE>(cat.get()),
  868. i,
  869. wbuf,
  870. 256
  871. );
  872. if (r == 0)
  873. return def;
  874. int buf_size = 1 + ::WideCharToMultiByte(CP_ACP, 0, wbuf, r, NULL, 0, NULL, NULL);
  875. LPSTR buf = (LPSTR)_alloca(buf_size);
  876. if (::WideCharToMultiByte(CP_ACP, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0)
  877. return def; // failed conversion.
  878. #endif
  879. return std::string(buf);
  880. }
  881. #ifndef BOOST_NO_WREGEX
  882. inline std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def)
  883. {
  884. wchar_t buf[256];
  885. if (0 == ::LoadStringW(
  886. static_cast<HMODULE>(cat.get()),
  887. i,
  888. buf,
  889. 256
  890. ))
  891. {
  892. return def;
  893. }
  894. return std::wstring(buf);
  895. }
  896. #endif
  897. inline std::string BOOST_REGEX_CALL w32_transform(lcid_type idx, const char* p1, const char* p2)
  898. {
  899. #ifndef BOOST_NO_ANSI_APIS
  900. int bytes = ::LCMapStringA(
  901. idx, // locale identifier
  902. LCMAP_SORTKEY, // mapping transformation type
  903. p1, // source string
  904. static_cast<int>(p2 - p1), // number of characters in source string
  905. 0, // destination buffer
  906. 0 // size of destination buffer
  907. );
  908. if (!bytes)
  909. return std::string(p1, p2);
  910. std::string result(++bytes, '\0');
  911. bytes = ::LCMapStringA(
  912. idx, // locale identifier
  913. LCMAP_SORTKEY, // mapping transformation type
  914. p1, // source string
  915. static_cast<int>(p2 - p1), // number of characters in source string
  916. &*result.begin(), // destination buffer
  917. bytes // size of destination buffer
  918. );
  919. #else
  920. UINT code_page = get_code_page_for_locale_id(idx);
  921. if (code_page == 0)
  922. return std::string(p1, p2);
  923. int src_len = static_cast<int>(p2 - p1);
  924. LPWSTR wide_p1 = (LPWSTR)_alloca((src_len + 1) * 2);
  925. if (::MultiByteToWideChar(code_page, 0, p1, src_len, wide_p1, src_len + 1) == 0)
  926. return std::string(p1, p2);
  927. int bytes = ::LCMapStringW(
  928. idx, // locale identifier
  929. LCMAP_SORTKEY, // mapping transformation type
  930. wide_p1, // source string
  931. src_len, // number of characters in source string
  932. 0, // destination buffer
  933. 0 // size of destination buffer
  934. );
  935. if (!bytes)
  936. return std::string(p1, p2);
  937. std::string result(++bytes, '\0');
  938. bytes = ::LCMapStringW(
  939. idx, // locale identifier
  940. LCMAP_SORTKEY, // mapping transformation type
  941. wide_p1, // source string
  942. src_len, // number of characters in source string
  943. (LPWSTR) & *result.begin(), // destination buffer
  944. bytes // size of destination buffer
  945. );
  946. #endif
  947. if (bytes > static_cast<int>(result.size()))
  948. return std::string(p1, p2);
  949. while (result.size() && result[result.size() - 1] == '\0')
  950. {
  951. result.erase(result.size() - 1);
  952. }
  953. return result;
  954. }
  955. #ifndef BOOST_NO_WREGEX
  956. inline std::wstring BOOST_REGEX_CALL w32_transform(lcid_type idx, const wchar_t* p1, const wchar_t* p2)
  957. {
  958. int bytes = ::LCMapStringW(
  959. idx, // locale identifier
  960. LCMAP_SORTKEY, // mapping transformation type
  961. p1, // source string
  962. static_cast<int>(p2 - p1), // number of characters in source string
  963. 0, // destination buffer
  964. 0 // size of destination buffer
  965. );
  966. if (!bytes)
  967. return std::wstring(p1, p2);
  968. std::string result(++bytes, '\0');
  969. bytes = ::LCMapStringW(
  970. idx, // locale identifier
  971. LCMAP_SORTKEY, // mapping transformation type
  972. p1, // source string
  973. static_cast<int>(p2 - p1), // number of characters in source string
  974. reinterpret_cast<wchar_t*>(&*result.begin()), // destination buffer *of bytes*
  975. bytes // size of destination buffer
  976. );
  977. if (bytes > static_cast<int>(result.size()))
  978. return std::wstring(p1, p2);
  979. while (result.size() && result[result.size() - 1] == L'\0')
  980. {
  981. result.erase(result.size() - 1);
  982. }
  983. std::wstring r2;
  984. for (std::string::size_type i = 0; i < result.size(); ++i)
  985. r2.append(1, static_cast<wchar_t>(static_cast<unsigned char>(result[i])));
  986. return r2;
  987. }
  988. #endif
  989. inline char BOOST_REGEX_CALL w32_tolower(char c, lcid_type idx)
  990. {
  991. char result[2];
  992. #ifndef BOOST_NO_ANSI_APIS
  993. int b = ::LCMapStringA(
  994. idx, // locale identifier
  995. LCMAP_LOWERCASE, // mapping transformation type
  996. &c, // source string
  997. 1, // number of characters in source string
  998. result, // destination buffer
  999. 1); // size of destination buffer
  1000. if (b == 0)
  1001. return c;
  1002. #else
  1003. UINT code_page = get_code_page_for_locale_id(idx);
  1004. if (code_page == 0)
  1005. return c;
  1006. WCHAR wide_c;
  1007. if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
  1008. return c;
  1009. WCHAR wide_result;
  1010. int b = ::LCMapStringW(
  1011. idx, // locale identifier
  1012. LCMAP_LOWERCASE, // mapping transformation type
  1013. &wide_c, // source string
  1014. 1, // number of characters in source string
  1015. &wide_result, // destination buffer
  1016. 1); // size of destination buffer
  1017. if (b == 0)
  1018. return c;
  1019. if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
  1020. return c; // No single byte lower case equivalent available
  1021. #endif
  1022. return result[0];
  1023. }
  1024. #ifndef BOOST_NO_WREGEX
  1025. inline wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type idx)
  1026. {
  1027. wchar_t result[2];
  1028. int b = ::LCMapStringW(
  1029. idx, // locale identifier
  1030. LCMAP_LOWERCASE, // mapping transformation type
  1031. &c, // source string
  1032. 1, // number of characters in source string
  1033. result, // destination buffer
  1034. 1); // size of destination buffer
  1035. if (b == 0)
  1036. return c;
  1037. return result[0];
  1038. }
  1039. #endif
  1040. inline char BOOST_REGEX_CALL w32_toupper(char c, lcid_type idx)
  1041. {
  1042. char result[2];
  1043. #ifndef BOOST_NO_ANSI_APIS
  1044. int b = ::LCMapStringA(
  1045. idx, // locale identifier
  1046. LCMAP_UPPERCASE, // mapping transformation type
  1047. &c, // source string
  1048. 1, // number of characters in source string
  1049. result, // destination buffer
  1050. 1); // size of destination buffer
  1051. if (b == 0)
  1052. return c;
  1053. #else
  1054. UINT code_page = get_code_page_for_locale_id(idx);
  1055. if (code_page == 0)
  1056. return c;
  1057. WCHAR wide_c;
  1058. if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
  1059. return c;
  1060. WCHAR wide_result;
  1061. int b = ::LCMapStringW(
  1062. idx, // locale identifier
  1063. LCMAP_UPPERCASE, // mapping transformation type
  1064. &wide_c, // source string
  1065. 1, // number of characters in source string
  1066. &wide_result, // destination buffer
  1067. 1); // size of destination buffer
  1068. if (b == 0)
  1069. return c;
  1070. if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
  1071. return c; // No single byte upper case equivalent available.
  1072. #endif
  1073. return result[0];
  1074. }
  1075. #ifndef BOOST_NO_WREGEX
  1076. inline wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type idx)
  1077. {
  1078. wchar_t result[2];
  1079. int b = ::LCMapStringW(
  1080. idx, // locale identifier
  1081. LCMAP_UPPERCASE, // mapping transformation type
  1082. &c, // source string
  1083. 1, // number of characters in source string
  1084. result, // destination buffer
  1085. 1); // size of destination buffer
  1086. if (b == 0)
  1087. return c;
  1088. return result[0];
  1089. }
  1090. #endif
  1091. inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, char c)
  1092. {
  1093. WORD mask;
  1094. #ifndef BOOST_NO_ANSI_APIS
  1095. if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
  1096. return true;
  1097. #else
  1098. UINT code_page = get_code_page_for_locale_id(idx);
  1099. if (code_page == 0)
  1100. return false;
  1101. WCHAR wide_c;
  1102. if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
  1103. return false;
  1104. if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
  1105. return true;
  1106. #endif
  1107. if ((m & w32_regex_traits_implementation<char>::mask_word) && (c == '_'))
  1108. return true;
  1109. return false;
  1110. }
  1111. #ifndef BOOST_NO_WREGEX
  1112. inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, wchar_t c)
  1113. {
  1114. WORD mask;
  1115. if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<wchar_t>::mask_base))
  1116. return true;
  1117. if ((m & w32_regex_traits_implementation<wchar_t>::mask_word) && (c == '_'))
  1118. return true;
  1119. if ((m & w32_regex_traits_implementation<wchar_t>::mask_unicode) && (c > 0xff))
  1120. return true;
  1121. return false;
  1122. }
  1123. #endif
  1124. } // BOOST_REGEX_DETAIL_NS
  1125. } // boost
  1126. #ifdef BOOST_MSVC
  1127. #pragma warning(pop)
  1128. #endif
  1129. #ifdef BOOST_MSVC
  1130. #pragma warning(push)
  1131. #pragma warning(disable: 4103)
  1132. #endif
  1133. #ifdef BOOST_HAS_ABI_HEADERS
  1134. # include BOOST_ABI_SUFFIX
  1135. #endif
  1136. #ifdef BOOST_MSVC
  1137. #pragma warning(pop)
  1138. #endif
  1139. #endif // BOOST_REGEX_NO_WIN32_LOCALE
  1140. #endif