]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/regex/v4/w32_regex_traits.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / regex / v4 / w32_regex_traits.hpp
index 1f38bf36ec329a0244f6927e659ea74f0e583ddf..e1ac5d5f55eb91345313986e2737172cf99d17d3 100644 (file)
 #include <boost/regex/v4/primary_transform.hpp>
 #endif
 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
-#include <boost/regex/pending/object_cache.hpp>
+#include <boost/regex/v4/object_cache.hpp>
 #endif
 
+#define VC_EXTRALEAN
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE)
+#pragma comment(lib, "user32.lib")
+#endif
+
+
 #ifdef BOOST_MSVC
 #pragma warning(push)
 #pragma warning(disable: 4103)
@@ -75,53 +84,35 @@ typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE.
 //
 // then add wrappers around the actual Win32 API's (ie implementation hiding):
 //
-BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale();
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
+lcid_type BOOST_REGEX_CALL w32_get_default_locale();
+bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
-#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(unsigned short ca, lcid_type state_id);
-#endif
+bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
 #endif
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
+bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
-#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(unsigned short ca, lcid_type state_id);
-#endif
+bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
 #endif
-BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
-BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
+cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
+std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
-#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
-BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::basic_string<unsigned short>& def);
+std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
 #endif
-#endif
-BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
+std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
-#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
-BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transform(lcid_type state_id, const unsigned short* p1, const unsigned short* p2);
-#endif
+std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
 #endif
-BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
+char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
-#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
-BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_tolower(unsigned short c, lcid_type state_id);
-#endif
+wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
 #endif
-BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
+char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
+wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
 #endif
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
+bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
 #ifndef BOOST_NO_WREGEX
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
-#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
-BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type state_id, boost::uint32_t m, unsigned short c);
-#endif
+bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
 #endif
 //
 // class w32_regex_traits_base:
@@ -253,14 +244,14 @@ typename w32_regex_traits_char_layer<charT>::string_type
 // specialised version for narrow characters:
 //
 template <>
-class BOOST_REGEX_DECL w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
+class w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
 {
    typedef std::string string_type;
 public:
    w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l)
    : w32_regex_traits_base<char>(l)
    {
-      init();
+      init<char>();
    }
 
    regex_constants::syntax_type syntax_type(char c)const
@@ -284,6 +275,7 @@ private:
    regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
    char m_lower_map[1u << CHAR_BIT];
    boost::uint16_t m_type_map[1u << CHAR_BIT];
+   template <class U>
    void init();
 };
 
@@ -722,6 +714,498 @@ static_mutex& w32_regex_traits<charT>::get_mutex_inst()
 }
 #endif
 
