w32_regex_traits.hpp 44 KB

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