Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-16 09:32:59

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 #include <boost/regex/pattern_except.hpp>
0025 #include <boost/regex/v5/regex_traits_defaults.hpp>
0026 #ifdef BOOST_HAS_THREADS
0027 #include <mutex>
0028 #endif
0029 #include <boost/regex/v5/primary_transform.hpp>
0030 #include <boost/regex/v5/object_cache.hpp>
0031 
0032 #if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
0033 #pragma comment(lib, "user32.lib")
0034 #endif
0035 
0036 #ifdef BOOST_REGEX_MSVC
0037 #pragma warning(push)
0038 #pragma warning(disable:4786)
0039 #if BOOST_REGEX_MSVC < 1910
0040 #pragma warning(disable:4800)
0041 #endif
0042 #endif
0043 
0044 #ifndef BASETYPES
0045 //
0046 // windows.h not included, so lets forward declare what we need:
0047 //
0048 #ifndef NO_STRICT
0049 #ifndef STRICT
0050 #define STRICT 1
0051 #endif
0052 #endif
0053 
0054 #if defined(STRICT)
0055 #define BOOST_RE_DETAIL_DECLARE_HANDLE(x) struct x##__; typedef struct x##__ *x
0056 #else
0057 #define BOOST_RE_DETAIL_DECLARE_HANDLE(x) typedef void* x
0058 #endif
0059 //
0060 // This must be in the global namespace:
0061 //
0062 extern "C" {
0063 
0064    BOOST_RE_DETAIL_DECLARE_HANDLE(HINSTANCE);
0065    typedef HINSTANCE HMODULE;
0066 }
0067 #endif
0068 
0069 namespace boost{ 
0070 
0071 //
0072 // forward declaration is needed by some compilers:
0073 //
0074 template <class charT>
0075 class w32_regex_traits;
0076    
0077 namespace BOOST_REGEX_DETAIL_NS{
0078 
0079 //
0080 // start by typedeffing the types we'll need:
0081 //
0082 typedef unsigned long lcid_type;        // placeholder for LCID.
0083 typedef std::shared_ptr<void> cat_type; // placeholder for dll HANDLE.
0084 
0085 //
0086 // then add wrappers around the actual Win32 API's (ie implementation hiding):
0087 //
0088 lcid_type  w32_get_default_locale();
0089 bool  w32_is_lower(char, lcid_type);
0090 #ifndef BOOST_NO_WREGEX
0091 bool  w32_is_lower(wchar_t, lcid_type);
0092 #endif
0093 bool  w32_is_upper(char, lcid_type);
0094 #ifndef BOOST_NO_WREGEX
0095 bool  w32_is_upper(wchar_t, lcid_type);
0096 #endif
0097 cat_type  w32_cat_open(const std::string& name);
0098 std::string  w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
0099 #ifndef BOOST_NO_WREGEX
0100 std::wstring  w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
0101 #endif
0102 std::string  w32_transform(lcid_type state_id, const char* p1, const char* p2);
0103 #ifndef BOOST_NO_WREGEX
0104 std::wstring  w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
0105 #endif
0106 char  w32_tolower(char c, lcid_type);
0107 #ifndef BOOST_NO_WREGEX
0108 wchar_t  w32_tolower(wchar_t c, lcid_type);
0109 #endif
0110 char  w32_toupper(char c, lcid_type);
0111 #ifndef BOOST_NO_WREGEX
0112 wchar_t  w32_toupper(wchar_t c, lcid_type);
0113 #endif
0114 bool  w32_is(lcid_type, std::uint32_t mask, char c);
0115 #ifndef BOOST_NO_WREGEX
0116 bool  w32_is(lcid_type, std::uint32_t mask, wchar_t c);
0117 #endif
0118 
0119 #ifndef BASETYPES
0120 //
0121 // Forward declarations of the small number of windows types and API's we use:
0122 //
0123 
0124 #if !defined(__LP64__)
0125 using dword = unsigned long;
0126 #else
0127 using DWORD = unsigned int;
0128 #endif
0129 using word = unsigned short;
0130 using lctype = dword;
0131 
0132 static constexpr dword ct_ctype1 = 0x00000001;
0133 static constexpr dword c1_upper = 0x0001;      // upper case
0134 static constexpr dword c1_lower = 0x0002;      // lower case
0135 static constexpr dword c1_digit = 0x0004;      // decimal digits
0136 static constexpr dword c1_space = 0x0008;      // spacing characters
0137 static constexpr dword c1_punct = 0x0010;      // punctuation characters
0138 static constexpr dword c1_cntrl = 0x0020;      // control characters
0139 static constexpr dword c1_blank = 0x0040;      // blank characters
0140 static constexpr dword c1_xdigit = 0x0080;      // other digits
0141 static constexpr dword c1_alpha = 0x0100;      // any linguistic character
0142 static constexpr dword c1_defined = 0x0200;      // defined character
0143 static constexpr unsigned int cp_acp = 0;
0144 static constexpr dword lcmap_lowercase = 0x00000100;
0145 static constexpr dword lcmap_uppercase = 0x00000200;
0146 static constexpr dword lcmap_sortkey = 0x00000400;  // WC sort key (normalize)
0147 static constexpr lctype locale_idefaultansicodepage = 0x00001004;
0148 
0149 # ifdef UNDER_CE
0150 #  ifndef WINAPI
0151 #   ifndef _WIN32_WCE_EMULATION
0152 #    define BOOST_RE_STDCALL __cdecl     // Note this doesn't match the desktop definition
0153 #   else
0154 #    define BOOST_RE_STDCALL __stdcall
0155 #   endif
0156 #  endif
0157 # else
0158 #  if defined(_M_IX86) || defined(__i386__)
0159 #   define BOOST_RE_STDCALL __stdcall
0160 #  else
0161     // On architectures other than 32-bit x86 __stdcall is ignored. Clang also issues a warning.
0162 #   define BOOST_RE_STDCALL
0163 #  endif
0164 # endif
0165 
0166 #if defined (WIN32_PLATFORM_PSPC)
0167 #define BOOST_RE_IMPORT __declspec( dllimport )
0168 #elif defined (_WIN32_WCE)
0169 #define BOOST_RE_IMPORT
0170 #else
0171 #define BOOST_RE_IMPORT __declspec( dllimport )
0172 #endif
0173 
0174 extern "C" {
0175 
0176    BOOST_RE_IMPORT int BOOST_RE_STDCALL FreeLibrary(HMODULE hLibModule);
0177    BOOST_RE_IMPORT int BOOST_RE_STDCALL LCMapStringA(lcid_type Locale, dword dwMapFlags, const char* lpSrcStr, int cchSrc, char* lpDestStr, int cchDest);
0178    BOOST_RE_IMPORT int BOOST_RE_STDCALL LCMapStringW(lcid_type Locale, dword dwMapFlags, const wchar_t* lpSrcStr, int cchSrc, wchar_t* lpDestStr, int cchDest);
0179    BOOST_RE_IMPORT int BOOST_RE_STDCALL MultiByteToWideChar(unsigned int CodePage, dword dwFlags, const char* lpMultiByteStr, int cbMultiByte, wchar_t* lpWideCharStr, int cchWideChar);
0180    BOOST_RE_IMPORT int BOOST_RE_STDCALL LCMapStringW(lcid_type Locale, dword dwMapFlags, const wchar_t* lpSrcStr, int cchSrc, wchar_t* lpDestStr, int cchDest);
0181    BOOST_RE_IMPORT int BOOST_RE_STDCALL WideCharToMultiByte(unsigned int CodePage, dword dwFlags, const wchar_t* lpWideCharStr, int cchWideChar, char* lpMultiByteStr, int cbMultiByte, const char* lpDefaultChar, int* lpUsedDefaultChar);
0182    BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExA(lcid_type Locale, dword dwInfoType, const char* lpSrcStr, int cchSrc, word* lpCharType);
0183    BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExW(lcid_type Locale, dword dwInfoType, const wchar_t* lpSrcStr, int cchSrc, word* lpCharType);
0184    BOOST_RE_IMPORT lcid_type BOOST_RE_STDCALL GetUserDefaultLCID();
0185    BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExA(lcid_type Locale, dword dwInfoType, const char* lpSrcStr, int cchSrc, word* lpCharType);
0186    BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExW(lcid_type Locale, dword dwInfoType, const wchar_t* lpSrcStr, int cchSrc, word* lpCharType);
0187    BOOST_RE_IMPORT HMODULE BOOST_RE_STDCALL LoadLibraryA(const char* lpLibFileName);
0188    BOOST_RE_IMPORT HMODULE BOOST_RE_STDCALL LoadLibraryW(const wchar_t* lpLibFileName);
0189    BOOST_RE_IMPORT int BOOST_RE_STDCALL LoadStringW(HINSTANCE hInstance, unsigned int uID, wchar_t* lpBuffer, int cchBufferMax);
0190    BOOST_RE_IMPORT int BOOST_RE_STDCALL LoadStringA(HINSTANCE hInstance, unsigned int uID, char* lpBuffer, int cchBufferMax);
0191    BOOST_RE_IMPORT int BOOST_RE_STDCALL GetLocaleInfoW(lcid_type Locale, lctype LCType, wchar_t* lpLCData, int cchData);
0192 }
0193 
0194 #else
0195 //
0196 // We have windows.h already included:
0197 //
0198 using dword = DWORD;
0199 using word = WORD;
0200 using lctype = LCTYPE;
0201 
0202 static constexpr dword ct_ctype1 = 0x00000001;
0203 static constexpr dword c1_upper = 0x0001;      // upper case
0204 static constexpr dword c1_lower = 0x0002;      // lower case
0205 static constexpr dword c1_digit = 0x0004;      // decimal digits
0206 static constexpr dword c1_space = 0x0008;      // spacing characters
0207 static constexpr dword c1_punct = 0x0010;      // punctuation characters
0208 static constexpr dword c1_cntrl = 0x0020;      // control characters
0209 static constexpr dword c1_blank = 0x0040;      // blank characters
0210 static constexpr dword c1_xdigit = 0x0080;      // other digits
0211 static constexpr dword c1_alpha = 0x0100;      // any linguistic character
0212 static constexpr dword c1_defined = 0x0200;      // defined character
0213 static constexpr unsigned int cp_acp = 0;
0214 static constexpr dword lcmap_lowercase = 0x00000100;
0215 static constexpr dword lcmap_uppercase = 0x00000200;
0216 static constexpr dword lcmap_sortkey = 0x00000400;  // WC sort key (normalize)
0217 static constexpr lctype locale_idefaultansicodepage = 0x00001004;
0218 
0219 using ::FreeLibrary;
0220 using ::LCMapStringA;
0221 using ::LCMapStringW;
0222 using ::MultiByteToWideChar;
0223 using ::LCMapStringW;
0224 using ::WideCharToMultiByte;
0225 using ::GetStringTypeExA;
0226 using ::GetStringTypeExW;
0227 using ::GetUserDefaultLCID;
0228 using ::GetStringTypeExA;
0229 using ::GetStringTypeExW;
0230 using ::LoadLibraryA;
0231 using ::LoadLibraryW;
0232 using ::LoadStringW;
0233 using ::LoadStringA;
0234 using ::GetLocaleInfoW;
0235 
0236 #endif
0237 //
0238 // class w32_regex_traits_base:
0239 // acts as a container for locale and the facets we are using.
0240 //
0241 template <class charT>
0242 struct w32_regex_traits_base
0243 {
0244    w32_regex_traits_base(lcid_type l)
0245    { imbue(l); }
0246    lcid_type imbue(lcid_type l);
0247 
0248    lcid_type m_locale;
0249 };
0250 
0251 template <class charT>
0252 inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l)
0253 {
0254    lcid_type result(m_locale);
0255    m_locale = l;
0256    return result;
0257 }
0258 
0259 //
0260 // class w32_regex_traits_char_layer:
0261 // implements methods that require specialisation for narrow characters:
0262 //
0263 template <class charT>
0264 class w32_regex_traits_char_layer : public w32_regex_traits_base<charT>
0265 {
0266    typedef std::basic_string<charT> string_type;
0267    typedef std::map<charT, regex_constants::syntax_type> map_type;
0268    typedef typename map_type::const_iterator map_iterator_type;
0269 public:
0270    w32_regex_traits_char_layer(const lcid_type l);
0271 
0272    regex_constants::syntax_type syntax_type(charT c)const
0273    {
0274       map_iterator_type i = m_char_map.find(c);
0275       return ((i == m_char_map.end()) ? 0 : i->second);
0276    }
0277    regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0278    {
0279       map_iterator_type i = m_char_map.find(c);
0280       if(i == m_char_map.end())
0281       {
0282          if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class;
0283          if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class;
0284          return 0;
0285       }
0286       return i->second;
0287    }
0288    charT tolower(charT c)const
0289    {
0290       return ::boost::BOOST_REGEX_DETAIL_NS::w32_tolower(c, this->m_locale);
0291    }
0292    bool isctype(std::uint32_t mask, charT c)const
0293    {
0294       return ::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, mask, c);
0295    }
0296 
0297 private:
0298    string_type get_default_message(regex_constants::syntax_type);
0299    // TODO: use a hash table when available!
0300    map_type m_char_map;
0301 };
0302 
0303 template <class charT>
0304 w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) 
0305    : w32_regex_traits_base<charT>(l)
0306 {
0307    // we need to start by initialising our syntax map so we know which
0308    // character is used for which purpose:
0309    cat_type cat;
0310    std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
0311    if(cat_name.size())
0312    {
0313       cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
0314       if(!cat)
0315       {
0316          std::string m("Unable to open message catalog: ");
0317          std::runtime_error err(m + cat_name);
0318          boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0319       }
0320    }
0321    //
0322    // if we have a valid catalog then load our messages:
0323    //
0324    if(cat)
0325    {
0326       for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0327       {
0328          string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_message(i));
0329          for(typename string_type::size_type j = 0; j < mss.size(); ++j)
0330          {
0331             this->m_char_map[mss[j]] = i;
0332          }
0333       }
0334    }
0335    else
0336    {
0337       for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0338       {
0339          const char* ptr = get_default_syntax(i);
0340          while(ptr && *ptr)
0341          {
0342             this->m_char_map[static_cast<charT>(*ptr)] = i;
0343             ++ptr;
0344          }
0345       }
0346    }
0347 }
0348 
0349 template <class charT>
0350 typename w32_regex_traits_char_layer<charT>::string_type 
0351    w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
0352 {
0353    const char* ptr = get_default_syntax(i);
0354    string_type result;
0355    while(ptr && *ptr)
0356    {
0357       result.append(1, static_cast<charT>(*ptr));
0358       ++ptr;
0359    }
0360    return result;
0361 }
0362 
0363 //
0364 // specialised version for narrow characters:
0365 //
0366 template <>
0367 class w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
0368 {
0369    typedef std::string string_type;
0370 public:
0371    w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0372    : w32_regex_traits_base<char>(l)
0373    {
0374       init<char>();
0375    }
0376 
0377    regex_constants::syntax_type syntax_type(char c)const
0378    {
0379       return m_char_map[static_cast<unsigned char>(c)];
0380    }
0381    regex_constants::escape_syntax_type escape_syntax_type(char c) const
0382    {
0383       return m_char_map[static_cast<unsigned char>(c)];
0384    }
0385    char tolower(char c)const
0386    {
0387       return m_lower_map[static_cast<unsigned char>(c)];
0388    }
0389    bool isctype(std::uint32_t mask, char c)const
0390    {
0391       return m_type_map[static_cast<unsigned char>(c)] & mask;
0392    }
0393 
0394 private:
0395    regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
0396    char m_lower_map[1u << CHAR_BIT];
0397    std::uint16_t m_type_map[1u << CHAR_BIT];
0398    template <class U>
0399    void init();
0400 };
0401 
0402 //
0403 // class w32_regex_traits_implementation:
0404 // provides pimpl implementation for w32_regex_traits.
0405 //
0406 template <class charT>
0407 class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT>
0408 {
0409 public:
0410    typedef typename w32_regex_traits<charT>::char_class_type char_class_type;
0411    static const char_class_type mask_word = 0x0400; // must be C1_DEFINED << 1
0412    static const char_class_type mask_unicode = 0x0800; // must be C1_DEFINED << 2
0413    static const char_class_type mask_horizontal = 0x1000; // must be C1_DEFINED << 3
0414    static const char_class_type mask_vertical = 0x2000; // must be C1_DEFINED << 4
0415    static const char_class_type mask_base = 0x3ff;  // all the masks used by the CT_CTYPE1 group
0416 
0417    typedef std::basic_string<charT> string_type;
0418    typedef charT char_type;
0419    w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l);
0420    std::string error_string(regex_constants::error_type n) const
0421    {
0422       if(!m_error_strings.empty())
0423       {
0424          std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
0425          return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
0426       }
0427       return get_default_error_string(n);
0428    }
0429    char_class_type lookup_classname(const charT* p1, const charT* p2) const
0430    {
0431       char_class_type result = lookup_classname_imp(p1, p2);
0432       if(result == 0)
0433       {
0434          typedef typename string_type::size_type size_type;
0435          string_type temp(p1, p2);
0436          for(size_type i = 0; i < temp.size(); ++i)
0437             temp[i] = this->tolower(temp[i]);
0438          result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
0439       }
0440       return result;
0441    }
0442    string_type lookup_collatename(const charT* p1, const charT* p2) const;
0443    string_type transform_primary(const charT* p1, const charT* p2) const;
0444    string_type transform(const charT* p1, const charT* p2) const
0445    {
0446       return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_locale, p1, p2);
0447    }
0448 private:
0449    std::map<int, std::string>     m_error_strings;   // error messages indexed by numberic ID
0450    std::map<string_type, char_class_type>  m_custom_class_names; // character class names
0451    std::map<string_type, string_type>      m_custom_collate_names; // collating element names
0452    unsigned                       m_collate_type;    // the form of the collation string
0453    charT                          m_collate_delim;   // the collation group delimiter
0454    //
0455    // helpers:
0456    //
0457    char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
0458 };
0459 
0460 template <class charT>
0461 typename w32_regex_traits_implementation<charT>::string_type 
0462    w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
0463 {
0464    string_type result;
0465    //
0466    // What we do here depends upon the format of the sort key returned by
0467    // sort key returned by this->transform:
0468    //
0469    switch(m_collate_type)
0470    {
0471    case sort_C:
0472    case sort_unknown:
0473       // the best we can do is translate to lower case, then get a regular sort key:
0474       {
0475          result.assign(p1, p2);
0476          typedef typename string_type::size_type size_type;
0477          for(size_type i = 0; i < result.size(); ++i)
0478             result[i] = this->tolower(result[i]);
0479          result = this->transform(&*result.begin(), &*result.begin() + result.size());
0480          break;
0481       }
0482    case sort_fixed:
0483       {
0484          // get a regular sort key, and then truncate it:
0485          result.assign(this->transform(p1, p2));
0486          result.erase(this->m_collate_delim);
0487          break;
0488       }
0489    case sort_delim:
0490          // get a regular sort key, and then truncate everything after the delim:
0491          result.assign(this->transform(p1, p2));
0492          std::size_t i;
0493          for(i = 0; i < result.size(); ++i)
0494          {
0495             if(result[i] == m_collate_delim)
0496                break;
0497          }
0498          result.erase(i);
0499          break;
0500    }
0501    if(result.empty())
0502       result = string_type(1, charT(0));
0503    return result;
0504 }
0505 
0506 template <class charT>
0507 typename w32_regex_traits_implementation<charT>::string_type 
0508    w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
0509 {
0510    typedef typename std::map<string_type, string_type>::const_iterator iter_type;
0511    if(m_custom_collate_names.size())
0512    {
0513       iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
0514       if(pos != m_custom_collate_names.end())
0515          return pos->second;
0516    }
0517    std::string name(p1, p2);
0518    name = lookup_default_collate_name(name);
0519    if(name.size())
0520       return string_type(name.begin(), name.end());
0521    if(p2 - p1 == 1)
0522       return string_type(1, *p1);
0523    return string_type();
0524 }
0525 
0526 template <class charT>
0527 w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0528 : w32_regex_traits_char_layer<charT>(l)
0529 {
0530    cat_type cat;
0531    std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
0532    if(cat_name.size())
0533    {
0534       cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
0535       if(!cat)
0536       {
0537          std::string m("Unable to open message catalog: ");
0538          std::runtime_error err(m + cat_name);
0539          boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0540       }
0541    }
0542    //
0543    // if we have a valid catalog then load our messages:
0544    //
0545    if(cat)
0546    {
0547       //
0548       // Error messages:
0549       //
0550       for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0); 
0551          i <= boost::regex_constants::error_unknown; 
0552          i = static_cast<boost::regex_constants::error_type>(i + 1))
0553       {
0554          const char* p = get_default_error_string(i);
0555          string_type default_message;
0556          while(*p)
0557          {
0558             default_message.append(1, static_cast<charT>(*p));
0559             ++p;
0560          }
0561          string_type s = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i+200, default_message);
0562          std::string result;
0563          for(std::string::size_type j = 0; j < s.size(); ++j)
0564          {
0565             result.append(1, static_cast<char>(s[j]));
0566          }
0567          m_error_strings[i] = result;
0568       }
0569       //
0570       // Custom class names:
0571       //
0572       static const char_class_type masks[14] = 
0573       {
0574          0x0104u, // C1_ALPHA | C1_DIGIT
0575          0x0100u, // C1_ALPHA
0576          0x0020u, // C1_CNTRL
0577          0x0004u, // C1_DIGIT
0578          (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE
0579          0x0002u, // C1_LOWER
0580          (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
0581          0x0010u, // C1_PUNCT
0582          0x0008u, // C1_SPACE
0583          0x0001u, // C1_UPPER
0584          0x0080u, // C1_XDIGIT
0585          0x0040u, // C1_BLANK
0586          w32_regex_traits_implementation<charT>::mask_word,
0587          w32_regex_traits_implementation<charT>::mask_unicode,
0588       };
0589       static const string_type null_string;
0590       for(unsigned int j = 0; j <= 13; ++j)
0591       {
0592          string_type s(::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, j+300, null_string));
0593          if(s.size())
0594             this->m_custom_class_names[s] = masks[j];
0595       }
0596    }
0597    //
0598    // get the collation format used by m_pcollate:
0599    //
0600    m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim);
0601 }
0602 
0603 template <class charT>
0604 typename w32_regex_traits_implementation<charT>::char_class_type 
0605    w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
0606 {
0607    static const char_class_type masks[22] = 
0608    {
0609       0,
0610       0x0104u, // C1_ALPHA | C1_DIGIT
0611       0x0100u, // C1_ALPHA
0612       0x0040u, // C1_BLANK
0613       0x0020u, // C1_CNTRL
0614       0x0004u, // C1_DIGIT
0615       0x0004u, // C1_DIGIT
0616       (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK
0617       w32_regex_traits_implementation<charT>::mask_horizontal, 
0618       0x0002u, // C1_LOWER
0619       0x0002u, // C1_LOWER
0620       (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
0621       0x0010u, // C1_PUNCT
0622       0x0008u, // C1_SPACE
0623       0x0008u, // C1_SPACE
0624       0x0001u, // C1_UPPER
0625       w32_regex_traits_implementation<charT>::mask_unicode,
0626       0x0001u, // C1_UPPER
0627       w32_regex_traits_implementation<charT>::mask_vertical, 
0628       0x0104u | w32_regex_traits_implementation<charT>::mask_word, 
0629       0x0104u | w32_regex_traits_implementation<charT>::mask_word, 
0630       0x0080u, // C1_XDIGIT
0631    };
0632    if(m_custom_class_names.size())
0633    {
0634       typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
0635       map_iter pos = m_custom_class_names.find(string_type(p1, p2));
0636       if(pos != m_custom_class_names.end())
0637          return pos->second;
0638    }
0639    std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
0640    if(state_id < sizeof(masks) / sizeof(masks[0]))
0641       return masks[state_id];
0642    return masks[0];
0643 }
0644 
0645 
0646 template <class charT>
0647 std::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
0648 {
0649    // TODO: create a cache for previously constructed objects.
0650    return boost::object_cache< ::boost::BOOST_REGEX_DETAIL_NS::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
0651 }
0652 
0653 } // BOOST_REGEX_DETAIL_NS
0654 
0655 template <class charT>
0656 class w32_regex_traits
0657 {
0658 public:
0659    typedef charT                         char_type;
0660    typedef std::size_t                   size_type;
0661    typedef std::basic_string<char_type>  string_type;
0662    typedef ::boost::BOOST_REGEX_DETAIL_NS::lcid_type locale_type;
0663    typedef std::uint_least32_t         char_class_type;
0664 
0665    struct boost_extensions_tag{};
0666 
0667    w32_regex_traits()
0668       : m_pimpl(BOOST_REGEX_DETAIL_NS::create_w32_regex_traits<charT>(::boost::BOOST_REGEX_DETAIL_NS::w32_get_default_locale()))
0669    { }
0670    static size_type length(const char_type* p)
0671    {
0672       return std::char_traits<charT>::length(p);
0673    }
0674    regex_constants::syntax_type syntax_type(charT c)const
0675    {
0676       return m_pimpl->syntax_type(c);
0677    }
0678    regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0679    {
0680       return m_pimpl->escape_syntax_type(c);
0681    }
0682    charT translate(charT c) const
0683    {
0684       return c;
0685    }
0686    charT translate_nocase(charT c) const
0687    {
0688       return this->m_pimpl->tolower(c);
0689    }
0690    charT translate(charT c, bool icase) const
0691    {
0692       return icase ? this->m_pimpl->tolower(c) : c;
0693    }
0694    charT tolower(charT c) const
0695    {
0696       return this->m_pimpl->tolower(c);
0697    }
0698    charT toupper(charT c) const
0699    {
0700       return ::boost::BOOST_REGEX_DETAIL_NS::w32_toupper(c, this->m_pimpl->m_locale);
0701    }
0702    string_type transform(const charT* p1, const charT* p2) const
0703    {
0704       return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_pimpl->m_locale, p1, p2);
0705    }
0706    string_type transform_primary(const charT* p1, const charT* p2) const
0707    {
0708       return m_pimpl->transform_primary(p1, p2);
0709    }
0710    char_class_type lookup_classname(const charT* p1, const charT* p2) const
0711    {
0712       return m_pimpl->lookup_classname(p1, p2);
0713    }
0714    string_type lookup_collatename(const charT* p1, const charT* p2) const
0715    {
0716       return m_pimpl->lookup_collatename(p1, p2);
0717    }
0718    bool isctype(charT c, char_class_type f) const
0719    {
0720       if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_base) 
0721          && (this->m_pimpl->isctype(f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_base, c)))
0722          return true;
0723       else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c))
0724          return true;
0725       else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_word) && (c == '_'))
0726          return true;
0727       else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_vertical)
0728          && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
0729          return true;
0730       else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_horizontal) 
0731          && this->isctype(c, 0x0008u) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT>::mask_vertical))
0732          return true;
0733       return false;
0734    }
0735    std::intmax_t toi(const charT*& p1, const charT* p2, int radix)const
0736    {
0737       return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this);
0738    }
0739    int value(charT c, int radix)const
0740    {
0741       int result = (int)::boost::BOOST_REGEX_DETAIL_NS::global_value(c);
0742       return result < radix ? result : -1;
0743    }
0744    locale_type imbue(locale_type l)
0745    {
0746       ::boost::BOOST_REGEX_DETAIL_NS::lcid_type result(getloc());
0747       m_pimpl = BOOST_REGEX_DETAIL_NS::create_w32_regex_traits<charT>(l);
0748       return result;
0749    }
0750    locale_type getloc()const
0751    {
0752       return m_pimpl->m_locale;
0753    }
0754    std::string error_string(regex_constants::error_type n) const
0755    {
0756       return m_pimpl->error_string(n);
0757    }
0758 
0759    //
0760    // extension:
0761    // set the name of the message catalog in use (defaults to "boost_regex").
0762    //
0763    static std::string catalog_name(const std::string& name);
0764    static std::string get_catalog_name();
0765 
0766 private:
0767    std::shared_ptr<const BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation<charT> > m_pimpl;
0768    //
0769    // catalog name handler:
0770    //
0771    static std::string& get_catalog_name_inst();
0772 
0773 #ifdef BOOST_HAS_THREADS
0774    static std::mutex& get_mutex_inst();
0775 #endif
0776 };
0777 
0778 template <class charT>
0779 std::string w32_regex_traits<charT>::catalog_name(const std::string& name)
0780 {
0781 #ifdef BOOST_HAS_THREADS
0782    std::lock_guard<std::mutex> lk(get_mutex_inst());
0783 #endif
0784    std::string result(get_catalog_name_inst());
0785    get_catalog_name_inst() = name;
0786    return result;
0787 }
0788 
0789 template <class charT>
0790 std::string& w32_regex_traits<charT>::get_catalog_name_inst()
0791 {
0792    static std::string s_name;
0793    return s_name;
0794 }
0795 
0796 template <class charT>
0797 std::string w32_regex_traits<charT>::get_catalog_name()
0798 {
0799 #ifdef BOOST_HAS_THREADS
0800    std::lock_guard<std::mutex> lk(get_mutex_inst());
0801 #endif
0802    std::string result(get_catalog_name_inst());
0803    return result;
0804 }
0805 
0806 #ifdef BOOST_HAS_THREADS
0807 template <class charT>
0808 std::mutex& w32_regex_traits<charT>::get_mutex_inst()
0809 {
0810    static std::mutex s_mutex;
0811    return s_mutex;
0812 }
0813 #endif
0814 
0815 namespace BOOST_REGEX_DETAIL_NS {
0816 
0817 #ifdef BOOST_NO_ANSI_APIS
0818    inline unsigned int get_code_page_for_locale_id(lcid_type idx)
0819    {
0820       wchar_t code_page_string[7];
0821       if (boost::BOOST_REGEX_DETAIL_NS::GetLocaleInfoW(idx, locale_idefaultansicodepage, code_page_string, 7) == 0)
0822          return 0;
0823 
0824       return static_cast<unsigned int>(_wtol(code_page_string));
0825 }
0826 #endif
0827 
0828    template <class U>
0829    inline void w32_regex_traits_char_layer<char>::init()
0830    {
0831       // we need to start by initialising our syntax map so we know which
0832       // character is used for which purpose:
0833       std::memset(m_char_map, 0, sizeof(m_char_map));
0834       cat_type cat;
0835       std::string cat_name(w32_regex_traits<char>::get_catalog_name());
0836       if (cat_name.size())
0837       {
0838          cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
0839          if (!cat)
0840          {
0841             std::string m("Unable to open message catalog: ");
0842             std::runtime_error err(m + cat_name);
0843             ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0844          }
0845       }
0846       //
0847       // if we have a valid catalog then load our messages:
0848       //
0849       if (cat)
0850       {
0851          for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0852          {
0853             string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i));
0854             for (string_type::size_type j = 0; j < mss.size(); ++j)
0855             {
0856                m_char_map[static_cast<unsigned char>(mss[j])] = i;
0857             }
0858          }
0859       }
0860       else
0861       {
0862          for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0863          {
0864             const char* ptr = get_default_syntax(i);
0865             while (ptr && *ptr)
0866             {
0867                m_char_map[static_cast<unsigned char>(*ptr)] = i;
0868                ++ptr;
0869             }
0870          }
0871       }
0872       //
0873       // finish off by calculating our escape types:
0874       //
0875       unsigned char i = 'A';
0876       do
0877       {
0878          if (m_char_map[i] == 0)
0879          {
0880             if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0002u, (char)i))
0881                m_char_map[i] = regex_constants::escape_type_class;
0882             else if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0001u, (char)i))
0883                m_char_map[i] = regex_constants::escape_type_not_class;
0884          }
0885       } while (0xFF != i++);
0886 
0887       //
0888       // fill in lower case map:
0889       //
0890       char char_map[1 << CHAR_BIT];
0891       for (int ii = 0; ii < (1 << CHAR_BIT); ++ii)
0892          char_map[ii] = static_cast<char>(ii);
0893 #ifndef BOOST_NO_ANSI_APIS
0894       int r = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA(this->m_locale, lcmap_lowercase, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT);
0895       BOOST_REGEX_ASSERT(r != 0);
0896 #else
0897       unsigned int code_page = get_code_page_for_locale_id(this->m_locale);
0898       BOOST_REGEX_ASSERT(code_page != 0);
0899 
0900       wchar_t wide_char_map[1 << CHAR_BIT];
0901       int conv_r = boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, char_map, 1 << CHAR_BIT, wide_char_map, 1 << CHAR_BIT);
0902       BOOST_REGEX_ASSERT(conv_r != 0);
0903 
0904       wchar_t wide_lower_map[1 << CHAR_BIT];
0905       int r = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(this->m_locale, lcmap_lowercase, wide_char_map, 1 << CHAR_BIT, wide_lower_map, 1 << CHAR_BIT);
0906       BOOST_REGEX_ASSERT(r != 0);
0907 
0908       conv_r = boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(code_page, 0, wide_lower_map, r, this->m_lower_map, 1 << CHAR_BIT, NULL, NULL);
0909       BOOST_REGEX_ASSERT(conv_r != 0);
0910 #endif
0911       if (r < (1 << CHAR_BIT))
0912       {
0913          // if we have multibyte characters then not all may have been given
0914          // a lower case mapping:
0915          for (int jj = r; jj < (1 << CHAR_BIT); ++jj)
0916             this->m_lower_map[jj] = static_cast<char>(jj);
0917       }
0918 
0919 #ifndef BOOST_NO_ANSI_APIS
0920       r = boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(this->m_locale, ct_ctype1, char_map, 1 << CHAR_BIT, this->m_type_map);
0921 #else
0922       r = boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(this->m_locale, ct_ctype1, wide_char_map, 1 << CHAR_BIT, this->m_type_map);
0923 #endif
0924       BOOST_REGEX_ASSERT(0 != r);
0925    }
0926 
0927    inline lcid_type  w32_get_default_locale()
0928    {
0929       return boost::BOOST_REGEX_DETAIL_NS::GetUserDefaultLCID();
0930    }
0931 
0932    inline bool  w32_is_lower(char c, lcid_type idx)
0933    {
0934 #ifndef BOOST_NO_ANSI_APIS
0935       word mask;
0936       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_lower))
0937          return true;
0938       return false;
0939 #else
0940       unsigned int code_page = get_code_page_for_locale_id(idx);
0941       if (code_page == 0)
0942          return false;
0943 
0944       wchar_t wide_c;
0945       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
0946          return false;
0947 
0948       word mask;
0949       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &wide_c, 1, &mask) && (mask & c1_lower))
0950          return true;
0951       return false;
0952 #endif
0953    }
0954 
0955    inline bool  w32_is_lower(wchar_t c, lcid_type idx)
0956    {
0957       word mask;
0958       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_lower))
0959          return true;
0960       return false;
0961    }
0962 
0963    inline bool  w32_is_upper(char c, lcid_type idx)
0964    {
0965 #ifndef BOOST_NO_ANSI_APIS
0966       word mask;
0967       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_upper))
0968          return true;
0969       return false;
0970 #else
0971       unsigned int code_page = get_code_page_for_locale_id(idx);
0972       if (code_page == 0)
0973          return false;
0974 
0975       wchar_t wide_c;
0976       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
0977          return false;
0978 
0979       word mask;
0980       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &wide_c, 1, &mask) && (mask & c1_upper))
0981          return true;
0982       return false;
0983 #endif
0984    }
0985 
0986    inline bool  w32_is_upper(wchar_t c, lcid_type idx)
0987    {
0988       word mask;
0989       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_upper))
0990          return true;
0991       return false;
0992    }
0993 
0994    inline void free_module(void* mod)
0995    {
0996       boost::BOOST_REGEX_DETAIL_NS::FreeLibrary(static_cast<HMODULE>(mod));
0997    }
0998 
0999    inline cat_type  w32_cat_open(const std::string& name)
1000    {
1001 #ifndef BOOST_NO_ANSI_APIS
1002       cat_type result(boost::BOOST_REGEX_DETAIL_NS::LoadLibraryA(name.c_str()), &free_module);
1003       return result;
1004 #else
1005       wchar_t* wide_name = (wchar_t*)_alloca((name.size() + 1) * sizeof(wchar_t));
1006       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(cp_acp, 0, name.c_str(), (int)name.size(), wide_name, (int)(name.size() + 1)) == 0)
1007          return cat_type();
1008 
1009       cat_type result(boost::BOOST_REGEX_DETAIL_NS::LoadLibraryW(wide_name), &free_module);
1010       return result;
1011 #endif
1012    }
1013 
1014    inline std::string  w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def)
1015    {
1016 #ifndef BOOST_NO_ANSI_APIS
1017       char buf[256];
1018       if (0 == boost::BOOST_REGEX_DETAIL_NS::LoadStringA(
1019          static_cast<HMODULE>(cat.get()),
1020          i,
1021          buf,
1022          256
1023       ))
1024       {
1025          return def;
1026       }
1027 #else
1028       wchar_t wbuf[256];
1029       int r = boost::BOOST_REGEX_DETAIL_NS::LoadStringW(
1030          static_cast<HMODULE>(cat.get()),
1031          i,
1032          wbuf,
1033          256
1034       );
1035       if (r == 0)
1036          return def;
1037 
1038 
1039       int buf_size = 1 + boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(cp_acp, 0, wbuf, r, NULL, 0, NULL, NULL);
1040       char* buf = (char*)_alloca(buf_size);
1041       if (boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(cp_acp, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0)
1042          return def; // failed conversion.
1043 #endif
1044       return std::string(buf);
1045    }
1046 
1047 #ifndef BOOST_NO_WREGEX
1048    inline std::wstring  w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def)
1049    {
1050       wchar_t buf[256];
1051       if (0 == boost::BOOST_REGEX_DETAIL_NS::LoadStringW(static_cast<HMODULE>(cat.get()), i, buf, 256))
1052       {
1053          return def;
1054       }
1055       return std::wstring(buf);
1056    }
1057 #endif
1058    inline std::string  w32_transform(lcid_type idx, const char* p1, const char* p2)
1059    {
1060 #ifndef BOOST_NO_ANSI_APIS
1061       int bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA(
1062          idx,       // locale identifier
1063          lcmap_sortkey,  // mapping transformation type
1064          p1,  // source string
1065          static_cast<int>(p2 - p1),        // number of characters in source string
1066          0,  // destination buffer
1067          0        // size of destination buffer
1068       );
1069       if (!bytes)
1070          return std::string(p1, p2);
1071       std::string result(++bytes, '\0');
1072       bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA(
1073          idx,       // locale identifier
1074          lcmap_sortkey,  // mapping transformation type
1075          p1,  // source string
1076          static_cast<int>(p2 - p1),        // number of characters in source string
1077          &*result.begin(),  // destination buffer
1078          bytes        // size of destination buffer
1079       );
1080 #else
1081       unsigned int code_page = get_code_page_for_locale_id(idx);
1082       if (code_page == 0)
1083          return std::string(p1, p2);
1084 
1085       int src_len = static_cast<int>(p2 - p1);
1086       wchar_t* wide_p1 = (wchar_t*)_alloca((src_len + 1) * 2);
1087       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, p1, src_len, wide_p1, src_len + 1) == 0)
1088          return std::string(p1, p2);
1089 
1090       int bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1091          idx,       // locale identifier
1092          lcmap_sortkey,  // mapping transformation type
1093          wide_p1,  // source string
1094          src_len,        // number of characters in source string
1095          0,  // destination buffer
1096          0        // size of destination buffer
1097       );
1098       if (!bytes)
1099          return std::string(p1, p2);
1100       std::string result(++bytes, '\0');
1101       bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1102          idx,       // locale identifier
1103          lcmap_sortkey,  // mapping transformation type
1104          wide_p1,  // source string
1105          src_len,        // number of characters in source string
1106          (wchar_t*) & *result.begin(),  // destination buffer
1107          bytes        // size of destination buffer
1108       );
1109 #endif
1110       if (bytes > static_cast<int>(result.size()))
1111          return std::string(p1, p2);
1112       while (result.size() && result[result.size() - 1] == '\0')
1113       {
1114          result.erase(result.size() - 1);
1115       }
1116       return result;
1117    }
1118 
1119 #ifndef BOOST_NO_WREGEX
1120    inline std::wstring  w32_transform(lcid_type idx, const wchar_t* p1, const wchar_t* p2)
1121    {
1122       int bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1123          idx,       // locale identifier
1124          lcmap_sortkey,  // mapping transformation type
1125          p1,  // source string
1126          static_cast<int>(p2 - p1),        // number of characters in source string
1127          0,  // destination buffer
1128          0        // size of destination buffer
1129       );
1130       if (!bytes)
1131          return std::wstring(p1, p2);
1132       std::string result(++bytes, '\0');
1133       bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1134          idx,       // locale identifier
1135          lcmap_sortkey,  // mapping transformation type
1136          p1,  // source string
1137          static_cast<int>(p2 - p1),        // number of characters in source string
1138          reinterpret_cast<wchar_t*>(&*result.begin()),  // destination buffer *of bytes*
1139          bytes        // size of destination buffer
1140       );
1141       if (bytes > static_cast<int>(result.size()))
1142          return std::wstring(p1, p2);
1143       while (result.size() && result[result.size() - 1] == L'\0')
1144       {
1145          result.erase(result.size() - 1);
1146       }
1147       std::wstring r2;
1148       for (std::string::size_type i = 0; i < result.size(); ++i)
1149          r2.append(1, static_cast<wchar_t>(static_cast<unsigned char>(result[i])));
1150       return r2;
1151    }
1152 #endif
1153    inline char  w32_tolower(char c, lcid_type idx)
1154    {
1155       char result[2];
1156 #ifndef BOOST_NO_ANSI_APIS
1157       int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA(
1158          idx,       // locale identifier
1159          lcmap_lowercase,  // mapping transformation type
1160          &c,  // source string
1161          1,        // number of characters in source string
1162          result,  // destination buffer
1163          1);        // size of destination buffer
1164       if (b == 0)
1165          return c;
1166 #else
1167       unsigned int code_page = get_code_page_for_locale_id(idx);
1168       if (code_page == 0)
1169          return c;
1170 
1171       wchar_t wide_c;
1172       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
1173          return c;
1174 
1175       wchar_t  wide_result;
1176       int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1177          idx,       // locale identifier
1178          lcmap_lowercase,  // mapping transformation type
1179          &wide_c,  // source string
1180          1,        // number of characters in source string
1181          &wide_result,  // destination buffer
1182          1);        // size of destination buffer
1183       if (b == 0)
1184          return c;
1185 
1186       if (boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
1187          return c;  // No single byte lower case equivalent available
1188 #endif
1189       return result[0];
1190    }
1191 
1192 #ifndef BOOST_NO_WREGEX
1193    inline wchar_t  w32_tolower(wchar_t c, lcid_type idx)
1194    {
1195       wchar_t result[2];
1196       int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1197          idx,       // locale identifier
1198          lcmap_lowercase,  // mapping transformation type
1199          &c,  // source string
1200          1,        // number of characters in source string
1201          result,  // destination buffer
1202          1);        // size of destination buffer
1203       if (b == 0)
1204          return c;
1205       return result[0];
1206    }
1207 #endif
1208    inline char  w32_toupper(char c, lcid_type idx)
1209    {
1210       char result[2];
1211 #ifndef BOOST_NO_ANSI_APIS
1212       int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA(
1213          idx,       // locale identifier
1214          lcmap_uppercase,  // mapping transformation type
1215          &c,  // source string
1216          1,        // number of characters in source string
1217          result,  // destination buffer
1218          1);        // size of destination buffer
1219       if (b == 0)
1220          return c;
1221 #else
1222       unsigned int code_page = get_code_page_for_locale_id(idx);
1223       if (code_page == 0)
1224          return c;
1225 
1226       wchar_t wide_c;
1227       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
1228          return c;
1229 
1230       wchar_t wide_result;
1231       int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1232          idx,       // locale identifier
1233          lcmap_uppercase,  // mapping transformation type
1234          &wide_c,  // source string
1235          1,        // number of characters in source string
1236          &wide_result,  // destination buffer
1237          1);        // size of destination buffer
1238       if (b == 0)
1239          return c;
1240 
1241       if (boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
1242          return c;  // No single byte upper case equivalent available.
1243 #endif
1244       return result[0];
1245    }
1246 
1247 #ifndef BOOST_NO_WREGEX
1248    inline wchar_t  w32_toupper(wchar_t c, lcid_type idx)
1249    {
1250       wchar_t result[2];
1251       int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(
1252          idx,       // locale identifier
1253          lcmap_uppercase,  // mapping transformation type
1254          &c,  // source string
1255          1,        // number of characters in source string
1256          result,  // destination buffer
1257          1);        // size of destination buffer
1258       if (b == 0)
1259          return c;
1260       return result[0];
1261    }
1262 #endif
1263    inline bool  w32_is(lcid_type idx, std::uint32_t m, char c)
1264    {
1265       word mask;
1266 #ifndef BOOST_NO_ANSI_APIS
1267       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(idx, ct_ctype1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
1268          return true;
1269 #else
1270       unsigned int code_page = get_code_page_for_locale_id(idx);
1271       if (code_page == 0)
1272          return false;
1273 
1274       wchar_t wide_c;
1275       if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
1276          return false;
1277 
1278       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
1279          return true;
1280 #endif
1281       if ((m & w32_regex_traits_implementation<char>::mask_word) && (c == '_'))
1282          return true;
1283       return false;
1284    }
1285 
1286 #ifndef BOOST_NO_WREGEX
1287    inline bool  w32_is(lcid_type idx, std::uint32_t m, wchar_t c)
1288    {
1289       word mask;
1290       if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<wchar_t>::mask_base))
1291          return true;
1292       if ((m & w32_regex_traits_implementation<wchar_t>::mask_word) && (c == '_'))
1293          return true;
1294       if ((m & w32_regex_traits_implementation<wchar_t>::mask_unicode) && (c > 0xff))
1295          return true;
1296       return false;
1297    }
1298 #endif
1299 
1300 } // BOOST_REGEX_DETAIL_NS
1301 
1302 
1303 } // boost
1304 
1305 #ifdef BOOST_REGEX_MSVC
1306 #pragma warning(pop)
1307 #endif
1308 
1309 #endif // BOOST_REGEX_NO_WIN32_LOCALE
1310 
1311 #endif