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