w32_regex_traits.hpp 44 KB

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