File indexing completed on 2025-01-18 09:51:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
0020 #define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
0021
0022 #ifndef BOOST_REGEX_NO_WIN32_LOCALE
0023
0024 #ifndef BOOST_RE_PAT_EXCEPT_HPP
0025 #include <boost/regex/pattern_except.hpp>
0026 #endif
0027 #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
0028 #include <boost/regex/v4/regex_traits_defaults.hpp>
0029 #endif
0030 #ifdef BOOST_HAS_THREADS
0031 #include <boost/regex/pending/static_mutex.hpp>
0032 #endif
0033 #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
0034 #include <boost/regex/v4/primary_transform.hpp>
0035 #endif
0036 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
0037 #include <boost/regex/v4/object_cache.hpp>
0038 #endif
0039
0040 #define VC_EXTRALEAN
0041 #define WIN32_LEAN_AND_MEAN
0042 #include <windows.h>
0043
0044 #if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
0045 #pragma comment(lib, "user32.lib")
0046 #endif
0047
0048
0049 #ifdef BOOST_MSVC
0050 #pragma warning(push)
0051 #pragma warning(disable: 4103)
0052 #endif
0053 #ifdef BOOST_HAS_ABI_HEADERS
0054 # include BOOST_ABI_PREFIX
0055 #endif
0056 #ifdef BOOST_MSVC
0057 #pragma warning(pop)
0058 #endif
0059
0060 #ifdef BOOST_MSVC
0061 #pragma warning(push)
0062 #pragma warning(disable:4786)
0063 #if BOOST_MSVC < 1910
0064 #pragma warning(disable:4800)
0065 #endif
0066 #endif
0067
0068 namespace boost{
0069
0070
0071
0072
0073 template <class charT>
0074 class w32_regex_traits;
0075
0076 namespace BOOST_REGEX_DETAIL_NS{
0077
0078
0079
0080
0081 typedef ::boost::uint32_t lcid_type;
0082 typedef ::boost::shared_ptr<void> cat_type;
0083
0084
0085
0086
0087 lcid_type BOOST_REGEX_CALL w32_get_default_locale();
0088 bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
0089 #ifndef BOOST_NO_WREGEX
0090 bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
0091 #endif
0092 bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
0093 #ifndef BOOST_NO_WREGEX
0094 bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
0095 #endif
0096 cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
0097 std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
0098 #ifndef BOOST_NO_WREGEX
0099 std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
0100 #endif
0101 std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
0102 #ifndef BOOST_NO_WREGEX
0103 std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
0104 #endif
0105 char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
0106 #ifndef BOOST_NO_WREGEX
0107 wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
0108 #endif
0109 char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
0110 #ifndef BOOST_NO_WREGEX
0111 wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
0112 #endif
0113 bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
0114 #ifndef BOOST_NO_WREGEX
0115 bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
0116 #endif
0117
0118
0119
0120
0121 template <class charT>
0122 struct w32_regex_traits_base
0123 {
0124 w32_regex_traits_base(lcid_type l)
0125 { imbue(l); }
0126 lcid_type imbue(lcid_type l);
0127
0128 lcid_type m_locale;
0129 };
0130
0131 template <class charT>
0132 inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l)
0133 {
0134 lcid_type result(m_locale);
0135 m_locale = l;
0136 return result;
0137 }
0138
0139
0140
0141
0142
0143 template <class charT>
0144 class w32_regex_traits_char_layer : public w32_regex_traits_base<charT>
0145 {
0146 typedef std::basic_string<charT> string_type;
0147 typedef std::map<charT, regex_constants::syntax_type> map_type;
0148 typedef typename map_type::const_iterator map_iterator_type;
0149 public:
0150 w32_regex_traits_char_layer(const lcid_type l);
0151
0152 regex_constants::syntax_type syntax_type(charT c)const
0153 {
0154 map_iterator_type i = m_char_map.find(c);
0155 return ((i == m_char_map.end()) ? 0 : i->second);
0156 }
0157 regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0158 {
0159 map_iterator_type i = m_char_map.find(c);
0160 if(i == m_char_map.end())
0161 {
0162 if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class;
0163 if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class;
0164 return 0;
0165 }
0166 return i->second;
0167 }
0168 charT tolower(charT c)const
0169 {
0170 return ::boost::BOOST_REGEX_DETAIL_NS::w32_tolower(c, this->m_locale);
0171 }
0172 bool isctype(boost::uint32_t mask, charT c)const
0173 {
0174 return ::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, mask, c);
0175 }
0176
0177 private:
0178 string_type get_default_message(regex_constants::syntax_type);
0179
0180 map_type m_char_map;
0181 };
0182
0183 template <class charT>
0184 w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0185 : w32_regex_traits_base<charT>(l)
0186 {
0187
0188
0189 cat_type cat;
0190 std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
0191 if(cat_name.size())
0192 {
0193 cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
0194 if(!cat)
0195 {
0196 std::string m("Unable to open message catalog: ");
0197 std::runtime_error err(m + cat_name);
0198 boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0199 }
0200 }
0201
0202
0203
0204 if(cat)
0205 {
0206 for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0207 {
0208 string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_message(i));
0209 for(typename string_type::size_type j = 0; j < mss.size(); ++j)
0210 {
0211 this->m_char_map[mss[j]] = i;
0212 }
0213 }
0214 }
0215 else
0216 {
0217 for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0218 {
0219 const char* ptr = get_default_syntax(i);
0220 while(ptr && *ptr)
0221 {
0222 this->m_char_map[static_cast<charT>(*ptr)] = i;
0223 ++ptr;
0224 }
0225 }
0226 }
0227 }
0228
0229 template <class charT>
0230 typename w32_regex_traits_char_layer<charT>::string_type
0231 w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
0232 {
0233 const char* ptr = get_default_syntax(i);
0234 string_type result;
0235 while(ptr && *ptr)
0236 {
0237 result.append(1, static_cast<charT>(*ptr));
0238 ++ptr;
0239 }
0240 return result;
0241 }
0242
0243
0244
0245
0246 template <>
0247 class w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
0248 {
0249 typedef std::string string_type;
0250 public:
0251 w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0252 : w32_regex_traits_base<char>(l)
0253 {
0254 init<char>();
0255 }
0256
0257 regex_constants::syntax_type syntax_type(char c)const
0258 {
0259 return m_char_map[static_cast<unsigned char>(c)];
0260 }
0261 regex_constants::escape_syntax_type escape_syntax_type(char c) const
0262 {
0263 return m_char_map[static_cast<unsigned char>(c)];
0264 }
0265 char tolower(char c)const
0266 {
0267 return m_lower_map[static_cast<unsigned char>(c)];
0268 }
0269 bool isctype(boost::uint32_t mask, char c)const
0270 {
0271 return m_type_map[static_cast<unsigned char>(c)] & mask;
0272 }
0273
0274 private:
0275 regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
0276 char m_lower_map[1u << CHAR_BIT];
0277 boost::uint16_t m_type_map[1u << CHAR_BIT];
0278 template <class U>
0279 void init();
0280 };
0281
0282
0283
0284
0285
0286 template <class charT>
0287 class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT>
0288 {
0289 public:
0290 typedef typename w32_regex_traits<charT>::char_class_type char_class_type;
0291 BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400);
0292 BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800);
0293 BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000);
0294 BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000);
0295 BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff);
0296
0297 typedef std::basic_string<charT> string_type;
0298 typedef charT char_type;
0299 w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l);
0300 std::string error_string(regex_constants::error_type n) const
0301 {
0302 if(!m_error_strings.empty())
0303 {
0304 std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
0305 return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
0306 }
0307 return get_default_error_string(n);
0308 }
0309 char_class_type lookup_classname(const charT* p1, const charT* p2) const
0310 {
0311 char_class_type result = lookup_classname_imp(p1, p2);
0312 if(result == 0)
0313 {
0314 typedef typename string_type::size_type size_type;
0315 string_type temp(p1, p2);
0316 for(size_type i = 0; i < temp.size(); ++i)
0317 temp[i] = this->tolower(temp[i]);
0318 result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
0319 }
0320 return result;
0321 }
0322 string_type lookup_collatename(const charT* p1, const charT* p2) const;
0323 string_type transform_primary(const charT* p1, const charT* p2) const;
0324 string_type transform(const charT* p1, const charT* p2) const
0325 {
0326 return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_locale, p1, p2);
0327 }
0328 private:
0329 std::map<int, std::string> m_error_strings;
0330 std::map<string_type, char_class_type> m_custom_class_names;
0331 std::map<string_type, string_type> m_custom_collate_names;
0332 unsigned m_collate_type;
0333 charT m_collate_delim;
0334
0335
0336
0337 char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
0338 };
0339
0340 template <class charT>
0341 typename w32_regex_traits_implementation<charT>::string_type
0342 w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
0343 {
0344 string_type result;
0345
0346
0347
0348
0349 switch(m_collate_type)
0350 {
0351 case sort_C:
0352 case sort_unknown:
0353
0354 {
0355 result.assign(p1, p2);
0356 typedef typename string_type::size_type size_type;
0357 for(size_type i = 0; i < result.size(); ++i)
0358 result[i] = this->tolower(result[i]);
0359 result = this->transform(&*result.begin(), &*result.begin() + result.size());
0360 break;
0361 }
0362 case sort_fixed:
0363 {
0364
0365 result.assign(this->transform(p1, p2));
0366 result.erase(this->m_collate_delim);
0367 break;
0368 }
0369 case sort_delim:
0370
0371 result.assign(this->transform(p1, p2));
0372 std::size_t i;
0373 for(i = 0; i < result.size(); ++i)
0374 {
0375 if(result[i] == m_collate_delim)
0376 break;
0377 }
0378 result.erase(i);
0379 break;
0380 }
0381 if(result.empty())
0382 result = string_type(1, charT(0));
0383 return result;
0384 }
0385
0386 template <class charT>
0387 typename w32_regex_traits_implementation<charT>::string_type
0388 w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
0389 {
0390 typedef typename std::map<string_type, string_type>::const_iterator iter_type;
0391 if(m_custom_collate_names.size())
0392 {
0393 iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
0394 if(pos != m_custom_collate_names.end())
0395 return pos->second;
0396 }
0397 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
0398 && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
0399 std::string name(p1, p2);
0400 #else
0401 std::string name;
0402 const charT* p0 = p1;
0403 while(p0 != p2)
0404 name.append(1, char(*p0++));
0405 #endif
0406 name = lookup_default_collate_name(name);
0407 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
0408 && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
0409 if(name.size())
0410 return string_type(name.begin(), name.end());
0411 #else
0412 if(name.size())
0413 {
0414 string_type result;
0415 typedef std::string::const_iterator iter;
0416 iter b = name.begin();
0417 iter e = name.end();
0418 while(b != e)
0419 result.append(1, charT(*b++));
0420 return result;
0421 }
0422 #endif
0423 if(p2 - p1 == 1)
0424 return string_type(1, *p1);
0425 return string_type();
0426 }
0427
0428 template <class charT>
0429 w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0430 : w32_regex_traits_char_layer<charT>(l)
0431 {
0432 cat_type cat;
0433 std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
0434 if(cat_name.size())
0435 {
0436 cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
0437 if(!cat)
0438 {
0439 std::string m("Unable to open message catalog: ");
0440 std::runtime_error err(m + cat_name);
0441 boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0442 }
0443 }
0444
0445
0446
0447 if(cat)
0448 {
0449
0450
0451
0452 for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
0453 i <= boost::regex_constants::error_unknown;
0454 i = static_cast<boost::regex_constants::error_type>(i + 1))
0455 {
0456 const char* p = get_default_error_string(i);
0457 string_type default_message;
0458 while(*p)
0459 {
0460 default_message.append(1, static_cast<charT>(*p));
0461 ++p;
0462 }
0463 string_type s = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i+200, default_message);
0464 std::string result;
0465 for(std::string::size_type j = 0; j < s.size(); ++j)
0466 {
0467 result.append(1, static_cast<char>(s[j]));
0468 }
0469 m_error_strings[i] = result;
0470 }
0471
0472
0473
0474 static const char_class_type masks[14] =
0475 {
0476 0x0104u,
0477 0x0100u,
0478 0x0020u,
0479 0x0004u,
0480 (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u,
0481 0x0002u,
0482 (~0x0020u & 0x01ffu) | 0x0400,
0483 0x0010u,
0484 0x0008u,
0485 0x0001u,
0486 0x0080u,
0487 0x0040u,
0488 w32_regex_traits_implementation<charT>::mask_word,
0489 w32_regex_traits_implementation<charT>::mask_unicode,
0490 };
0491 static const string_type null_string;
0492 for(unsigned int j = 0; j <= 13; ++j)
0493 {
0494 string_type s(::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, j+300, null_string));
0495 if(s.size())
0496 this->m_custom_class_names[s] = masks[j];
0497 }
0498 }
0499
0500
0501
0502 m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim);
0503 }
0504
0505 template <class charT>
0506 typename w32_regex_traits_implementation<charT>::char_class_type
0507 w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
0508 {
0509 static const char_class_type masks[22] =
0510 {
0511 0,
0512 0x0104u,
0513 0x0100u,
0514 0x0040u,
0515 0x0020u,
0516 0x0004u,
0517 0x0004u,
0518 (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u,
0519 w32_regex_traits_implementation<charT>::mask_horizontal,
0520 0x0002u,
0521 0x0002u,
0522 (~0x0020u & 0x01ffu) | 0x0400,
0523 0x0010u,
0524 0x0008u,
0525 0x0008u,
0526 0x0001u,
0527 w32_regex_traits_implementation<charT>::mask_unicode,
0528 0x0001u,
0529 w32_regex_traits_implementation<charT>::mask_vertical,
0530 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
0531 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
0532 0x0080u,
0533 };
0534 if(m_custom_class_names.size())
0535 {
0536 typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
0537 map_iter pos = m_custom_class_names.find(string_type(p1, p2));
0538 if(pos != m_custom_class_names.end())
0539 return pos->second;
0540 }
0541 std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
0542 if(state_id < sizeof(masks) / sizeof(masks[0]))
0543 return masks[state_id];
0544 return masks[0];
0545 }
0546
0547
0548 template <class charT>
0549 boost::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0550 {
0551
0552 return boost::object_cache< ::boost::BOOST_REGEX_DETAIL_NS::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
0553 }
0554
0555 }
0556
0557 template <class charT>
0558 class w32_regex_traits
0559 {
0560 public:
0561 typedef charT char_type;
0562 typedef std::size_t size_type;
0563 typedef std::basic_string<char_type> string_type;
0564 typedef ::boost::BOOST_REGEX_DETAIL_NS::lcid_type locale_type;
0565 typedef boost::uint_least32_t char_class_type;
0566
0567 struct boost_extensions_tag{};
0568
0569 w32_regex_traits()
0570 : m_pimpl(BOOST_REGEX_DETAIL_NS::create_w32_regex_traits<charT>(::boost::BOOST_REGEX_DETAIL_NS::w32_get_default_locale()))
0571 { }
0572 static size_type length(const char_type* p)
0573 {
0574 return std::char_traits<charT>::length(p);
0575 }
0576 regex_constants::syntax_type syntax_type(charT c)const
0577 {
0578 return m_pimpl->syntax_type(c);
0579 }
0580 regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0581 {
0582 return m_pimpl->escape_syntax_type(c);
0583 }
0584 charT translate(charT c) const
0585 {
0586 return c;
0587 }
0588 charT translate_nocase(charT c) const
0589 {
0590 return this->m_pimpl->tolower(c);
0591 }
0592 charT translate(charT c, bool icase) const
0593 {
0594 return icase ? this->m_pimpl->tolower(c) : c;
0595 }
0596 charT tolower(charT c) const
0597 {
0598 return this->m_pimpl->tolower(c);
0599 }
0600 charT toupper(charT c) const
0601 {
0602 return ::boost::BOOST_REGEX_DETAIL_NS::w32_toupper(c, this->m_pimpl->m_locale);
0603 }
0604 string_type transform(const charT* p1, const charT* p2) const
0605 {
0606 return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_pimpl->m_locale, p1, p2);
0607 }
0608 string_type transform_primary(const charT* p1, const charT* p2) const
0609 {
0610 return m_pimpl->transform_primary(p1, p2);
0611 }
0612 char_class_type lookup_classname(const charT* p1, const charT* p2) const
0613 {
0614 return m_pimpl->lookup_classname(p1, p2);
0615 }
0616 string_type lookup_collatename(const charT* p1, const charT* p2) const
0617 {
0618 return m_pimpl->lookup_collatename(p1, p2);
0619 }
0620 bool isctype(charT c, char_class_type f) const
0621 {
0622 if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_base)
0623 && (this->m_pimpl->isctype(f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_base, c)))
0624 return true;
0625 else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c))
0626 return true;
0627 else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_word) && (c == '_'))
0628 return true;
0629 else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_vertical)
0630 && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
0631 return true;
0632 else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_horizontal)
0633 && this->isctype(c, 0x0008u) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_vertical))
0634 return true;
0635 return false;
0636 }
0637 boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const
0638 {
0639 return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
0640 }
0641 int value(charT c, int radix)const
0642 {
0643 int result = (int)::boost::BOOST_REGEX_DETAIL_NS::global_value(c);
0644 return result < radix ? result : -1;
0645 }
0646 locale_type imbue(locale_type l)
0647 {
0648 ::boost::BOOST_REGEX_DETAIL_NS::lcid_type result(getloc());
0649 m_pimpl = BOOST_REGEX_DETAIL_NS::create_w32_regex_traits<charT>(l);
0650 return result;
0651 }
0652 locale_type getloc()const
0653 {
0654 return m_pimpl->m_locale;
0655 }
0656 std::string error_string(regex_constants::error_type n) const
0657 {
0658 return m_pimpl->error_string(n);
0659 }
0660
0661
0662
0663
0664
0665 static std::string catalog_name(const std::string& name);
0666 static std::string get_catalog_name();
0667
0668 private:
0669 boost::shared_ptr<const BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT> > m_pimpl;
0670
0671
0672
0673 static std::string& get_catalog_name_inst();
0674
0675 #ifdef BOOST_HAS_THREADS
0676 static static_mutex& get_mutex_inst();
0677 #endif
0678 };
0679
0680 template <class charT>
0681 std::string w32_regex_traits<charT>::catalog_name(const std::string& name)
0682 {
0683 #ifdef BOOST_HAS_THREADS
0684 static_mutex::scoped_lock lk(get_mutex_inst());
0685 #endif
0686 std::string result(get_catalog_name_inst());
0687 get_catalog_name_inst() = name;
0688 return result;
0689 }
0690
0691 template <class charT>
0692 std::string& w32_regex_traits<charT>::get_catalog_name_inst()
0693 {
0694 static std::string s_name;
0695 return s_name;
0696 }
0697
0698 template <class charT>
0699 std::string w32_regex_traits<charT>::get_catalog_name()
0700 {
0701 #ifdef BOOST_HAS_THREADS
0702 static_mutex::scoped_lock lk(get_mutex_inst());
0703 #endif
0704 std::string result(get_catalog_name_inst());
0705 return result;
0706 }
0707
0708 #ifdef BOOST_HAS_THREADS
0709 template <class charT>
0710 static_mutex& w32_regex_traits<charT>::get_mutex_inst()
0711 {
0712 static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
0713 return s_mutex;
0714 }
0715 #endif
0716
0717 namespace BOOST_REGEX_DETAIL_NS {
0718
0719 #ifdef BOOST_NO_ANSI_APIS
0720 inline UINT get_code_page_for_locale_id(lcid_type idx)
0721 {
0722 WCHAR code_page_string[7];
0723 if (::GetLocaleInfoW(idx, LOCALE_IDEFAULTANSICODEPAGE, code_page_string, 7) == 0)
0724 return 0;
0725
0726 return static_cast<UINT>(_wtol(code_page_string));
0727 }
0728 #endif
0729
0730 template <class U>
0731 inline void w32_regex_traits_char_layer<char>::init()
0732 {
0733
0734
0735 std::memset(m_char_map, 0, sizeof(m_char_map));
0736 cat_type cat;
0737 std::string cat_name(w32_regex_traits<char>::get_catalog_name());
0738 if (cat_name.size())
0739 {
0740 cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
0741 if (!cat)
0742 {
0743 std::string m("Unable to open message catalog: ");
0744 std::runtime_error err(m + cat_name);
0745 ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0746 }
0747 }
0748
0749
0750
0751 if (cat)
0752 {
0753 for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0754 {
0755 string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i));
0756 for (string_type::size_type j = 0; j < mss.size(); ++j)
0757 {
0758 m_char_map[static_cast<unsigned char>(mss[j])] = i;
0759 }
0760 }
0761 }
0762 else
0763 {
0764 for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0765 {
0766 const char* ptr = get_default_syntax(i);
0767 while (ptr && *ptr)
0768 {
0769 m_char_map[static_cast<unsigned char>(*ptr)] = i;
0770 ++ptr;
0771 }
0772 }
0773 }
0774
0775
0776
0777 unsigned char i = 'A';
0778 do
0779 {
0780 if (m_char_map[i] == 0)
0781 {
0782 if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0002u, (char)i))
0783 m_char_map[i] = regex_constants::escape_type_class;
0784 else if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0001u, (char)i))
0785 m_char_map[i] = regex_constants::escape_type_not_class;
0786 }
0787 } while (0xFF != i++);
0788
0789
0790
0791
0792 char char_map[1 << CHAR_BIT];
0793 for (int ii = 0; ii < (1 << CHAR_BIT); ++ii)
0794 char_map[ii] = static_cast<char>(ii);
0795 #ifndef BOOST_NO_ANSI_APIS
0796 int r = ::LCMapStringA(this->m_locale, LCMAP_LOWERCASE, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT);
0797 BOOST_REGEX_ASSERT(r != 0);
0798 #else
0799 UINT code_page = get_code_page_for_locale_id(this->m_locale);
0800 BOOST_REGEX_ASSERT(code_page != 0);
0801
0802 WCHAR wide_char_map[1 << CHAR_BIT];
0803 int conv_r = ::MultiByteToWideChar(code_page, 0, char_map, 1 << CHAR_BIT, wide_char_map, 1 << CHAR_BIT);
0804 BOOST_REGEX_ASSERT(conv_r != 0);
0805
0806 WCHAR wide_lower_map[1 << CHAR_BIT];
0807 int r = ::LCMapStringW(this->m_locale, LCMAP_LOWERCASE, wide_char_map, 1 << CHAR_BIT, wide_lower_map, 1 << CHAR_BIT);
0808 BOOST_REGEX_ASSERT(r != 0);
0809
0810 conv_r = ::WideCharToMultiByte(code_page, 0, wide_lower_map, r, this->m_lower_map, 1 << CHAR_BIT, NULL, NULL);
0811 BOOST_REGEX_ASSERT(conv_r != 0);
0812 #endif
0813 if (r < (1 << CHAR_BIT))
0814 {
0815
0816
0817 for (int jj = r; jj < (1 << CHAR_BIT); ++jj)
0818 this->m_lower_map[jj] = static_cast<char>(jj);
0819 }
0820
0821 #ifndef BOOST_NO_ANSI_APIS
0822 r = ::GetStringTypeExA(this->m_locale, CT_CTYPE1, char_map, 1 << CHAR_BIT, this->m_type_map);
0823 #else
0824 r = ::GetStringTypeExW(this->m_locale, CT_CTYPE1, wide_char_map, 1 << CHAR_BIT, this->m_type_map);
0825 #endif
0826 BOOST_REGEX_ASSERT(0 != r);
0827 }
0828
0829 inline lcid_type BOOST_REGEX_CALL w32_get_default_locale()
0830 {
0831 return ::GetUserDefaultLCID();
0832 }
0833
0834 inline bool BOOST_REGEX_CALL w32_is_lower(char c, lcid_type idx)
0835 {
0836 #ifndef BOOST_NO_ANSI_APIS
0837 WORD mask;
0838 if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
0839 return true;
0840 return false;
0841 #else
0842 UINT code_page = get_code_page_for_locale_id(idx);
0843 if (code_page == 0)
0844 return false;
0845
0846 WCHAR wide_c;
0847 if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
0848 return false;
0849
0850 WORD mask;
0851 if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_LOWER))
0852 return true;
0853 return false;
0854 #endif
0855 }
0856
0857 inline bool BOOST_REGEX_CALL w32_is_lower(wchar_t c, lcid_type idx)
0858 {
0859 WORD mask;
0860 if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
0861 return true;
0862 return false;
0863 }
0864
0865 inline bool BOOST_REGEX_CALL w32_is_upper(char c, lcid_type idx)
0866 {
0867 #ifndef BOOST_NO_ANSI_APIS
0868 WORD mask;
0869 if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
0870 return true;
0871 return false;
0872 #else
0873 UINT code_page = get_code_page_for_locale_id(idx);
0874 if (code_page == 0)
0875 return false;
0876
0877 WCHAR wide_c;
0878 if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
0879 return false;
0880
0881 WORD mask;
0882 if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_UPPER))
0883 return true;
0884 return false;
0885 #endif
0886 }
0887
0888 inline bool BOOST_REGEX_CALL w32_is_upper(wchar_t c, lcid_type idx)
0889 {
0890 WORD mask;
0891 if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
0892 return true;
0893 return false;
0894 }
0895
0896 inline void free_module(void* mod)
0897 {
0898 ::FreeLibrary(static_cast<HMODULE>(mod));
0899 }
0900
0901 inline cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name)
0902 {
0903 #ifndef BOOST_NO_ANSI_APIS
0904 cat_type result(::LoadLibraryA(name.c_str()), &free_module);
0905 return result;
0906 #else
0907 LPWSTR wide_name = (LPWSTR)_alloca((name.size() + 1) * sizeof(WCHAR));
0908 if (::MultiByteToWideChar(CP_ACP, 0, name.c_str(), name.size(), wide_name, name.size() + 1) == 0)
0909 return cat_type();
0910
0911 cat_type result(::LoadLibraryW(wide_name), &free_module);
0912 return result;
0913 #endif
0914 }
0915
0916 inline std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def)
0917 {
0918 #ifndef BOOST_NO_ANSI_APIS
0919 char buf[256];
0920 if (0 == ::LoadStringA(
0921 static_cast<HMODULE>(cat.get()),
0922 i,
0923 buf,
0924 256
0925 ))
0926 {
0927 return def;
0928 }
0929 #else
0930 WCHAR wbuf[256];
0931 int r = ::LoadStringW(
0932 static_cast<HMODULE>(cat.get()),
0933 i,
0934 wbuf,
0935 256
0936 );
0937 if (r == 0)
0938 return def;
0939
0940
0941 int buf_size = 1 + ::WideCharToMultiByte(CP_ACP, 0, wbuf, r, NULL, 0, NULL, NULL);
0942 LPSTR buf = (LPSTR)_alloca(buf_size);
0943 if (::WideCharToMultiByte(CP_ACP, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0)
0944 return def;
0945 #endif
0946 return std::string(buf);
0947 }
0948
0949 #ifndef BOOST_NO_WREGEX
0950 inline std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def)
0951 {
0952 wchar_t buf[256];
0953 if (0 == ::LoadStringW(
0954 static_cast<HMODULE>(cat.get()),
0955 i,
0956 buf,
0957 256
0958 ))
0959 {
0960 return def;
0961 }
0962 return std::wstring(buf);
0963 }
0964 #endif
0965 inline std::string BOOST_REGEX_CALL w32_transform(lcid_type idx, const char* p1, const char* p2)
0966 {
0967 #ifndef BOOST_NO_ANSI_APIS
0968 int bytes = ::LCMapStringA(
0969 idx,
0970 LCMAP_SORTKEY,
0971 p1,
0972 static_cast<int>(p2 - p1),
0973 0,
0974 0
0975 );
0976 if (!bytes)
0977 return std::string(p1, p2);
0978 std::string result(++bytes, '\0');
0979 bytes = ::LCMapStringA(
0980 idx,
0981 LCMAP_SORTKEY,
0982 p1,
0983 static_cast<int>(p2 - p1),
0984 &*result.begin(),
0985 bytes
0986 );
0987 #else
0988 UINT code_page = get_code_page_for_locale_id(idx);
0989 if (code_page == 0)
0990 return std::string(p1, p2);
0991
0992 int src_len = static_cast<int>(p2 - p1);
0993 LPWSTR wide_p1 = (LPWSTR)_alloca((src_len + 1) * 2);
0994 if (::MultiByteToWideChar(code_page, 0, p1, src_len, wide_p1, src_len + 1) == 0)
0995 return std::string(p1, p2);
0996
0997 int bytes = ::LCMapStringW(
0998 idx,
0999 LCMAP_SORTKEY,
1000 wide_p1,
1001 src_len,
1002 0,
1003 0
1004 );
1005 if (!bytes)
1006 return std::string(p1, p2);
1007 std::string result(++bytes, '\0');
1008 bytes = ::LCMapStringW(
1009 idx,
1010 LCMAP_SORTKEY,
1011 wide_p1,
1012 src_len,
1013 (LPWSTR) & *result.begin(),
1014 bytes
1015 );
1016 #endif
1017 if (bytes > static_cast<int>(result.size()))
1018 return std::string(p1, p2);
1019 while (result.size() && result[result.size() - 1] == '\0')
1020 {
1021 result.erase(result.size() - 1);
1022 }
1023 return result;
1024 }
1025
1026 #ifndef BOOST_NO_WREGEX
1027 inline std::wstring BOOST_REGEX_CALL w32_transform(lcid_type idx, const wchar_t* p1, const wchar_t* p2)
1028 {
1029 int bytes = ::LCMapStringW(
1030 idx,
1031 LCMAP_SORTKEY,
1032 p1,
1033 static_cast<int>(p2 - p1),
1034 0,
1035 0
1036 );
1037 if (!bytes)
1038 return std::wstring(p1, p2);
1039 std::string result(++bytes, '\0');
1040 bytes = ::LCMapStringW(
1041 idx,
1042 LCMAP_SORTKEY,
1043 p1,
1044 static_cast<int>(p2 - p1),
1045 reinterpret_cast<wchar_t*>(&*result.begin()),
1046 bytes
1047 );
1048 if (bytes > static_cast<int>(result.size()))
1049 return std::wstring(p1, p2);
1050 while (result.size() && result[result.size() - 1] == L'\0')
1051 {
1052 result.erase(result.size() - 1);
1053 }
1054 std::wstring r2;
1055 for (std::string::size_type i = 0; i < result.size(); ++i)
1056 r2.append(1, static_cast<wchar_t>(static_cast<unsigned char>(result[i])));
1057 return r2;
1058 }
1059 #endif
1060 inline char BOOST_REGEX_CALL w32_tolower(char c, lcid_type idx)
1061 {
1062 char result[2];
1063 #ifndef BOOST_NO_ANSI_APIS
1064 int b = ::LCMapStringA(
1065 idx,
1066 LCMAP_LOWERCASE,
1067 &c,
1068 1,
1069 result,
1070 1);
1071 if (b == 0)
1072 return c;
1073 #else
1074 UINT code_page = get_code_page_for_locale_id(idx);
1075 if (code_page == 0)
1076 return c;
1077
1078 WCHAR wide_c;
1079 if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
1080 return c;
1081
1082 WCHAR wide_result;
1083 int b = ::LCMapStringW(
1084 idx,
1085 LCMAP_LOWERCASE,
1086 &wide_c,
1087 1,
1088 &wide_result,
1089 1);
1090 if (b == 0)
1091 return c;
1092
1093 if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
1094 return c;
1095 #endif
1096 return result[0];
1097 }
1098
1099 #ifndef BOOST_NO_WREGEX
1100 inline wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type idx)
1101 {
1102 wchar_t result[2];
1103 int b = ::LCMapStringW(
1104 idx,
1105 LCMAP_LOWERCASE,
1106 &c,
1107 1,
1108 result,
1109 1);
1110 if (b == 0)
1111 return c;
1112 return result[0];
1113 }
1114 #endif
1115 inline char BOOST_REGEX_CALL w32_toupper(char c, lcid_type idx)
1116 {
1117 char result[2];
1118 #ifndef BOOST_NO_ANSI_APIS
1119 int b = ::LCMapStringA(
1120 idx,
1121 LCMAP_UPPERCASE,
1122 &c,
1123 1,
1124 result,
1125 1);
1126 if (b == 0)
1127 return c;
1128 #else
1129 UINT code_page = get_code_page_for_locale_id(idx);
1130 if (code_page == 0)
1131 return c;
1132
1133 WCHAR wide_c;
1134 if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
1135 return c;
1136
1137 WCHAR wide_result;
1138 int b = ::LCMapStringW(
1139 idx,
1140 LCMAP_UPPERCASE,
1141 &wide_c,
1142 1,
1143 &wide_result,
1144 1);
1145 if (b == 0)
1146 return c;
1147
1148 if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
1149 return c;
1150 #endif
1151 return result[0];
1152 }
1153
1154 #ifndef BOOST_NO_WREGEX
1155 inline wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type idx)
1156 {
1157 wchar_t result[2];
1158 int b = ::LCMapStringW(
1159 idx,
1160 LCMAP_UPPERCASE,
1161 &c,
1162 1,
1163 result,
1164 1);
1165 if (b == 0)
1166 return c;
1167 return result[0];
1168 }
1169 #endif
1170 inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, char c)
1171 {
1172 WORD mask;
1173 #ifndef BOOST_NO_ANSI_APIS
1174 if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
1175 return true;
1176 #else
1177 UINT code_page = get_code_page_for_locale_id(idx);
1178 if (code_page == 0)
1179 return false;
1180
1181 WCHAR wide_c;
1182 if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
1183 return false;
1184
1185 if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
1186 return true;
1187 #endif
1188 if ((m & w32_regex_traits_implementation<char>::mask_word) && (c == '_'))
1189 return true;
1190 return false;
1191 }
1192
1193 #ifndef BOOST_NO_WREGEX
1194 inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, wchar_t c)
1195 {
1196 WORD mask;
1197 if (::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
1207 }
1208
1209
1210 }
1211
1212 #ifdef BOOST_MSVC
1213 #pragma warning(pop)
1214 #endif
1215
1216 #ifdef BOOST_MSVC
1217 #pragma warning(push)
1218 #pragma warning(disable: 4103)
1219 #endif
1220 #ifdef BOOST_HAS_ABI_HEADERS
1221 # include BOOST_ABI_SUFFIX
1222 #endif
1223 #ifdef BOOST_MSVC
1224 #pragma warning(pop)
1225 #endif
1226
1227 #endif
1228
1229 #endif