Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*
0002  *
0003  * Copyright (c) 2004 John Maddock
0004  * Copyright 2011 Garmin Ltd. or its subsidiaries
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         cpp_regex_traits.hpp
0015   *   VERSION      see <boost/version.hpp>
0016   *   DESCRIPTION: Declares regular expression traits class cpp_regex_traits.
0017   */
0018 
0019 #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
0020 #define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
0021 
0022 #include <boost/config.hpp>
0023 #include <boost/integer.hpp>
0024 #include <boost/type_traits/make_unsigned.hpp>
0025 
0026 #ifndef BOOST_NO_STD_LOCALE
0027 
0028 #ifndef BOOST_RE_PAT_EXCEPT_HPP
0029 #include <boost/regex/pattern_except.hpp>
0030 #endif
0031 #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
0032 #include <boost/regex/v4/regex_traits_defaults.hpp>
0033 #endif
0034 #ifdef BOOST_HAS_THREADS
0035 #include <boost/regex/pending/static_mutex.hpp>
0036 #endif
0037 #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
0038 #include <boost/regex/v4/primary_transform.hpp>
0039 #endif
0040 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
0041 #include <boost/regex/v4/object_cache.hpp>
0042 #endif
0043 
0044 #include <climits>
0045 #include <ios>
0046 #include <istream>
0047 
0048 #ifdef BOOST_MSVC
0049 #pragma warning(push)
0050 #pragma warning(disable: 4103)
0051 #endif
0052 #ifdef BOOST_HAS_ABI_HEADERS
0053 #  include BOOST_ABI_PREFIX
0054 #endif
0055 #ifdef BOOST_MSVC
0056 #pragma warning(pop)
0057 #endif
0058 
0059 #ifdef BOOST_MSVC
0060 #pragma warning(push)
0061 #pragma warning(disable:4786 4251)
0062 #endif
0063 
0064 namespace boost{ 
0065 
0066 //
0067 // forward declaration is needed by some compilers:
0068 //
0069 template <class charT>
0070 class cpp_regex_traits;
0071    
0072 namespace BOOST_REGEX_DETAIL_NS{
0073 
0074 //
0075 // class parser_buf:
0076 // acts as a stream buffer which wraps around a pair of pointers:
0077 //
0078 template <class charT,
0079           class traits = ::std::char_traits<charT> >
0080 class parser_buf : public ::std::basic_streambuf<charT, traits>
0081 {
0082    typedef ::std::basic_streambuf<charT, traits> base_type;
0083    typedef typename base_type::int_type int_type;
0084    typedef typename base_type::char_type char_type;
0085    typedef typename base_type::pos_type pos_type;
0086    typedef ::std::streamsize streamsize;
0087    typedef typename base_type::off_type off_type;
0088 public:
0089    parser_buf() : base_type() { setbuf(0, 0); }
0090    const charT* getnext() { return this->gptr(); }
0091 protected:
0092    std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) BOOST_OVERRIDE;
0093    typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) BOOST_OVERRIDE;
0094    typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) BOOST_OVERRIDE;
0095 private:
0096    parser_buf& operator=(const parser_buf&);
0097    parser_buf(const parser_buf&);
0098 };
0099 
0100 template<class charT, class traits>
0101 std::basic_streambuf<charT, traits>*
0102 parser_buf<charT, traits>::setbuf(char_type* s, streamsize n)
0103 {
0104    this->setg(s, s, s + n);
0105    return this;
0106 }
0107 
0108 template<class charT, class traits>
0109 typename parser_buf<charT, traits>::pos_type
0110 parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which)
0111 {
0112    typedef typename boost::int_t<sizeof(way) * CHAR_BIT>::least cast_type;
0113 
0114    if(which & ::std::ios_base::out)
0115       return pos_type(off_type(-1));
0116    std::ptrdiff_t size = this->egptr() - this->eback();
0117    std::ptrdiff_t pos = this->gptr() - this->eback();
0118    charT* g = this->eback();
0119    switch(static_cast<cast_type>(way))
0120    {
0121    case ::std::ios_base::beg:
0122       if((off < 0) || (off > size))
0123          return pos_type(off_type(-1));
0124       else
0125          this->setg(g, g + off, g + size);
0126       break;
0127    case ::std::ios_base::end:
0128       if((off < 0) || (off > size))
0129          return pos_type(off_type(-1));
0130       else
0131          this->setg(g, g + size - off, g + size);
0132       break;
0133    case ::std::ios_base::cur:
0134    {
0135       std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
0136       if((newpos < 0) || (newpos > size))
0137          return pos_type(off_type(-1));
0138       else
0139          this->setg(g, g + newpos, g + size);
0140       break;
0141    }
0142    default: ;
0143    }
0144 #ifdef BOOST_MSVC
0145 #pragma warning(push)
0146 #pragma warning(disable:4244)
0147 #endif
0148    return static_cast<pos_type>(this->gptr() - this->eback());
0149 #ifdef BOOST_MSVC
0150 #pragma warning(pop)
0151 #endif
0152 }
0153 
0154 template<class charT, class traits>
0155 typename parser_buf<charT, traits>::pos_type
0156 parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which)
0157 {
0158    if(which & ::std::ios_base::out)
0159       return pos_type(off_type(-1));
0160    off_type size = static_cast<off_type>(this->egptr() - this->eback());
0161    charT* g = this->eback();
0162    if(off_type(sp) <= size)
0163    {
0164       this->setg(g, g + off_type(sp), g + size);
0165    }
0166    return pos_type(off_type(-1));
0167 }
0168 
0169 //
0170 // class cpp_regex_traits_base:
0171 // acts as a container for locale and the facets we are using.
0172 //
0173 template <class charT>
0174 struct cpp_regex_traits_base
0175 {
0176    cpp_regex_traits_base(const std::locale& l)
0177    { (void)imbue(l); }
0178    std::locale imbue(const std::locale& l);
0179 
0180    std::locale m_locale;
0181    std::ctype<charT> const* m_pctype;
0182 #ifndef BOOST_NO_STD_MESSAGES
0183    std::messages<charT> const* m_pmessages;
0184 #endif
0185    std::collate<charT> const* m_pcollate;
0186 
0187    bool operator<(const cpp_regex_traits_base& b)const
0188    {
0189       if(m_pctype == b.m_pctype)
0190       {
0191 #ifndef BOOST_NO_STD_MESSAGES
0192          if(m_pmessages == b.m_pmessages)
0193          {
0194             return m_pcollate < b.m_pcollate;
0195          }
0196          return m_pmessages < b.m_pmessages;
0197 #else
0198          return m_pcollate < b.m_pcollate;
0199 #endif
0200       }
0201       return m_pctype < b.m_pctype;
0202    }
0203    bool operator==(const cpp_regex_traits_base& b)const
0204    {
0205       return (m_pctype == b.m_pctype) 
0206 #ifndef BOOST_NO_STD_MESSAGES
0207          && (m_pmessages == b.m_pmessages) 
0208 #endif
0209          && (m_pcollate == b.m_pcollate);
0210    }
0211 };
0212 
0213 template <class charT>
0214 std::locale cpp_regex_traits_base<charT>::imbue(const std::locale& l)
0215 {
0216    std::locale result(m_locale);
0217    m_locale = l;
0218    m_pctype = &BOOST_USE_FACET(std::ctype<charT>, l);
0219 #ifndef BOOST_NO_STD_MESSAGES
0220    m_pmessages = BOOST_HAS_FACET(std::messages<charT>, l) ? &BOOST_USE_FACET(std::messages<charT>, l) : 0;
0221 #endif
0222    m_pcollate = &BOOST_USE_FACET(std::collate<charT>, l);
0223    return result;
0224 }
0225 
0226 //
0227 // class cpp_regex_traits_char_layer:
0228 // implements methods that require specialization for narrow characters:
0229 //
0230 template <class charT>
0231 class cpp_regex_traits_char_layer : public cpp_regex_traits_base<charT>
0232 {
0233    typedef std::basic_string<charT> string_type;
0234    typedef std::map<charT, regex_constants::syntax_type> map_type;
0235    typedef typename map_type::const_iterator map_iterator_type;
0236 public:
0237    cpp_regex_traits_char_layer(const std::locale& l)
0238       : cpp_regex_traits_base<charT>(l)
0239    {
0240       init();
0241    }
0242    cpp_regex_traits_char_layer(const cpp_regex_traits_base<charT>& b)
0243       : cpp_regex_traits_base<charT>(b)
0244    {
0245       init();
0246    }
0247    void init();
0248 
0249    regex_constants::syntax_type syntax_type(charT c)const
0250    {
0251       map_iterator_type i = m_char_map.find(c);
0252       return ((i == m_char_map.end()) ? 0 : i->second);
0253    }
0254    regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0255    {
0256       map_iterator_type i = m_char_map.find(c);
0257       if(i == m_char_map.end())
0258       {
0259          if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class;
0260          if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class;
0261          return 0;
0262       }
0263       return i->second;
0264    }
0265 
0266 private:
0267    string_type get_default_message(regex_constants::syntax_type);
0268    // TODO: use a hash table when available!
0269    map_type m_char_map;
0270 };
0271 
0272 template <class charT>
0273 void cpp_regex_traits_char_layer<charT>::init()
0274 {
0275    // we need to start by initialising our syntax map so we know which
0276    // character is used for which purpose:
0277 #ifndef BOOST_NO_STD_MESSAGES
0278 #ifndef __IBMCPP__
0279    typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
0280 #else
0281    typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
0282 #endif
0283    std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
0284    if((!cat_name.empty()) && (this->m_pmessages != 0))
0285    {
0286       cat = this->m_pmessages->open(
0287          cat_name, 
0288          this->m_locale);
0289       if((int)cat < 0)
0290       {
0291          std::string m("Unable to open message catalog: ");
0292          std::runtime_error err(m + cat_name);
0293          boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0294       }
0295    }
0296    //
0297    // if we have a valid catalog then load our messages:
0298    //
0299    if((int)cat >= 0)
0300    {
0301 #ifndef BOOST_NO_EXCEPTIONS
0302       try{
0303 #endif
0304          for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0305          {
0306             string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i));
0307             for(typename string_type::size_type j = 0; j < mss.size(); ++j)
0308             {
0309                m_char_map[mss[j]] = i;
0310             }
0311          }
0312          this->m_pmessages->close(cat);
0313 #ifndef BOOST_NO_EXCEPTIONS
0314       }
0315       catch(...)
0316       {
0317          if(this->m_pmessages)
0318             this->m_pmessages->close(cat);
0319          throw;
0320       }
0321 #endif
0322    }
0323    else
0324    {
0325 #endif
0326       for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
0327       {
0328          const char* ptr = get_default_syntax(i);
0329          while(ptr && *ptr)
0330          {
0331             m_char_map[this->m_pctype->widen(*ptr)] = i;
0332             ++ptr;
0333          }
0334       }
0335 #ifndef BOOST_NO_STD_MESSAGES
0336    }
0337 #endif
0338 }
0339 
0340 template <class charT>
0341 typename cpp_regex_traits_char_layer<charT>::string_type 
0342    cpp_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
0343 {
0344    const char* ptr = get_default_syntax(i);
0345    string_type result;
0346    while(ptr && *ptr)
0347    {
0348       result.append(1, this->m_pctype->widen(*ptr));
0349       ++ptr;
0350    }
0351    return result;
0352 }
0353 
0354 //
0355 // specialized version for narrow characters:
0356 //
0357 template <>
0358 class cpp_regex_traits_char_layer<char> : public cpp_regex_traits_base<char>
0359 {
0360    typedef std::string string_type;
0361 public:
0362    cpp_regex_traits_char_layer(const std::locale& l)
0363    : cpp_regex_traits_base<char>(l)
0364    {
0365       init();
0366    }
0367    cpp_regex_traits_char_layer(const cpp_regex_traits_base<char>& l)
0368    : cpp_regex_traits_base<char>(l)
0369    {
0370       init();
0371    }
0372 
0373    regex_constants::syntax_type syntax_type(char c)const
0374    {
0375       return m_char_map[static_cast<unsigned char>(c)];
0376    }
0377    regex_constants::escape_syntax_type escape_syntax_type(char c) const
0378    {
0379       return m_char_map[static_cast<unsigned char>(c)];
0380    }
0381 
0382 private:
0383    regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
0384    void init();
0385 };
0386 
0387 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
0388 enum
0389 {
0390    char_class_space=1<<0, 
0391    char_class_print=1<<1, 
0392    char_class_cntrl=1<<2, 
0393    char_class_upper=1<<3, 
0394    char_class_lower=1<<4,
0395    char_class_alpha=1<<5, 
0396    char_class_digit=1<<6, 
0397    char_class_punct=1<<7, 
0398    char_class_xdigit=1<<8,
0399    char_class_alnum=char_class_alpha|char_class_digit, 
0400    char_class_graph=char_class_alnum|char_class_punct,
0401    char_class_blank=1<<9,
0402    char_class_word=1<<10,
0403    char_class_unicode=1<<11,
0404    char_class_horizontal_space=1<<12,
0405    char_class_vertical_space=1<<13
0406 };
0407 
0408 #endif
0409 
0410 //
0411 // class cpp_regex_traits_implementation:
0412 // provides pimpl implementation for cpp_regex_traits.
0413 //
0414 template <class charT>
0415 class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT>
0416 {
0417 public:
0418    typedef typename cpp_regex_traits<charT>::char_class_type      char_class_type;
0419    typedef typename std::ctype<charT>::mask                       native_mask_type;
0420    typedef typename boost::make_unsigned<native_mask_type>::type  unsigned_native_mask_type;
0421 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0422    BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 24);
0423    BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 25);
0424    BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 26);
0425    BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 1u << 27);
0426    BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 1u << 28);
0427 #endif
0428 
0429    typedef std::basic_string<charT> string_type;
0430    typedef charT char_type;
0431    //cpp_regex_traits_implementation();
0432    cpp_regex_traits_implementation(const std::locale& l)
0433       : cpp_regex_traits_char_layer<charT>(l)
0434    {
0435       init();
0436    }
0437    cpp_regex_traits_implementation(const cpp_regex_traits_base<charT>& l)
0438       : cpp_regex_traits_char_layer<charT>(l)
0439    {
0440       init();
0441    }
0442    std::string error_string(regex_constants::error_type n) const
0443    {
0444       if(!m_error_strings.empty())
0445       {
0446          std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
0447          return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
0448       }
0449       return get_default_error_string(n);
0450    }
0451    char_class_type lookup_classname(const charT* p1, const charT* p2) const
0452    {
0453       char_class_type result = lookup_classname_imp(p1, p2);
0454       if(result == 0)
0455       {
0456          string_type temp(p1, p2);
0457          this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size());
0458          result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
0459       }
0460       return result;
0461    }
0462    string_type lookup_collatename(const charT* p1, const charT* p2) const;
0463    string_type transform_primary(const charT* p1, const charT* p2) const;
0464    string_type transform(const charT* p1, const charT* p2) const;
0465 private:
0466    std::map<int, std::string>     m_error_strings;   // error messages indexed by numberic ID
0467    std::map<string_type, char_class_type>  m_custom_class_names; // character class names
0468    std::map<string_type, string_type>      m_custom_collate_names; // collating element names
0469    unsigned                       m_collate_type;    // the form of the collation string
0470    charT                          m_collate_delim;   // the collation group delimiter
0471    //
0472    // helpers:
0473    //
0474    char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
0475    void init();
0476 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
0477 public:
0478    bool isctype(charT c, char_class_type m)const;
0479 #endif
0480 };
0481 
0482 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0483 #if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
0484 
0485 template <class charT>
0486 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_blank;
0487 template <class charT>
0488 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_word;
0489 template <class charT>
0490 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_unicode;
0491 template <class charT>
0492 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_vertical;
0493 template <class charT>
0494 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_horizontal;
0495 
0496 #endif
0497 #endif
0498 
0499 template <class charT>
0500 typename cpp_regex_traits_implementation<charT>::string_type 
0501    cpp_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
0502 {
0503    //
0504    // PRECONDITIONS:
0505    //
0506    // A bug in gcc 3.2 (and maybe other versions as well) treats
0507    // p1 as a null terminated string, for efficiency reasons 
0508    // we work around this elsewhere, but just assert here that
0509    // we adhere to gcc's (buggy) preconditions...
0510    //
0511    BOOST_REGEX_ASSERT(*p2 == 0);
0512    string_type result;
0513 #if defined(_CPPLIB_VER)
0514    //
0515    // A bug in VC11 and 12 causes the program to hang if we pass a null-string
0516    // to std::collate::transform, but only for certain locales :-(
0517    // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
0518    //
0519    if(*p1 == 0)
0520    {
0521       return string_type(1, charT(0));
0522    }
0523 #endif
0524    //
0525    // swallowing all exceptions here is a bad idea
0526    // however at least one std lib will always throw
0527    // std::bad_alloc for certain arguments...
0528    //
0529 #ifndef BOOST_NO_EXCEPTIONS
0530    try{
0531 #endif
0532       //
0533       // What we do here depends upon the format of the sort key returned by
0534       // sort key returned by this->transform:
0535       //
0536       switch(m_collate_type)
0537       {
0538       case sort_C:
0539       case sort_unknown:
0540          // the best we can do is translate to lower case, then get a regular sort key:
0541          {
0542             result.assign(p1, p2);
0543             this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size());
0544             result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size());
0545             break;
0546          }
0547       case sort_fixed:
0548          {
0549             // get a regular sort key, and then truncate it:
0550             result.assign(this->m_pcollate->transform(p1, p2));
0551             result.erase(this->m_collate_delim);
0552             break;
0553          }
0554       case sort_delim:
0555             // get a regular sort key, and then truncate everything after the delim:
0556             result.assign(this->m_pcollate->transform(p1, p2));
0557             std::size_t i;
0558             for(i = 0; i < result.size(); ++i)
0559             {
0560                if(result[i] == m_collate_delim)
0561                   break;
0562             }
0563             result.erase(i);
0564             break;
0565       }
0566 #ifndef BOOST_NO_EXCEPTIONS
0567    }catch(...){}
0568 #endif
0569    while((!result.empty()) && (charT(0) == *result.rbegin()))
0570       result.erase(result.size() - 1);
0571    if(result.empty())
0572    {
0573       // character is ignorable at the primary level:
0574       result = string_type(1, charT(0));
0575    }
0576    return result;
0577 }
0578 
0579 template <class charT>
0580 typename cpp_regex_traits_implementation<charT>::string_type 
0581    cpp_regex_traits_implementation<charT>::transform(const charT* p1, const charT* p2) const
0582 {
0583    //
0584    // PRECONDITIONS:
0585    //
0586    // A bug in gcc 3.2 (and maybe other versions as well) treats
0587    // p1 as a null terminated string, for efficiency reasons 
0588    // we work around this elsewhere, but just assert here that
0589    // we adhere to gcc's (buggy) preconditions...
0590    //
0591    BOOST_REGEX_ASSERT(*p2 == 0);
0592    //
0593    // swallowing all exceptions here is a bad idea
0594    // however at least one std lib will always throw
0595    // std::bad_alloc for certain arguments...
0596    //
0597    string_type result, result2;
0598 #if defined(_CPPLIB_VER)
0599    //
0600    // A bug in VC11 and 12 causes the program to hang if we pass a null-string
0601    // to std::collate::transform, but only for certain locales :-(
0602    // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware).
0603    //
0604    if(*p1 == 0)
0605    {
0606       return result;
0607    }
0608 #endif
0609 #ifndef BOOST_NO_EXCEPTIONS
0610    try{
0611 #endif
0612       result = this->m_pcollate->transform(p1, p2);
0613       //
0614       // Borland's STLPort version returns a NULL-terminated
0615       // string that has garbage at the end - each call to
0616       // std::collate<wchar_t>::transform returns a different string!
0617       // So as a workaround, we'll truncate the string at the first NULL
0618       // which _seems_ to work....
0619 #if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x580)
0620       result.erase(result.find(charT(0)));
0621 #else
0622       //
0623       // some implementations (Dinkumware) append unnecessary trailing \0's:
0624       while((!result.empty()) && (charT(0) == *result.rbegin()))
0625          result.erase(result.size() - 1);
0626 #endif
0627       //
0628       // We may have NULL's used as separators between sections of the collate string,
0629       // an example would be Boost.Locale.  We have no way to detect this case via
0630       // #defines since this can be used with any compiler/platform combination.
0631       // Unfortunately our state machine (which was devised when all implementations
0632       // used underlying C language API's) can't cope with that case.  One workaround
0633       // is to replace each character with 2, fortunately this code isn't used that
0634       // much as this is now slower than before :-(
0635       //
0636       typedef typename make_unsigned<charT>::type uchar_type;
0637       result2.reserve(result.size() * 2 + 2);
0638       for(unsigned i = 0; i < result.size(); ++i)
0639       {
0640          if(static_cast<uchar_type>(result[i]) == (std::numeric_limits<uchar_type>::max)())
0641          {
0642             result2.append(1, charT((std::numeric_limits<uchar_type>::max)())).append(1, charT('b'));
0643          }
0644          else
0645          {
0646             result2.append(1, static_cast<charT>(1 + static_cast<uchar_type>(result[i]))).append(1, charT('b') - 1);
0647          }
0648       }
0649       BOOST_REGEX_ASSERT(std::find(result2.begin(), result2.end(), charT(0)) == result2.end());
0650 #ifndef BOOST_NO_EXCEPTIONS
0651    }
0652    catch(...)
0653    {
0654    }
0655 #endif
0656    return result2;
0657 }
0658 
0659 
0660 template <class charT>
0661 typename cpp_regex_traits_implementation<charT>::string_type 
0662    cpp_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
0663 {
0664    typedef typename std::map<string_type, string_type>::const_iterator iter_type;
0665    if(!m_custom_collate_names.empty())
0666    {
0667       iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
0668       if(pos != m_custom_collate_names.end())
0669          return pos->second;
0670    }
0671 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
0672                && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
0673    std::string name(p1, p2);
0674 #else
0675    std::string name;
0676    const charT* p0 = p1;
0677    while(p0 != p2)
0678       name.append(1, char(*p0++));
0679 #endif
0680    name = lookup_default_collate_name(name);
0681 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
0682                && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)
0683    if(!name.empty())
0684       return string_type(name.begin(), name.end());
0685 #else
0686    if(!name.empty())
0687    {
0688       string_type result;
0689       typedef std::string::const_iterator iter;
0690       iter b = name.begin();
0691       iter e = name.end();
0692       while(b != e)
0693          result.append(1, charT(*b++));
0694       return result;
0695    }
0696 #endif
0697    if(p2 - p1 == 1)
0698       return string_type(1, *p1);
0699    return string_type();
0700 }
0701 
0702 template <class charT>
0703 void cpp_regex_traits_implementation<charT>::init()
0704 {
0705 #ifndef BOOST_NO_STD_MESSAGES
0706 #ifndef __IBMCPP__
0707    typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
0708 #else
0709    typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
0710 #endif
0711    std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
0712    if((!cat_name.empty()) && (this->m_pmessages != 0))
0713    {
0714       cat = this->m_pmessages->open(
0715          cat_name, 
0716          this->m_locale);
0717       if((int)cat < 0)
0718       {
0719          std::string m("Unable to open message catalog: ");
0720          std::runtime_error err(m + cat_name);
0721          boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
0722       }
0723    }
0724    //
0725    // if we have a valid catalog then load our messages:
0726    //
0727    if((int)cat >= 0)
0728    {
0729       //
0730       // Error messages:
0731       //
0732       for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0); 
0733          i <= boost::regex_constants::error_unknown; 
0734          i = static_cast<boost::regex_constants::error_type>(i + 1))
0735       {
0736          const char* p = get_default_error_string(i);
0737          string_type default_message;
0738          while(*p)
0739          {
0740             default_message.append(1, this->m_pctype->widen(*p));
0741             ++p;
0742          }
0743          string_type s = this->m_pmessages->get(cat, 0, i+200, default_message);
0744          std::string result;
0745          for(std::string::size_type j = 0; j < s.size(); ++j)
0746          {
0747             result.append(1, this->m_pctype->narrow(s[j], 0));
0748          }
0749          m_error_strings[i] = result;
0750       }
0751       //
0752       // Custom class names:
0753       //
0754 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0755       static const char_class_type masks[16] = 
0756       {
0757          static_cast<unsigned_native_mask_type>(std::ctype<charT>::alnum),
0758          static_cast<unsigned_native_mask_type>(std::ctype<charT>::alpha),
0759          static_cast<unsigned_native_mask_type>(std::ctype<charT>::cntrl),
0760          static_cast<unsigned_native_mask_type>(std::ctype<charT>::digit),
0761          static_cast<unsigned_native_mask_type>(std::ctype<charT>::graph),
0762          cpp_regex_traits_implementation<charT>::mask_horizontal,
0763          static_cast<unsigned_native_mask_type>(std::ctype<charT>::lower),
0764          static_cast<unsigned_native_mask_type>(std::ctype<charT>::print),
0765          static_cast<unsigned_native_mask_type>(std::ctype<charT>::punct),
0766          static_cast<unsigned_native_mask_type>(std::ctype<charT>::space),
0767          static_cast<unsigned_native_mask_type>(std::ctype<charT>::upper),
0768          cpp_regex_traits_implementation<charT>::mask_vertical,
0769          static_cast<unsigned_native_mask_type>(std::ctype<charT>::xdigit),
0770          cpp_regex_traits_implementation<charT>::mask_blank,
0771          cpp_regex_traits_implementation<charT>::mask_word,
0772          cpp_regex_traits_implementation<charT>::mask_unicode,
0773       };
0774 #else
0775       static const char_class_type masks[16] = 
0776       {
0777          ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum,
0778          ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha,
0779          ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl,
0780          ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
0781          ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph,
0782          ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space,
0783          ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
0784          ::boost::BOOST_REGEX_DETAIL_NS::char_class_print,
0785          ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct,
0786          ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
0787          ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
0788          ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space,
0789          ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit,
0790          ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank,
0791          ::boost::BOOST_REGEX_DETAIL_NS::char_class_word,
0792          ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode,
0793       };
0794 #endif
0795       static const string_type null_string;
0796       for(unsigned int j = 0; j <= 13; ++j)
0797       {
0798          string_type s(this->m_pmessages->get(cat, 0, j+300, null_string));
0799          if(!s.empty())
0800             this->m_custom_class_names[s] = masks[j];
0801       }
0802    }
0803 #endif
0804    //
0805    // get the collation format used by m_pcollate:
0806    //
0807    m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim);
0808 }
0809 
0810 template <class charT>
0811 typename cpp_regex_traits_implementation<charT>::char_class_type 
0812    cpp_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
0813 {
0814 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0815    static const char_class_type masks[22] = 
0816    {
0817       0,
0818       static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum),
0819       static_cast<unsigned_native_mask_type>(std::ctype<char>::alpha),
0820       cpp_regex_traits_implementation<charT>::mask_blank,
0821       static_cast<unsigned_native_mask_type>(std::ctype<char>::cntrl),
0822       static_cast<unsigned_native_mask_type>(std::ctype<char>::digit),
0823       static_cast<unsigned_native_mask_type>(std::ctype<char>::digit),
0824       static_cast<unsigned_native_mask_type>(std::ctype<char>::graph),
0825       cpp_regex_traits_implementation<charT>::mask_horizontal,
0826       static_cast<unsigned_native_mask_type>(std::ctype<char>::lower),
0827       static_cast<unsigned_native_mask_type>(std::ctype<char>::lower),
0828       static_cast<unsigned_native_mask_type>(std::ctype<char>::print),
0829       static_cast<unsigned_native_mask_type>(std::ctype<char>::punct),
0830       static_cast<unsigned_native_mask_type>(std::ctype<char>::space),
0831       static_cast<unsigned_native_mask_type>(std::ctype<char>::space),
0832       static_cast<unsigned_native_mask_type>(std::ctype<char>::upper),
0833       cpp_regex_traits_implementation<charT>::mask_unicode,
0834       static_cast<unsigned_native_mask_type>(std::ctype<char>::upper),
0835       cpp_regex_traits_implementation<charT>::mask_vertical,
0836       static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum) | cpp_regex_traits_implementation<charT>::mask_word, 
0837       static_cast<unsigned_native_mask_type>(std::ctype<char>::alnum) | cpp_regex_traits_implementation<charT>::mask_word, 
0838       static_cast<unsigned_native_mask_type>(std::ctype<char>::xdigit),
0839    };
0840 #else
0841    static const char_class_type masks[22] = 
0842    {
0843       0,
0844       ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum, 
0845       ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha,
0846       ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank,
0847       ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl,
0848       ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
0849       ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit,
0850       ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph,
0851       ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space,
0852       ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
0853       ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower,
0854       ::boost::BOOST_REGEX_DETAIL_NS::char_class_print,
0855       ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct,
0856       ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
0857       ::boost::BOOST_REGEX_DETAIL_NS::char_class_space,
0858       ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
0859       ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode,
0860       ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper,
0861       ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space,
0862       ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word, 
0863       ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word, 
0864       ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit,
0865    };
0866 #endif
0867    if(!m_custom_class_names.empty())
0868    {
0869       typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
0870       map_iter pos = m_custom_class_names.find(string_type(p1, p2));
0871       if(pos != m_custom_class_names.end())
0872          return pos->second;
0873    }
0874    std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2);
0875    BOOST_REGEX_ASSERT(state_id < sizeof(masks) / sizeof(masks[0]));
0876    return masks[state_id];
0877 }
0878 
0879 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
0880 template <class charT>
0881 bool cpp_regex_traits_implementation<charT>::isctype(const charT c, char_class_type mask) const
0882 {
0883    return
0884       ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_space) && (this->m_pctype->is(std::ctype<charT>::space, c)))
0885       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_print) && (this->m_pctype->is(std::ctype<charT>::print, c)))
0886       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl) && (this->m_pctype->is(std::ctype<charT>::cntrl, c)))
0887       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper) && (this->m_pctype->is(std::ctype<charT>::upper, c)))
0888       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower) && (this->m_pctype->is(std::ctype<charT>::lower, c)))
0889       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha) && (this->m_pctype->is(std::ctype<charT>::alpha, c)))
0890       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit) && (this->m_pctype->is(std::ctype<charT>::digit, c)))
0891       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct) && (this->m_pctype->is(std::ctype<charT>::punct, c)))
0892       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit) && (this->m_pctype->is(std::ctype<charT>::xdigit, c)))
0893       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank) && (this->m_pctype->is(std::ctype<charT>::space, c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c))
0894       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_word) && (c == '_'))
0895       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode) && ::boost::BOOST_REGEX_DETAIL_NS::is_extended(c))
0896       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space) && (is_separator(c) || (c == '\v')))
0897       || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space) && this->m_pctype->is(std::ctype<charT>::space, c) && !(is_separator(c) || (c == '\v')));
0898 }
0899 #endif
0900 
0901 
0902 template <class charT>
0903 inline boost::shared_ptr<const cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l)
0904 {
0905    cpp_regex_traits_base<charT> key(l);
0906    return ::boost::object_cache<cpp_regex_traits_base<charT>, cpp_regex_traits_implementation<charT> >::get(key, 5);
0907 }
0908 
0909 } // BOOST_REGEX_DETAIL_NS
0910 
0911 template <class charT>
0912 class cpp_regex_traits
0913 {
0914 private:
0915    typedef std::ctype<charT>            ctype_type;
0916 public:
0917    typedef charT                        char_type;
0918    typedef std::size_t                  size_type;
0919    typedef std::basic_string<char_type> string_type;
0920    typedef std::locale                  locale_type;
0921    typedef boost::uint_least32_t        char_class_type;
0922 
0923    struct boost_extensions_tag{};
0924 
0925    cpp_regex_traits()
0926       : m_pimpl(BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits<charT>(std::locale()))
0927    { }
0928    static size_type length(const char_type* p)
0929    {
0930       return std::char_traits<charT>::length(p);
0931    }
0932    regex_constants::syntax_type syntax_type(charT c)const
0933    {
0934       return m_pimpl->syntax_type(c);
0935    }
0936    regex_constants::escape_syntax_type escape_syntax_type(charT c) const
0937    {
0938       return m_pimpl->escape_syntax_type(c);
0939    }
0940    charT translate(charT c) const
0941    {
0942       return c;
0943    }
0944    charT translate_nocase(charT c) const
0945    {
0946       return m_pimpl->m_pctype->tolower(c);
0947    }
0948    charT translate(charT c, bool icase) const
0949    {
0950       return icase ? m_pimpl->m_pctype->tolower(c) : c;
0951    }
0952    charT tolower(charT c) const
0953    {
0954       return m_pimpl->m_pctype->tolower(c);
0955    }
0956    charT toupper(charT c) const
0957    {
0958       return m_pimpl->m_pctype->toupper(c);
0959    }
0960    string_type transform(const charT* p1, const charT* p2) const
0961    {
0962       return m_pimpl->transform(p1, p2);
0963    }
0964    string_type transform_primary(const charT* p1, const charT* p2) const
0965    {
0966       return m_pimpl->transform_primary(p1, p2);
0967    }
0968    char_class_type lookup_classname(const charT* p1, const charT* p2) const
0969    {
0970       return m_pimpl->lookup_classname(p1, p2);
0971    }
0972    string_type lookup_collatename(const charT* p1, const charT* p2) const
0973    {
0974       return m_pimpl->lookup_collatename(p1, p2);
0975    }
0976    bool isctype(charT c, char_class_type f) const
0977    {
0978 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
0979       typedef typename std::ctype<charT>::mask ctype_mask;
0980 
0981       static const ctype_mask mask_base = 
0982          static_cast<ctype_mask>(
0983             std::ctype<charT>::alnum 
0984             | std::ctype<charT>::alpha
0985             | std::ctype<charT>::cntrl
0986             | std::ctype<charT>::digit
0987             | std::ctype<charT>::graph
0988             | std::ctype<charT>::lower
0989             | std::ctype<charT>::print
0990             | std::ctype<charT>::punct
0991             | std::ctype<charT>::space
0992             | std::ctype<charT>::upper
0993             | std::ctype<charT>::xdigit);
0994 
0995       if((f & mask_base) 
0996          && (m_pimpl->m_pctype->is(
0997             static_cast<ctype_mask>(f & mask_base), c)))
0998          return true;
0999       else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c))
1000          return true;
1001       else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_word) && (c == '_'))
1002          return true;
1003       else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_blank) 
1004          && m_pimpl->m_pctype->is(std::ctype<charT>::space, c)
1005          && !BOOST_REGEX_DETAIL_NS::is_separator(c))
1006          return true;
1007       else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_vertical) 
1008          && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v')))
1009          return true;
1010       else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_horizontal) 
1011          && this->isctype(c, std::ctype<charT>::space) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT>::mask_vertical))
1012          return true;
1013 #ifdef __CYGWIN__
1014       //
1015       // Cygwin has a buggy ctype facet, see https://www.cygwin.com/ml/cygwin/2012-08/msg00178.html:
1016       //
1017       else if((f & std::ctype<charT>::xdigit) == std::ctype<charT>::xdigit)
1018       {
1019          if((c >= 'a') && (c <= 'f'))
1020             return true;
1021          if((c >= 'A') && (c <= 'F'))
1022             return true;
1023       }
1024 #endif
1025       return false;
1026 #else
1027       return m_pimpl->isctype(c, f);
1028 #endif
1029    }
1030    boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const;
1031    int value(charT c, int radix)const
1032    {
1033       const charT* pc = &c;
1034       return (int)toi(pc, pc + 1, radix);
1035    }
1036    locale_type imbue(locale_type l)
1037    {
1038       std::locale result(getloc());
1039       m_pimpl = BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits<charT>(l);
1040       return result;
1041    }
1042    locale_type getloc()const
1043    {
1044       return m_pimpl->m_locale;
1045    }
1046    std::string error_string(regex_constants::error_type n) const
1047    {
1048       return m_pimpl->error_string(n);
1049    }
1050 
1051    //
1052    // extension:
1053    // set the name of the message catalog in use (defaults to "boost_regex").
1054    //
1055    static std::string catalog_name(const std::string& name);
1056    static std::string get_catalog_name();
1057 
1058 private:
1059    boost::shared_ptr<const BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation<charT> > m_pimpl;
1060    //
1061    // catalog name handler:
1062    //
1063    static std::string& get_catalog_name_inst();
1064 
1065 #ifdef BOOST_HAS_THREADS
1066    static static_mutex& get_mutex_inst();
1067 #endif
1068 };
1069 
1070 
1071 template <class charT>
1072 boost::intmax_t cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const
1073 {
1074    BOOST_REGEX_DETAIL_NS::parser_buf<charT>   sbuf;            // buffer for parsing numbers.
1075    std::basic_istream<charT>      is(&sbuf);       // stream for parsing numbers.
1076 
1077    // we do NOT want to parse any thousands separators inside the stream:
1078    last = std::find(first, last, BOOST_USE_FACET(std::numpunct<charT>, is.getloc()).thousands_sep());
1079 
1080    sbuf.pubsetbuf(const_cast<charT*>(static_cast<const charT*>(first)), static_cast<std::streamsize>(last-first));
1081    is.clear();
1082    if(std::abs(radix) == 16) is >> std::hex;
1083    else if(std::abs(radix) == 8) is >> std::oct;
1084    else is >> std::dec;
1085    boost::intmax_t val;
1086    if(is >> val)
1087    {
1088       first = first + ((last - first) - sbuf.in_avail());
1089       return val;
1090    }
1091    else
1092       return -1;
1093 }
1094 
1095 template <class charT>
1096 std::string cpp_regex_traits<charT>::catalog_name(const std::string& name)
1097 {
1098 #ifdef BOOST_HAS_THREADS
1099    static_mutex::scoped_lock lk(get_mutex_inst());
1100 #endif
1101    std::string result(get_catalog_name_inst());
1102    get_catalog_name_inst() = name;
1103    return result;
1104 }
1105 
1106 template <class charT>
1107 std::string& cpp_regex_traits<charT>::get_catalog_name_inst()
1108 {
1109    static std::string s_name;
1110    return s_name;
1111 }
1112 
1113 template <class charT>
1114 std::string cpp_regex_traits<charT>::get_catalog_name()
1115 {
1116 #ifdef BOOST_HAS_THREADS
1117    static_mutex::scoped_lock lk(get_mutex_inst());
1118 #endif
1119    std::string result(get_catalog_name_inst());
1120    return result;
1121 }
1122 
1123 #ifdef BOOST_HAS_THREADS
1124 template <class charT>
1125 static_mutex& cpp_regex_traits<charT>::get_mutex_inst()
1126 {
1127    static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
1128    return s_mutex;
1129 }
1130 #endif
1131 
1132 namespace BOOST_REGEX_DETAIL_NS {
1133 
1134    inline void cpp_regex_traits_char_layer<char>::init()
1135    {
1136       // we need to start by initialising our syntax map so we know which
1137       // character is used for which purpose:
1138       std::memset(m_char_map, 0, sizeof(m_char_map));
1139 #ifndef BOOST_NO_STD_MESSAGES
1140 #ifndef __IBMCPP__
1141       std::messages<char>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
1142 #else
1143       std::messages<char>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
1144 #endif
1145       std::string cat_name(cpp_regex_traits<char>::get_catalog_name());
1146       if ((!cat_name.empty()) && (m_pmessages != 0))
1147       {
1148          cat = this->m_pmessages->open(
1149             cat_name,
1150             this->m_locale);
1151          if ((int)cat < 0)
1152          {
1153             std::string m("Unable to open message catalog: ");
1154             std::runtime_error err(m + cat_name);
1155             boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err);
1156          }
1157       }
1158       //
1159       // if we have a valid catalog then load our messages:
1160       //
1161       if ((int)cat >= 0)
1162       {
1163 #ifndef BOOST_NO_EXCEPTIONS
1164          try {
1165 #endif
1166             for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
1167             {
1168                string_type mss = this->m_pmessages->get(cat, 0, i, get_default_syntax(i));
1169                for (string_type::size_type j = 0; j < mss.size(); ++j)
1170                {
1171                   m_char_map[static_cast<unsigned char>(mss[j])] = i;
1172                }
1173             }
1174             this->m_pmessages->close(cat);
1175 #ifndef BOOST_NO_EXCEPTIONS
1176          }
1177          catch (...)
1178          {
1179             this->m_pmessages->close(cat);
1180             throw;
1181          }
1182 #endif
1183       }
1184       else
1185       {
1186 #endif
1187          for (regex_constants::syntax_type j = 1; j < regex_constants::syntax_max; ++j)
1188          {
1189             const char* ptr = get_default_syntax(j);
1190             while (ptr && *ptr)
1191             {
1192                m_char_map[static_cast<unsigned char>(*ptr)] = j;
1193                ++ptr;
1194             }
1195          }
1196 #ifndef BOOST_NO_STD_MESSAGES
1197       }
1198 #endif
1199       //
1200       // finish off by calculating our escape types:
1201       //
1202       unsigned char i = 'A';
1203       do
1204       {
1205          if (m_char_map[i] == 0)
1206          {
1207             if (this->m_pctype->is(std::ctype_base::lower, i))
1208                m_char_map[i] = regex_constants::escape_type_class;
1209             else if (this->m_pctype->is(std::ctype_base::upper, i))
1210                m_char_map[i] = regex_constants::escape_type_not_class;
1211          }
1212       } while (0xFF != i++);
1213    }
1214 
1215 } // namespace detail
1216 
1217 
1218 } // boost
1219 
1220 #ifdef BOOST_MSVC
1221 #pragma warning(pop)
1222 #endif
1223 
1224 #ifdef BOOST_MSVC
1225 #pragma warning(push)
1226 #pragma warning(disable: 4103)
1227 #endif
1228 #ifdef BOOST_HAS_ABI_HEADERS
1229 #  include BOOST_ABI_SUFFIX
1230 #endif
1231 #ifdef BOOST_MSVC
1232 #pragma warning(pop)
1233 #endif
1234 
1235 #endif
1236 
1237 #endif