]> git.lyx.org Git - features.git/blob - boost/libs/regex/src/w32_regex_traits.cpp
365fccc00274690d16fa31b64d0fc29cbd31307f
[features.git] / boost / libs / regex / src / w32_regex_traits.cpp
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.cpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Implements w32_regex_traits<char> (and associated helper classes).
17   */
18
19 #define BOOST_REGEX_SOURCE
20 #include <boost/regex/config.hpp>
21
22 #if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32)
23 #include <boost/regex/regex_traits.hpp>
24 #include <boost/regex/pattern_except.hpp>
25
26 #define WIN32_LEAN_AND_MEAN
27 #ifndef NOMINMAX
28 #  define NOMINMAX
29 #endif
30 #define NOGDI
31 #include <windows.h>
32
33 #if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
34 #pragma comment(lib, "user32.lib")
35 #endif
36
37 #ifdef BOOST_NO_STDC_NAMESPACE
38 namespace std{
39    using ::memset;
40 }
41 #endif
42
43 namespace boost{ namespace re_detail{
44
45 #ifdef BOOST_NO_ANSI_APIS
46 UINT get_code_page_for_locale_id(lcid_type id)
47 {
48    WCHAR code_page_string[7];
49    if (::GetLocaleInfoW(id, LOCALE_IDEFAULTANSICODEPAGE, code_page_string, 7) == 0)
50        return 0;
51
52    return static_cast<UINT>(_wtol(code_page_string));
53 }
54 #endif
55
56
57 void w32_regex_traits_char_layer<char>::init() 
58 {
59    // we need to start by initialising our syntax map so we know which
60    // character is used for which purpose:
61    std::memset(m_char_map, 0, sizeof(m_char_map));
62    cat_type cat;
63    std::string cat_name(w32_regex_traits<char>::get_catalog_name());
64    if(cat_name.size())
65    {
66       cat = ::boost::re_detail::w32_cat_open(cat_name);
67       if(!cat)
68       {
69          std::string m("Unable to open message catalog: ");
70          std::runtime_error err(m + cat_name);
71          ::boost::re_detail::raise_runtime_error(err);
72       }
73    }
74    //
75    // if we have a valid catalog then load our messages:
76    //
77    if(cat)
78    {
79       for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
80       {
81          string_type mss = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i));
82          for(string_type::size_type j = 0; j < mss.size(); ++j)
83          {
84             m_char_map[static_cast<unsigned char>(mss[j])] = i;
85          }
86       }
87    }
88    else
89    {
90       for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
91       {
92          const char* ptr = get_default_syntax(i);
93          while(ptr && *ptr)
94          {
95             m_char_map[static_cast<unsigned char>(*ptr)] = i;
96             ++ptr;
97          }
98       }
99    }
100    //
101    // finish off by calculating our escape types:
102    //
103    unsigned char i = 'A';
104    do
105    {
106       if(m_char_map[i] == 0)
107       {
108          if(::boost::re_detail::w32_is(this->m_locale, 0x0002u, (char)i)) 
109             m_char_map[i] = regex_constants::escape_type_class;
110          else if(::boost::re_detail::w32_is(this->m_locale, 0x0001u, (char)i)) 
111             m_char_map[i] = regex_constants::escape_type_not_class;
112       }
113    }while(0xFF != i++);
114
115    //
116    // fill in lower case map:
117    //
118    char char_map[1 << CHAR_BIT];
119    for(int ii = 0; ii < (1 << CHAR_BIT); ++ii)
120       char_map[ii] = static_cast<char>(ii);
121 #ifndef BOOST_NO_ANSI_APIS
122    int r = ::LCMapStringA(this->m_locale, LCMAP_LOWERCASE, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT);
123    BOOST_ASSERT(r != 0);
124 #else
125    UINT code_page = get_code_page_for_locale_id(this->m_locale);
126    BOOST_ASSERT(code_page != 0);
127
128    WCHAR wide_char_map[1 << CHAR_BIT];
129    int conv_r = ::MultiByteToWideChar(code_page, 0,  char_map, 1 << CHAR_BIT,  wide_char_map, 1 << CHAR_BIT);
130    BOOST_ASSERT(conv_r != 0);
131
132    WCHAR wide_lower_map[1 << CHAR_BIT];
133    int r = ::LCMapStringW(this->m_locale, LCMAP_LOWERCASE,  wide_char_map, 1 << CHAR_BIT,  wide_lower_map, 1 << CHAR_BIT);
134    BOOST_ASSERT(r != 0);
135
136    conv_r = ::WideCharToMultiByte(code_page, 0,  wide_lower_map, r,  this->m_lower_map, 1 << CHAR_BIT,  NULL, NULL);
137    BOOST_ASSERT(conv_r != 0);
138 #endif
139    if(r < (1 << CHAR_BIT))
140    {
141       // if we have multibyte characters then not all may have been given
142       // a lower case mapping:
143       for(int jj = r; jj < (1 << CHAR_BIT); ++jj)
144          this->m_lower_map[jj] = static_cast<char>(jj);
145    }
146
147 #ifndef BOOST_NO_ANSI_APIS
148    r = ::GetStringTypeExA(this->m_locale, CT_CTYPE1, char_map, 1 << CHAR_BIT, this->m_type_map);
149 #else
150    r = ::GetStringTypeExW(this->m_locale, CT_CTYPE1, wide_char_map, 1 << CHAR_BIT, this->m_type_map);
151 #endif
152    BOOST_ASSERT(0 != r);
153 }
154
155 BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale()
156 {
157    return ::GetUserDefaultLCID();
158 }
159
160 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char c, lcid_type id)
161 {
162 #ifndef BOOST_NO_ANSI_APIS
163    WORD mask;
164    if(::GetStringTypeExA(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
165       return true;
166    return false;
167 #else
168    UINT code_page = get_code_page_for_locale_id(id);
169    if (code_page == 0)
170        return false;
171
172    WCHAR wide_c;
173    if (::MultiByteToWideChar(code_page, 0,  &c, 1,  &wide_c, 1) == 0)
174        return false;
175
176    WORD mask;
177    if(::GetStringTypeExW(id, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_LOWER))
178       return true;
179    return false;
180 #endif
181 }
182
183 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t c, lcid_type id)
184 {
185    WORD mask;
186    if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
187       return true;
188    return false;
189 }
190 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
191 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(unsigned short ca, lcid_type id)
192 {
193    WORD mask;
194    wchar_t c = ca;
195    if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
196       return true;
197    return false;
198 }
199 #endif
200
201 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char c, lcid_type id)
202 {
203 #ifndef BOOST_NO_ANSI_APIS
204    WORD mask;
205    if(::GetStringTypeExA(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
206       return true;
207    return false;
208 #else
209    UINT code_page = get_code_page_for_locale_id(id);
210    if (code_page == 0)
211        return false;
212
213    WCHAR wide_c;
214    if (::MultiByteToWideChar(code_page, 0,  &c, 1,  &wide_c, 1) == 0)
215        return false;
216
217    WORD mask;
218    if(::GetStringTypeExW(id, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_UPPER))
219       return true;
220    return false;
221 #endif
222 }
223
224 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t c, lcid_type id)
225 {
226    WORD mask;
227    if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
228       return true;
229    return false;
230 }
231 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
232 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(unsigned short ca, lcid_type id)
233 {
234    WORD mask;
235    wchar_t c = ca;
236    if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
237       return true;
238    return false;
239 }
240 #endif
241
242 void free_module(void* mod)
243 {
244    ::FreeLibrary(static_cast<HMODULE>(mod));
245 }
246
247 BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name)
248 {
249 #ifndef BOOST_NO_ANSI_APIS
250    cat_type result(::LoadLibraryA(name.c_str()), &free_module);
251    return result;
252 #else
253    LPWSTR wide_name = (LPWSTR)_alloca( (name.size() + 1) * sizeof(WCHAR) );
254    if (::MultiByteToWideChar(CP_ACP, 0,  name.c_str(), name.size(),  wide_name, name.size() + 1) == 0)
255        return cat_type();
256
257    cat_type result(::LoadLibraryW(wide_name), &free_module);
258    return result;
259 #endif
260 }
261
262 BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def)
263 {
264 #ifndef BOOST_NO_ANSI_APIS
265    char buf[256];
266    if(0 == ::LoadStringA(
267       static_cast<HMODULE>(cat.get()),
268       i,
269       buf,
270       256
271    ))
272    {
273       return def;
274    }
275 #else
276    WCHAR wbuf[256];
277    int r = ::LoadStringW(
278       static_cast<HMODULE>(cat.get()),
279       i,
280       wbuf,
281       256
282    );
283    if (r == 0)
284       return def;
285
286    LPSTR buf = (LPSTR)_alloca( (r + 1) * 2 );
287    if (::WideCharToMultiByte(CP_ACP, 0,  wbuf, r,  buf, (r + 1) * 2,  NULL, NULL) == 0)
288       return def;
289 #endif
290    return std::string(buf);
291 }
292
293 #ifndef BOOST_NO_WREGEX
294 BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def)
295 {
296    wchar_t buf[256];
297    if(0 == ::LoadStringW(
298       static_cast<HMODULE>(cat.get()),
299       i,
300       buf,
301       256
302    ))
303    {
304       return def;
305    }
306    return std::wstring(buf);
307 }
308 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
309 BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::basic_string<unsigned short>& def)
310 {
311    unsigned short buf[256];
312    if(0 == ::LoadStringW(
313       static_cast<HMODULE>(cat.get()),
314       i,
315       (LPWSTR)buf,
316       256
317    ))
318    {
319       return def;
320    }
321    return std::basic_string<unsigned short>(buf);
322 }
323 #endif
324 #endif
325 BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const char* p1, const char* p2)
326 {
327 #ifndef BOOST_NO_ANSI_APIS
328    int bytes = ::LCMapStringA(
329       id,       // locale identifier
330       LCMAP_SORTKEY,  // mapping transformation type
331       p1,  // source string
332       static_cast<int>(p2 - p1),        // number of characters in source string
333       0,  // destination buffer
334       0        // size of destination buffer
335       );
336    if(!bytes)
337       return std::string(p1, p2);
338    std::string result(++bytes, '\0');
339    bytes = ::LCMapStringA(
340       id,       // locale identifier
341       LCMAP_SORTKEY,  // mapping transformation type
342       p1,  // source string
343       static_cast<int>(p2 - p1),        // number of characters in source string
344       &*result.begin(),  // destination buffer
345       bytes        // size of destination buffer
346       );
347 #else
348    UINT code_page = get_code_page_for_locale_id(id);
349    if(code_page == 0)
350       return std::string(p1, p2);
351
352    int src_len = static_cast<int>(p2 - p1);
353    LPWSTR wide_p1 = (LPWSTR)_alloca( (src_len + 1) * 2 );
354    if(::MultiByteToWideChar(code_page, 0,  p1, src_len,  wide_p1, src_len + 1) == 0)
355       return std::string(p1, p2);
356
357    int bytes = ::LCMapStringW(
358       id,       // locale identifier
359       LCMAP_SORTKEY,  // mapping transformation type
360       wide_p1,  // source string
361       src_len,        // number of characters in source string
362       0,  // destination buffer
363       0        // size of destination buffer
364       );
365    if(!bytes)
366       return std::string(p1, p2);
367    std::string result(++bytes, '\0');
368    bytes = ::LCMapStringW(
369       id,       // locale identifier
370       LCMAP_SORTKEY,  // mapping transformation type
371       wide_p1,  // source string
372       src_len,        // number of characters in source string
373       (LPWSTR)&*result.begin(),  // destination buffer
374       bytes        // size of destination buffer
375       );
376 #endif
377    if(bytes > static_cast<int>(result.size()))
378       return std::string(p1, p2);
379    while(result.size() && result[result.size()-1] == '\0')
380    {
381       result.erase(result.size()-1);
382    }
383    return result;
384 }
385
386 #ifndef BOOST_NO_WREGEX
387 BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const wchar_t* p1, const wchar_t* p2)
388 {
389    int bytes = ::LCMapStringW(
390       id,       // locale identifier
391       LCMAP_SORTKEY,  // mapping transformation type
392       p1,  // source string
393       static_cast<int>(p2 - p1),        // number of characters in source string
394       0,  // destination buffer
395       0        // size of destination buffer
396       );
397    if(!bytes)
398       return std::wstring(p1, p2);
399    std::string result(++bytes, '\0');
400    bytes = ::LCMapStringW(
401       id,       // locale identifier
402       LCMAP_SORTKEY,  // mapping transformation type
403       p1,  // source string
404       static_cast<int>(p2 - p1),        // number of characters in source string
405       reinterpret_cast<wchar_t*>(&*result.begin()),  // destination buffer *of bytes*
406       bytes        // size of destination buffer
407       );
408    if(bytes > static_cast<int>(result.size()))
409       return std::wstring(p1, p2);
410    while(result.size() && result[result.size()-1] == L'\0')
411    {
412       result.erase(result.size()-1);
413    }
414    std::wstring r2;
415    for(std::string::size_type i = 0; i < result.size(); ++i)
416       r2.append(1, static_cast<wchar_t>(static_cast<unsigned char>(result[i])));
417    return r2;
418 }
419 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
420 BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transform(lcid_type id, const unsigned short* p1, const unsigned short* p2)
421 {
422    int bytes = ::LCMapStringW(
423       id,       // locale identifier
424       LCMAP_SORTKEY,  // mapping transformation type
425       (LPCWSTR)p1,  // source string
426       static_cast<int>(p2 - p1),        // number of characters in source string
427       0,  // destination buffer
428       0        // size of destination buffer
429       );
430    if(!bytes)
431       return std::basic_string<unsigned short>(p1, p2);
432    std::string result(++bytes, '\0');
433    bytes = ::LCMapStringW(
434       id,       // locale identifier
435       LCMAP_SORTKEY,  // mapping transformation type
436       (LPCWSTR)p1,  // source string
437       static_cast<int>(p2 - p1),        // number of characters in source string
438       reinterpret_cast<wchar_t*>(&*result.begin()),  // destination buffer *of bytes*
439       bytes        // size of destination buffer
440       );
441    if(bytes > static_cast<int>(result.size()))
442       return std::basic_string<unsigned short>(p1, p2);
443    while(result.size() && result[result.size()-1] == L'\0')
444    {
445       result.erase(result.size()-1);
446    }
447    std::basic_string<unsigned short> r2;
448    for(std::string::size_type i = 0; i < result.size(); ++i)
449       r2.append(1, static_cast<unsigned short>(static_cast<unsigned char>(result[i])));
450    return r2;
451 }
452 #endif
453 #endif
454 BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type id)
455 {
456    char result[2];
457 #ifndef BOOST_NO_ANSI_APIS
458    int b = ::LCMapStringA(
459       id,       // locale identifier
460       LCMAP_LOWERCASE,  // mapping transformation type
461       &c,  // source string
462       1,        // number of characters in source string
463       result,  // destination buffer
464       1);        // size of destination buffer
465    if(b == 0)
466       return c;
467 #else
468    UINT code_page = get_code_page_for_locale_id(id);
469    if (code_page == 0)
470       return c;
471
472    WCHAR wide_c;
473    if (::MultiByteToWideChar(code_page, 0,  &c, 1,  &wide_c, 1) == 0)
474       return c;
475
476    WCHAR wide_result;
477    int b = ::LCMapStringW(
478       id,       // locale identifier
479       LCMAP_LOWERCASE,  // mapping transformation type
480       &wide_c,  // source string
481       1,        // number of characters in source string
482       &wide_result,  // destination buffer
483       1);        // size of destination buffer
484    if(b == 0)
485       return c;
486
487    if (::WideCharToMultiByte(code_page, 0,  &wide_result, 1,  result, 2,  NULL, NULL) == 0)
488        return c;
489 #endif
490    return result[0];
491 }
492
493 #ifndef BOOST_NO_WREGEX
494 BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type id)
495 {
496    wchar_t result[2];
497    int b = ::LCMapStringW(
498       id,       // locale identifier
499       LCMAP_LOWERCASE,  // mapping transformation type
500       &c,  // source string
501       1,        // number of characters in source string
502       result,  // destination buffer
503       1);        // size of destination buffer
504    if(b == 0)
505       return c;
506    return result[0];
507 }
508 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
509 BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_tolower(unsigned short c, lcid_type id)
510 {
511    wchar_t result[2];
512    int b = ::LCMapStringW(
513       id,       // locale identifier
514       LCMAP_LOWERCASE,  // mapping transformation type
515       (wchar_t const*)&c,  // source string
516       1,        // number of characters in source string
517       result,  // destination buffer
518       1);        // size of destination buffer
519    if(b == 0)
520       return c;
521    return result[0];
522 }
523 #endif
524 #endif
525 BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type id)
526 {
527    char result[2];
528 #ifndef BOOST_NO_ANSI_APIS
529    int b = ::LCMapStringA(
530       id,       // locale identifier
531       LCMAP_UPPERCASE,  // mapping transformation type
532       &c,  // source string
533       1,        // number of characters in source string
534       result,  // destination buffer
535       1);        // size of destination buffer
536    if(b == 0)
537       return c;
538 #else
539    UINT code_page = get_code_page_for_locale_id(id);
540    if(code_page == 0)
541        return c;
542
543    WCHAR wide_c;
544    if (::MultiByteToWideChar(code_page, 0,  &c, 1,  &wide_c, 1) == 0)
545        return c;
546
547    WCHAR wide_result;
548    int b = ::LCMapStringW(
549       id,       // locale identifier
550       LCMAP_UPPERCASE,  // mapping transformation type
551       &wide_c,  // source string
552       1,        // number of characters in source string
553       &wide_result,  // destination buffer
554       1);        // size of destination buffer
555    if(b == 0)
556       return c;
557
558    if (::WideCharToMultiByte(code_page, 0,  &wide_result, 1,  result, 2,  NULL, NULL) == 0)
559        return c;
560 #endif
561    return result[0];
562 }
563
564 #ifndef BOOST_NO_WREGEX
565 BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type id)
566 {
567    wchar_t result[2];
568    int b = ::LCMapStringW(
569       id,       // locale identifier
570       LCMAP_UPPERCASE,  // mapping transformation type
571       &c,  // source string
572       1,        // number of characters in source string
573       result,  // destination buffer
574       1);        // size of destination buffer
575    if(b == 0)
576       return c;
577    return result[0];
578 }
579 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
580 BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_toupper(unsigned short c, lcid_type id)
581 {
582    wchar_t result[2];
583    int b = ::LCMapStringW(
584       id,       // locale identifier
585       LCMAP_UPPERCASE,  // mapping transformation type
586       (wchar_t const*)&c,  // source string
587       1,        // number of characters in source string
588       result,  // destination buffer
589       1);        // size of destination buffer
590    if(b == 0)
591       return c;
592    return result[0];
593 }
594 #endif
595 #endif
596 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type id, boost::uint32_t m, char c)
597 {
598    WORD mask;
599 #ifndef BOOST_NO_ANSI_APIS
600    if(::GetStringTypeExA(id, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
601       return true;
602 #else
603    UINT code_page = get_code_page_for_locale_id(id);
604    if(code_page == 0)
605        return false;
606
607    WCHAR wide_c;
608    if (::MultiByteToWideChar(code_page, 0,  &c, 1,  &wide_c, 1) == 0)
609        return false;
610
611    if(::GetStringTypeExW(id, CT_CTYPE1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
612       return true;
613 #endif
614    if((m & w32_regex_traits_implementation<char>::mask_word) && (c == '_'))
615       return true;
616    return false;
617 }
618
619 #ifndef BOOST_NO_WREGEX
620 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type id, boost::uint32_t m, wchar_t c)
621 {
622    WORD mask;
623    if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<wchar_t>::mask_base))
624       return true;
625    if((m & w32_regex_traits_implementation<wchar_t>::mask_word) && (c == '_'))
626       return true;
627    if((m & w32_regex_traits_implementation<wchar_t>::mask_unicode) && (c > 0xff))
628       return true;
629    return false;
630 }
631 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
632 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type id, boost::uint32_t m, unsigned short c)
633 {
634    WORD mask;
635    if(::GetStringTypeExW(id, CT_CTYPE1, (wchar_t const*)&c, 1, &mask) && (mask & m & w32_regex_traits_implementation<wchar_t>::mask_base))
636       return true;
637    if((m & w32_regex_traits_implementation<wchar_t>::mask_word) && (c == '_'))
638       return true;
639    if((m & w32_regex_traits_implementation<wchar_t>::mask_unicode) && (c > 0xff))
640       return true;
641    return false;
642 }
643 #endif
644 #endif
645
646 } // re_detail
647 } // boost
648
649 #endif
650