Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:28

0001 /*
0002  *
0003  * Copyright (c) 2004
0004  * John Maddock
0005  *
0006  * Use, modification and distribution are subject to the 
0007  * Boost Software License, Version 1.0. (See accompanying file 
0008  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009  *
0010  */
0011  
0012  /*
0013   *   LOCATION:    see http://www.boost.org for most recent version.
0014   *   FILE         w32_regex_traits.hpp
0015   *   VERSION      see <boost/version.hpp>
0016   *   DESCRIPTION: Declares regular expression traits class w32_regex_traits.
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 // forward declaration is needed by some compilers:
0072 //
0073 template <class charT>
0074 class w32_regex_traits;
0075    
0076 namespace BOOST_REGEX_DETAIL_NS{
0077 
0078 //
0079 // start by typedeffing the types we'll need:
0080 //
0081 typedef ::boost::uint32_t lcid_type;   // placeholder for LCID.
0082 typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE.
0083 
0084 //
0085 // then add wrappers around the actual Win32 API's (ie implementation hiding):
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 // class w32_regex_traits_base:
0119 // acts as a container for locale and the facets we are using.
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 // class w32_regex_traits_char_layer:
0141 // implements methods that require specialisation for narrow characters:
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    // TODO: use a hash table when available!
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    // we need to start by initialising our syntax map so we know which
0188    // character is used for which purpose:
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    // if we have a valid catalog then load our messages:
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 // specialised version for narrow characters:
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 // class w32_regex_traits_implementation:
0284 // provides pimpl implementation for w32_regex_traits.
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); // must be C1_DEFINED << 1
0292    BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2
0293    BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3
0294    BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4
0295    BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff);  // all the masks used by the CT_CTYPE1 group
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;   // error messages indexed by numberic ID
0330    std::map<string_type, char_class_type>  m_custom_class_names; // character class names
0331    std::map<string_type, string_type>      m_custom_collate_names; // collating element names
0332    unsigned                       m_collate_type;    // the form of the collation string
0333    charT                          m_collate_delim;   // the collation group delimiter
0334    //
0335    // helpers:
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    // What we do here depends upon the format of the sort key returned by
0347    // sort key returned by this->transform:
0348    //
0349    switch(m_collate_type)
0350    {
0351    case sort_C:
0352    case sort_unknown:
0353       // the best we can do is translate to lower case, then get a regular sort key:
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          // get a regular sort key, and then truncate it:
0365          result.assign(this->transform(p1, p2));
0366          result.erase(this->m_collate_delim);
0367          break;
0368       }
0369    case sort_delim:
0370          // get a regular sort key, and then truncate everything after the delim:
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    // if we have a valid catalog then load our messages:
0446    //
0447    if(cat)
0448    {
0449       //
0450       // Error messages:
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       // Custom class names:
0473       //
0474       static const char_class_type masks[14] = 
0475       {
0476          0x0104u, // C1_ALPHA | C1_DIGIT
0477          0x0100u, // C1_ALPHA
0478          0x0020u, // C1_CNTRL
0479          0x0004u, // C1_DIGIT
0480          (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE
0481          0x0002u, // C1_LOWER
0482          (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
0483          0x0010u, // C1_PUNCT
0484          0x0008u, // C1_SPACE
0485          0x0001u, // C1_UPPER
0486          0x0080u, // C1_XDIGIT
0487          0x0040u, // C1_BLANK
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    // get the collation format used by m_pcollate:
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, // C1_ALPHA | C1_DIGIT
0513       0x0100u, // C1_ALPHA
0514       0x0040u, // C1_BLANK
0515       0x0020u, // C1_CNTRL
0516       0x0004u, // C1_DIGIT
0517       0x0004u, // C1_DIGIT
0518       (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK
0519       w32_regex_traits_implementation<charT>::mask_horizontal, 
0520       0x0002u, // C1_LOWER
0521       0x0002u, // C1_LOWER
0522       (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
0523       0x0010u, // C1_PUNCT
0524       0x0008u, // C1_SPACE
0525       0x0008u, // C1_SPACE
0526       0x0001u, // C1_UPPER
0527       w32_regex_traits_implementation<charT>::mask_unicode,
0528       0x0001u, // C1_UPPER
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, // C1_XDIGIT
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    // TODO: create a cache for previously constructed objects.
0552    return boost::object_cache< ::boost::BOOST_REGEX_DETAIL_NS::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
0553 }
0554 
0555 } // BOOST_REGEX_DETAIL_NS
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    // extension:
0663    // set the name of the message catalog in use (defaults to "boost_regex").
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    // catalog name handler:
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       // we need to start by initialising our syntax map so we know which
0734       // character is used for which purpose:
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       // if we have a valid catalog then load our messages:
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       // finish off by calculating our escape types:
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       // fill in lower case map:
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          // if we have multibyte characters then not all may have been given
0816          // a lower case mapping:
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; // failed conversion.
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,       // locale identifier
0970          LCMAP_SORTKEY,  // mapping transformation type
0971          p1,  // source string
0972          static_cast<int>(p2 - p1),        // number of characters in source string
0973          0,  // destination buffer
0974          0        // size of destination buffer
0975       );
0976       if (!bytes)
0977          return std::string(p1, p2);
0978       std::string result(++bytes, '\0');
0979       bytes = ::LCMapStringA(
0980          idx,       // locale identifier
0981          LCMAP_SORTKEY,  // mapping transformation type
0982          p1,  // source string
0983          static_cast<int>(p2 - p1),        // number of characters in source string
0984          &*result.begin(),  // destination buffer
0985          bytes        // size of destination buffer
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,       // locale identifier
0999          LCMAP_SORTKEY,  // mapping transformation type
1000          wide_p1,  // source string
1001          src_len,        // number of characters in source string
1002          0,  // destination buffer
1003          0        // size of destination buffer
1004       );
1005       if (!bytes)
1006          return std::string(p1, p2);
1007       std::string result(++bytes, '\0');
1008       bytes = ::LCMapStringW(
1009          idx,       // locale identifier
1010          LCMAP_SORTKEY,  // mapping transformation type
1011          wide_p1,  // source string
1012          src_len,        // number of characters in source string
1013          (LPWSTR) & *result.begin(),  // destination buffer
1014          bytes        // size of destination buffer
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,       // locale identifier
1031          LCMAP_SORTKEY,  // mapping transformation type
1032          p1,  // source string
1033          static_cast<int>(p2 - p1),        // number of characters in source string
1034          0,  // destination buffer
1035          0        // size of destination buffer
1036       );
1037       if (!bytes)
1038          return std::wstring(p1, p2);
1039       std::string result(++bytes, '\0');
1040       bytes = ::LCMapStringW(
1041          idx,       // locale identifier
1042          LCMAP_SORTKEY,  // mapping transformation type
1043          p1,  // source string
1044          static_cast<int>(p2 - p1),        // number of characters in source string
1045          reinterpret_cast<wchar_t*>(&*result.begin()),  // destination buffer *of bytes*
1046          bytes        // size of destination buffer
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,       // locale identifier
1066          LCMAP_LOWERCASE,  // mapping transformation type
1067          &c,  // source string
1068          1,        // number of characters in source string
1069          result,  // destination buffer
1070          1);        // size of destination buffer
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,       // locale identifier
1085          LCMAP_LOWERCASE,  // mapping transformation type
1086          &wide_c,  // source string
1087          1,        // number of characters in source string
1088          &wide_result,  // destination buffer
1089          1);        // size of destination buffer
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;  // No single byte lower case equivalent available
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,       // locale identifier
1105          LCMAP_LOWERCASE,  // mapping transformation type
1106          &c,  // source string
1107          1,        // number of characters in source string
1108          result,  // destination buffer
1109          1);        // size of destination buffer
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,       // locale identifier
1121          LCMAP_UPPERCASE,  // mapping transformation type
1122          &c,  // source string
1123          1,        // number of characters in source string
1124          result,  // destination buffer
1125          1);        // size of destination buffer
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,       // locale identifier
1140          LCMAP_UPPERCASE,  // mapping transformation type
1141          &wide_c,  // source string
1142          1,        // number of characters in source string
1143          &wide_result,  // destination buffer
1144          1);        // size of destination buffer
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;  // No single byte upper case equivalent available.
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,       // locale identifier
1160          LCMAP_UPPERCASE,  // mapping transformation type
1161          &c,  // source string
1162          1,        // number of characters in source string
1163          result,  // destination buffer
1164          1);        // size of destination buffer
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 } // BOOST_REGEX_DETAIL_NS
1208 
1209 
1210 } // boost
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 // BOOST_REGEX_NO_WIN32_LOCALE
1228 
1229 #endif