+namespace BOOST_REGEX_DETAIL_NS {
+
+#ifdef BOOST_NO_ANSI_APIS
+   inline UINT get_code_page_for_locale_id(lcid_type idx)
+   {
+      WCHAR code_page_string[7];
+      if (::GetLocaleInfoW(idx, LOCALE_IDEFAULTANSICODEPAGE, code_page_string, 7) == 0)
+         return 0;
+
+      return static_cast<UINT>(_wtol(code_page_string));
+}
+#endif
+
+   template <class U>
+   inline void w32_regex_traits_char_layer<char>::init()
+   {
+      // we need to start by initialising our syntax map so we know which
+      // character is used for which purpose:
+      std::memset(m_char_map, 0, sizeof(m_char_map));
+      cat_type cat;
+      std::string cat_name(w32_regex_traits<char>::get_catalog_name());
+      if (cat_name.size())
+      {
+         cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name);
+         if (!cat)
+         {
+            std::string m("Unable to open message catalog: ");
+            std::runtime_error err(m + cat_name);
+            ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
+         }
+      }
+      //
+      // if we have a valid catalog then load our messages:
+      //
+      if (cat)
+      {
+         for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
+         {
+            string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i));
+            for (string_type::size_type j = 0; j < mss.size(); ++j)
+            {
+               m_char_map[static_cast<unsigned char>(mss[j])] = i;
+            }
+         }
+      }
+      else
+      {
+         for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
+         {
+            const char* ptr = get_default_syntax(i);
+            while (ptr && *ptr)
+            {
+               m_char_map[static_cast<unsigned char>(*ptr)] = i;
+               ++ptr;
+            }
+         }
+      }
+      //
+      // finish off by calculating our escape types:
+      //
+      unsigned char i = 'A';
+      do
+      {
+         if (m_char_map[i] == 0)
+         {
+            if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0002u, (char)i))
+               m_char_map[i] = regex_constants::escape_type_class;
+            else if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0001u, (char)i))
+               m_char_map[i] = regex_constants::escape_type_not_class;
+         }
+      } while (0xFF != i++);
+
+      //
+      // fill in lower case map:
+      //
+      char char_map[1 << CHAR_BIT];
+      for (int ii = 0; ii < (1 << CHAR_BIT); ++ii)
+         char_map[ii] = static_cast<char>(ii);
+#ifndef BOOST_NO_ANSI_APIS
+      int r = ::LCMapStringA(this->m_locale, LCMAP_LOWERCASE, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT);
+      BOOST_REGEX_ASSERT(r != 0);
+#else
+      UINT code_page = get_code_page_for_locale_id(this->m_locale);
+      BOOST_REGEX_ASSERT(code_page != 0);
+
+      WCHAR wide_char_map[1 << CHAR_BIT];
+      int conv_r = ::MultiByteToWideChar(code_page, 0, char_map, 1 << CHAR_BIT, wide_char_map, 1 << CHAR_BIT);
+      BOOST_REGEX_ASSERT(conv_r != 0);
+
+      WCHAR wide_lower_map[1 << CHAR_BIT];
+      int r = ::LCMapStringW(this->m_locale, LCMAP_LOWERCASE, wide_char_map, 1 << CHAR_BIT, wide_lower_map, 1 << CHAR_BIT);
+      BOOST_REGEX_ASSERT(r != 0);
+
+      conv_r = ::WideCharToMultiByte(code_page, 0, wide_lower_map, r, this->m_lower_map, 1 << CHAR_BIT, NULL, NULL);
+      BOOST_REGEX_ASSERT(conv_r != 0);
+#endif
+      if (r < (1 << CHAR_BIT))
+      {
+         // if we have multibyte characters then not all may have been given
+         // a lower case mapping:
+         for (int jj = r; jj < (1 << CHAR_BIT); ++jj)
+            this->m_lower_map[jj] = static_cast<char>(jj);
+      }
+
+#ifndef BOOST_NO_ANSI_APIS
+      r = ::GetStringTypeExA(this->m_locale, CT_CTYPE1, char_map, 1 << CHAR_BIT, this->m_type_map);
+#else
+      r = ::GetStringTypeExW(this->m_locale, CT_CTYPE1, wide_char_map, 1 << CHAR_BIT, this->m_type_map);
+#endif
+      BOOST_REGEX_ASSERT(0 != r);
+   }
+
+   inline lcid_type BOOST_REGEX_CALL w32_get_default_locale()
+   {
+      return ::GetUserDefaultLCID();
+   }
+
+   inline bool BOOST_REGEX_CALL w32_is_lower(char c, lcid_type idx)
+   {
+#ifndef BOOST_NO_ANSI_APIS
+      WORD mask;
+      if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
+         return true;
+      return false;
+#else
+      UINT code_page = get_code_page_for_locale_id(idx);
+      if (code_page == 0)
+         return false;
+
+      WCHAR wide_c;
+      if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
+         return false;
+
+      WORD mask;
+      if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_LOWER))
+         return true;
+      return false;
+#endif
+   }
+
+   inline bool BOOST_REGEX_CALL w32_is_lower(wchar_t c, lcid_type idx)
+   {
+      WORD mask;
+      if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER))
+         return true;
+      return false;
+   }
+
+   inline bool BOOST_REGEX_CALL w32_is_upper(char c, lcid_type idx)
+   {
+#ifndef BOOST_NO_ANSI_APIS
+      WORD mask;
+      if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
+         return true;
+      return false;
+#else
+      UINT code_page = get_code_page_for_locale_id(idx);
+      if (code_page == 0)
+         return false;
+
+      WCHAR wide_c;
+      if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
+         return false;
+
+      WORD mask;
+      if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_UPPER))
+         return true;
+      return false;
+#endif
+   }
+
+   inline bool BOOST_REGEX_CALL w32_is_upper(wchar_t c, lcid_type idx)
+   {
+      WORD mask;
+      if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER))
+         return true;
+      return false;
+   }
+
+   inline void free_module(void* mod)
+   {
+      ::FreeLibrary(static_cast<HMODULE>(mod));
+   }
+
+   inline cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name)
+   {
+#ifndef BOOST_NO_ANSI_APIS
+      cat_type result(::LoadLibraryA(name.c_str()), &free_module);
+      return result;
+#else
+      LPWSTR wide_name = (LPWSTR)_alloca((name.size() + 1) * sizeof(WCHAR));
+      if (::MultiByteToWideChar(CP_ACP, 0, name.c_str(), name.size(), wide_name, name.size() + 1) == 0)
+         return cat_type();
+
+      cat_type result(::LoadLibraryW(wide_name), &free_module);
+      return result;
+#endif
+   }
+
+   inline std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def)
+   {
+#ifndef BOOST_NO_ANSI_APIS
+      char buf[256];
+      if (0 == ::LoadStringA(
+         static_cast<HMODULE>(cat.get()),
+         i,
+         buf,
+         256
+      ))
+      {
+         return def;
+      }
+#else
+      WCHAR wbuf[256];
+      int r = ::LoadStringW(
+         static_cast<HMODULE>(cat.get()),
+         i,
+         wbuf,
+         256
+      );
+      if (r == 0)
+         return def;
+
+
+      int buf_size = 1 + ::WideCharToMultiByte(CP_ACP, 0, wbuf, r, NULL, 0, NULL, NULL);
+      LPSTR buf = (LPSTR)_alloca(buf_size);
+      if (::WideCharToMultiByte(CP_ACP, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0)
+         return def; // failed conversion.
+#endif
+      return std::string(buf);
+   }
+
+#ifndef BOOST_NO_WREGEX
+   inline std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def)
+   {
+      wchar_t buf[256];
+      if (0 == ::LoadStringW(
+         static_cast<HMODULE>(cat.get()),
+         i,
+         buf,
+         256
+      ))
+      {
+         return def;
+      }
+      return std::wstring(buf);
+   }
+#endif
+   inline std::string BOOST_REGEX_CALL w32_transform(lcid_type idx, const char* p1, const char* p2)
+   {
+#ifndef BOOST_NO_ANSI_APIS
+      int bytes = ::LCMapStringA(
+         idx,       // locale identifier
+         LCMAP_SORTKEY,  // mapping transformation type
+         p1,  // source string
+         static_cast<int>(p2 - p1),        // number of characters in source string
+         0,  // destination buffer
+         0        // size of destination buffer
+      );
+      if (!bytes)
+         return std::string(p1, p2);
+      std::string result(++bytes, '\0');
+      bytes = ::LCMapStringA(
+         idx,       // locale identifier
+         LCMAP_SORTKEY,  // mapping transformation type
+         p1,  // source string
+         static_cast<int>(p2 - p1),        // number of characters in source string
+         &*result.begin(),  // destination buffer
+         bytes        // size of destination buffer
+      );
+#else
+      UINT code_page = get_code_page_for_locale_id(idx);
+      if (code_page == 0)
+         return std::string(p1, p2);
+
+      int src_len = static_cast<int>(p2 - p1);
+      LPWSTR wide_p1 = (LPWSTR)_alloca((src_len + 1) * 2);
+      if (::MultiByteToWideChar(code_page, 0, p1, src_len, wide_p1, src_len + 1) == 0)
+         return std::string(p1, p2);
+
+      int bytes = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_SORTKEY,  // mapping transformation type
+         wide_p1,  // source string
+         src_len,        // number of characters in source string
+         0,  // destination buffer
+         0        // size of destination buffer
+      );
+      if (!bytes)
+         return std::string(p1, p2);
+      std::string result(++bytes, '\0');
+      bytes = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_SORTKEY,  // mapping transformation type
+         wide_p1,  // source string
+         src_len,        // number of characters in source string
+         (LPWSTR) & *result.begin(),  // destination buffer
+         bytes        // size of destination buffer
+      );
+#endif
+      if (bytes > static_cast<int>(result.size()))
+         return std::string(p1, p2);
+      while (result.size() && result[result.size() - 1] == '\0')
+      {
+         result.erase(result.size() - 1);
+      }
+      return result;
+   }
+
+#ifndef BOOST_NO_WREGEX
+   inline std::wstring BOOST_REGEX_CALL w32_transform(lcid_type idx, const wchar_t* p1, const wchar_t* p2)
+   {
+      int bytes = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_SORTKEY,  // mapping transformation type
+         p1,  // source string
+         static_cast<int>(p2 - p1),        // number of characters in source string
+         0,  // destination buffer
+         0        // size of destination buffer
+      );
+      if (!bytes)
+         return std::wstring(p1, p2);
+      std::string result(++bytes, '\0');
+      bytes = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_SORTKEY,  // mapping transformation type
+         p1,  // source string
+         static_cast<int>(p2 - p1),        // number of characters in source string
+         reinterpret_cast<wchar_t*>(&*result.begin()),  // destination buffer *of bytes*
+         bytes        // size of destination buffer
+      );
+      if (bytes > static_cast<int>(result.size()))
+         return std::wstring(p1, p2);
+      while (result.size() && result[result.size() - 1] == L'\0')
+      {
+         result.erase(result.size() - 1);
+      }
+      std::wstring r2;
+      for (std::string::size_type i = 0; i < result.size(); ++i)
+         r2.append(1, static_cast<wchar_t>(static_cast<unsigned char>(result[i])));
+      return r2;
+   }
+#endif
+   inline char BOOST_REGEX_CALL w32_tolower(char c, lcid_type idx)
+   {
+      char result[2];
+#ifndef BOOST_NO_ANSI_APIS
+      int b = ::LCMapStringA(
+         idx,       // locale identifier
+         LCMAP_LOWERCASE,  // mapping transformation type
+         &c,  // source string
+         1,        // number of characters in source string
+         result,  // destination buffer
+         1);        // size of destination buffer
+      if (b == 0)
+         return c;
+#else
+      UINT code_page = get_code_page_for_locale_id(idx);
+      if (code_page == 0)
+         return c;
+
+      WCHAR wide_c;
+      if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
+         return c;
+
+      WCHAR wide_result;
+      int b = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_LOWERCASE,  // mapping transformation type
+         &wide_c,  // source string
+         1,        // number of characters in source string
+         &wide_result,  // destination buffer
+         1);        // size of destination buffer
+      if (b == 0)
+         return c;
+
+      if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
+         return c;  // No single byte lower case equivalent available
+#endif
+      return result[0];
+   }
+
+#ifndef BOOST_NO_WREGEX
+   inline wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type idx)
+   {
+      wchar_t result[2];
+      int b = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_LOWERCASE,  // mapping transformation type
+         &c,  // source string
+         1,        // number of characters in source string
+         result,  // destination buffer
+         1);        // size of destination buffer
+      if (b == 0)
+         return c;
+      return result[0];
+   }
+#endif
+   inline char BOOST_REGEX_CALL w32_toupper(char c, lcid_type idx)
+   {
+      char result[2];
+#ifndef BOOST_NO_ANSI_APIS
+      int b = ::LCMapStringA(
+         idx,       // locale identifier
+         LCMAP_UPPERCASE,  // mapping transformation type
+         &c,  // source string
+         1,        // number of characters in source string
+         result,  // destination buffer
+         1);        // size of destination buffer
+      if (b == 0)
+         return c;
+#else
+      UINT code_page = get_code_page_for_locale_id(idx);
+      if (code_page == 0)
+         return c;
+
+      WCHAR wide_c;
+      if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
+         return c;
+
+      WCHAR wide_result;
+      int b = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_UPPERCASE,  // mapping transformation type
+         &wide_c,  // source string
+         1,        // number of characters in source string
+         &wide_result,  // destination buffer
+         1);        // size of destination buffer
+      if (b == 0)
+         return c;
+
+      if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0)
+         return c;  // No single byte upper case equivalent available.
+#endif
+      return result[0];
+   }
+
+#ifndef BOOST_NO_WREGEX
+   inline wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type idx)
+   {
+      wchar_t result[2];
+      int b = ::LCMapStringW(
+         idx,       // locale identifier
+         LCMAP_UPPERCASE,  // mapping transformation type
+         &c,  // source string
+         1,        // number of characters in source string
+         result,  // destination buffer
+         1);        // size of destination buffer
+      if (b == 0)
+         return c;
+      return result[0];
+   }
+#endif
+   inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, char c)
+   {
+      WORD mask;
+#ifndef BOOST_NO_ANSI_APIS
+      if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
+         return true;
+#else
+      UINT code_page = get_code_page_for_locale_id(idx);
+      if (code_page == 0)
+         return false;
+
+      WCHAR wide_c;
+      if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0)
+         return false;
+
+      if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation<char>::mask_base))
+         return true;
+#endif
+      if ((m & w32_regex_traits_implementation<char>::mask_word) && (c == '_'))
+         return true;
+      return false;
+   }
+
+#ifndef BOOST_NO_WREGEX
+   inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, wchar_t c)
+   {
+      WORD mask;
+      if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation<wchar_t>::mask_base))
+         return true;
+      if ((m & w32_regex_traits_implementation<wchar_t>::mask_word) && (c == '_'))
+         return true;
+      if ((m & w32_regex_traits_implementation<wchar_t>::mask_unicode) && (c > 0xff))
+         return true;
+      return false;
+   }
+#endif
+
+} // BOOST_REGEX_DETAIL_NS
+
 
 } // boost