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