imgtools/imglib/boostlibrary/boost/regex/v4/cpp_regex_traits.hpp
changeset 600 6d08f4a05d93
equal deleted inserted replaced
599:fa7a3cc6effd 600:6d08f4a05d93
       
     1 /*
       
     2  *
       
     3  * Copyright (c) 2004
       
     4  * John Maddock
       
     5  *
       
     6  * Use, modification and distribution are subject to the 
       
     7  * Boost Software License, Version 1.0. (See accompanying file 
       
     8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       
     9  *
       
    10  */
       
    11  
       
    12  /*
       
    13   *   LOCATION:    see http://www.boost.org for most recent version.
       
    14   *   FILE         cpp_regex_traits.hpp
       
    15   *   VERSION      see <boost/version.hpp>
       
    16   *   DESCRIPTION: Declares regular expression traits class cpp_regex_traits.
       
    17   */
       
    18 
       
    19 #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
       
    20 #define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
       
    21 
       
    22 #include <boost/config.hpp>
       
    23 
       
    24 #ifndef BOOST_NO_STD_LOCALE
       
    25 
       
    26 #ifndef BOOST_RE_PAT_EXCEPT_HPP
       
    27 #include <boost/regex/pattern_except.hpp>
       
    28 #endif
       
    29 #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
       
    30 #include <boost/regex/v4/regex_traits_defaults.hpp>
       
    31 #endif
       
    32 #ifdef BOOST_HAS_THREADS
       
    33 #include <boost/regex/pending/static_mutex.hpp>
       
    34 #endif
       
    35 #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
       
    36 #include <boost/regex/v4/primary_transform.hpp>
       
    37 #endif
       
    38 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
       
    39 #include <boost/regex/pending/object_cache.hpp>
       
    40 #endif
       
    41 
       
    42 #include <istream>
       
    43 #include <ios>
       
    44 #include <climits>
       
    45 
       
    46 #ifdef BOOST_MSVC
       
    47 #pragma warning(push)
       
    48 #pragma warning(disable: 4103)
       
    49 #endif
       
    50 #ifdef BOOST_HAS_ABI_HEADERS
       
    51 #  include BOOST_ABI_PREFIX
       
    52 #endif
       
    53 #ifdef BOOST_MSVC
       
    54 #pragma warning(pop)
       
    55 #endif
       
    56 
       
    57 #ifdef BOOST_MSVC
       
    58 #pragma warning(push)
       
    59 #pragma warning(disable:4786)
       
    60 #endif
       
    61 
       
    62 namespace boost{ 
       
    63 
       
    64 //
       
    65 // forward declaration is needed by some compilers:
       
    66 //
       
    67 template <class charT>
       
    68 class cpp_regex_traits;
       
    69    
       
    70 namespace re_detail{
       
    71 
       
    72 //
       
    73 // class parser_buf:
       
    74 // acts as a stream buffer which wraps around a pair of pointers:
       
    75 //
       
    76 template <class charT,
       
    77           class traits = ::std::char_traits<charT> >
       
    78 class parser_buf : public ::std::basic_streambuf<charT, traits>
       
    79 {
       
    80    typedef ::std::basic_streambuf<charT, traits> base_type;
       
    81    typedef typename base_type::int_type int_type;
       
    82    typedef typename base_type::char_type char_type;
       
    83    typedef typename base_type::pos_type pos_type;
       
    84    typedef ::std::streamsize streamsize;
       
    85    typedef typename base_type::off_type off_type;
       
    86 public:
       
    87    parser_buf() : base_type() { setbuf(0, 0); }
       
    88    const charT* getnext() { return this->gptr(); }
       
    89 protected:
       
    90    std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n);
       
    91    typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which);
       
    92    typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which);
       
    93 private:
       
    94    parser_buf& operator=(const parser_buf&);
       
    95    parser_buf(const parser_buf&);
       
    96 };
       
    97 
       
    98 template<class charT, class traits>
       
    99 std::basic_streambuf<charT, traits>*
       
   100 parser_buf<charT, traits>::setbuf(char_type* s, streamsize n)
       
   101 {
       
   102    this->setg(s, s, s + n);
       
   103    return this;
       
   104 }
       
   105 
       
   106 template<class charT, class traits>
       
   107 typename parser_buf<charT, traits>::pos_type
       
   108 parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which)
       
   109 {
       
   110    if(which & ::std::ios_base::out)
       
   111       return pos_type(off_type(-1));
       
   112    std::ptrdiff_t size = this->egptr() - this->eback();
       
   113    std::ptrdiff_t pos = this->gptr() - this->eback();
       
   114    charT* g = this->eback();
       
   115    switch(way)
       
   116    {
       
   117    case ::std::ios_base::beg:
       
   118       if((off < 0) || (off > size))
       
   119          return pos_type(off_type(-1));
       
   120       else
       
   121          this->setg(g, g + off, g + size);
       
   122       break;
       
   123    case ::std::ios_base::end:
       
   124       if((off < 0) || (off > size))
       
   125          return pos_type(off_type(-1));
       
   126       else
       
   127          this->setg(g, g + size - off, g + size);
       
   128       break;
       
   129    case ::std::ios_base::cur:
       
   130    {
       
   131       std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
       
   132       if((newpos < 0) || (newpos > size))
       
   133          return pos_type(off_type(-1));
       
   134       else
       
   135          this->setg(g, g + newpos, g + size);
       
   136       break;
       
   137    }
       
   138    default: ;
       
   139    }
       
   140 #ifdef BOOST_MSVC
       
   141 #pragma warning(push)
       
   142 #pragma warning(disable:4244)
       
   143 #endif
       
   144    return static_cast<pos_type>(this->gptr() - this->eback());
       
   145 #ifdef BOOST_MSVC
       
   146 #pragma warning(pop)
       
   147 #endif
       
   148 }
       
   149 
       
   150 template<class charT, class traits>
       
   151 typename parser_buf<charT, traits>::pos_type
       
   152 parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which)
       
   153 {
       
   154    if(which & ::std::ios_base::out)
       
   155       return pos_type(off_type(-1));
       
   156    off_type size = static_cast<off_type>(this->egptr() - this->eback());
       
   157    charT* g = this->eback();
       
   158    if(off_type(sp) <= size)
       
   159    {
       
   160       this->setg(g, g + off_type(sp), g + size);
       
   161    }
       
   162    return pos_type(off_type(-1));
       
   163 }
       
   164 
       
   165 //
       
   166 // class cpp_regex_traits_base:
       
   167 // acts as a container for locale and the facets we are using.
       
   168 //
       
   169 template <class charT>
       
   170 struct cpp_regex_traits_base
       
   171 {
       
   172    cpp_regex_traits_base(const std::locale& l)
       
   173    { imbue(l); }
       
   174    std::locale imbue(const std::locale& l);
       
   175 
       
   176    std::locale m_locale;
       
   177    std::ctype<charT> const* m_pctype;
       
   178 #ifndef BOOST_NO_STD_MESSAGES
       
   179    std::messages<charT> const* m_pmessages;
       
   180 #endif
       
   181    std::collate<charT> const* m_pcollate;
       
   182 
       
   183    bool operator<(const cpp_regex_traits_base& b)const
       
   184    {
       
   185       if(m_pctype == b.m_pctype)
       
   186       {
       
   187 #ifndef BOOST_NO_STD_MESSAGES
       
   188          if(m_pmessages == b.m_pmessages)
       
   189          {
       
   190          }
       
   191          return m_pmessages < b.m_pmessages;
       
   192 #else
       
   193          return m_pcollate < b.m_pcollate;
       
   194 #endif
       
   195       }
       
   196       return m_pctype < b.m_pctype;
       
   197    }
       
   198    bool operator==(const cpp_regex_traits_base& b)const
       
   199    {
       
   200       return (m_pctype == b.m_pctype) 
       
   201 #ifndef BOOST_NO_STD_MESSAGES
       
   202          && (m_pmessages == b.m_pmessages) 
       
   203 #endif
       
   204          && (m_pcollate == b.m_pcollate);
       
   205    }
       
   206 };
       
   207 
       
   208 template <class charT>
       
   209 std::locale cpp_regex_traits_base<charT>::imbue(const std::locale& l)
       
   210 {
       
   211    std::locale result(m_locale);
       
   212    m_locale = l;
       
   213    m_pctype = &BOOST_USE_FACET(std::ctype<charT>, l);
       
   214 #ifndef BOOST_NO_STD_MESSAGES
       
   215    m_pmessages = &BOOST_USE_FACET(std::messages<charT>, l);
       
   216 #endif
       
   217    m_pcollate = &BOOST_USE_FACET(std::collate<charT>, l);
       
   218    return result;
       
   219 }
       
   220 
       
   221 //
       
   222 // class cpp_regex_traits_char_layer:
       
   223 // implements methods that require specialisation for narrow characters:
       
   224 //
       
   225 template <class charT>
       
   226 class cpp_regex_traits_char_layer : public cpp_regex_traits_base<charT>
       
   227 {
       
   228    typedef std::basic_string<charT> string_type;
       
   229    typedef std::map<charT, regex_constants::syntax_type> map_type;
       
   230    typedef typename map_type::const_iterator map_iterator_type;
       
   231 public:
       
   232    cpp_regex_traits_char_layer(const std::locale& l)
       
   233       : cpp_regex_traits_base<charT>(l)
       
   234    {
       
   235       init();
       
   236    }
       
   237    cpp_regex_traits_char_layer(const cpp_regex_traits_base<charT>& b)
       
   238       : cpp_regex_traits_base<charT>(b)
       
   239    {
       
   240       init();
       
   241    }
       
   242    void init();
       
   243 
       
   244    regex_constants::syntax_type syntax_type(charT c)const
       
   245    {
       
   246       map_iterator_type i = m_char_map.find(c);
       
   247       return ((i == m_char_map.end()) ? 0 : i->second);
       
   248    }
       
   249    regex_constants::escape_syntax_type escape_syntax_type(charT c) const
       
   250    {
       
   251       map_iterator_type i = m_char_map.find(c);
       
   252       if(i == m_char_map.end())
       
   253       {
       
   254          if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class;
       
   255          if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class;
       
   256          return 0;
       
   257       }
       
   258       return i->second;
       
   259    }
       
   260 
       
   261 private:
       
   262    string_type get_default_message(regex_constants::syntax_type);
       
   263    // TODO: use a hash table when available!
       
   264    map_type m_char_map;
       
   265 };
       
   266 
       
   267 template <class charT>
       
   268 void cpp_regex_traits_char_layer<charT>::init()
       
   269 {
       
   270    // we need to start by initialising our syntax map so we know which
       
   271    // character is used for which purpose:
       
   272 #ifndef BOOST_NO_STD_MESSAGES
       
   273 #ifndef __IBMCPP__
       
   274    typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
       
   275 #else
       
   276    typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
       
   277 #endif
       
   278    std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
       
   279    if(cat_name.size())
       
   280    {
       
   281       cat = this->m_pmessages->open(
       
   282          cat_name, 
       
   283          this->m_locale);
       
   284       if((int)cat < 0)
       
   285       {
       
   286          std::string m("Unable to open message catalog: ");
       
   287          std::runtime_error err(m + cat_name);
       
   288          boost::re_detail::raise_runtime_error(err);
       
   289       }
       
   290    }
       
   291    //
       
   292    // if we have a valid catalog then load our messages:
       
   293    //
       
   294    if((int)cat >= 0)
       
   295    {
       
   296 #ifndef BOOST_NO_EXCEPTIONS
       
   297       try{
       
   298 #endif
       
   299          for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
       
   300          {
       
   301             string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i));
       
   302             for(typename string_type::size_type j = 0; j < mss.size(); ++j)
       
   303             {
       
   304                m_char_map[mss[j]] = i;
       
   305             }
       
   306          }
       
   307          this->m_pmessages->close(cat);
       
   308 #ifndef BOOST_NO_EXCEPTIONS
       
   309       }
       
   310       catch(...)
       
   311       {
       
   312          this->m_pmessages->close(cat);
       
   313          throw;
       
   314       }
       
   315 #endif
       
   316    }
       
   317    else
       
   318    {
       
   319 #endif
       
   320       for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
       
   321       {
       
   322          const char* ptr = get_default_syntax(i);
       
   323          while(ptr && *ptr)
       
   324          {
       
   325             m_char_map[this->m_pctype->widen(*ptr)] = i;
       
   326             ++ptr;
       
   327          }
       
   328       }
       
   329 #ifndef BOOST_NO_STD_MESSAGES
       
   330    }
       
   331 #endif
       
   332 }
       
   333 
       
   334 template <class charT>
       
   335 typename cpp_regex_traits_char_layer<charT>::string_type 
       
   336    cpp_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
       
   337 {
       
   338    const char* ptr = get_default_syntax(i);
       
   339    string_type result;
       
   340    while(ptr && *ptr)
       
   341    {
       
   342       result.append(1, this->m_pctype->widen(*ptr));
       
   343       ++ptr;
       
   344    }
       
   345    return result;
       
   346 }
       
   347 
       
   348 //
       
   349 // specialised version for narrow characters:
       
   350 //
       
   351 template <>
       
   352 class BOOST_REGEX_DECL cpp_regex_traits_char_layer<char> : public cpp_regex_traits_base<char>
       
   353 {
       
   354    typedef std::string string_type;
       
   355 public:
       
   356    cpp_regex_traits_char_layer(const std::locale& l)
       
   357    : cpp_regex_traits_base<char>(l)
       
   358    {
       
   359       init();
       
   360    }
       
   361    cpp_regex_traits_char_layer(const cpp_regex_traits_base<char>& l)
       
   362    : cpp_regex_traits_base<char>(l)
       
   363    {
       
   364       init();
       
   365    }
       
   366 
       
   367    regex_constants::syntax_type syntax_type(char c)const
       
   368    {
       
   369       return m_char_map[static_cast<unsigned char>(c)];
       
   370    }
       
   371    regex_constants::escape_syntax_type escape_syntax_type(char c) const
       
   372    {
       
   373       return m_char_map[static_cast<unsigned char>(c)];
       
   374    }
       
   375 
       
   376 private:
       
   377    regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
       
   378    void init();
       
   379 };
       
   380 
       
   381 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   382 enum
       
   383 {
       
   384    char_class_space=1<<0, 
       
   385    char_class_print=1<<1, 
       
   386    char_class_cntrl=1<<2, 
       
   387    char_class_upper=1<<3, 
       
   388    char_class_lower=1<<4,
       
   389    char_class_alpha=1<<5, 
       
   390    char_class_digit=1<<6, 
       
   391    char_class_punct=1<<7, 
       
   392    char_class_xdigit=1<<8,
       
   393    char_class_alnum=char_class_alpha|char_class_digit, 
       
   394    char_class_graph=char_class_alnum|char_class_punct,
       
   395    char_class_blank=1<<9,
       
   396    char_class_word=1<<10,
       
   397    char_class_unicode=1<<11
       
   398 };
       
   399 
       
   400 #endif
       
   401 
       
   402 //
       
   403 // class cpp_regex_traits_implementation:
       
   404 // provides pimpl implementation for cpp_regex_traits.
       
   405 //
       
   406 template <class charT>
       
   407 class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT>
       
   408 {
       
   409 public:
       
   410    typedef typename cpp_regex_traits<charT>::char_class_type char_class_type;
       
   411    typedef typename std::ctype<charT>::mask                  native_mask_type;
       
   412 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   413    BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 24);
       
   414    BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 25);
       
   415    BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 26);
       
   416 #endif
       
   417 
       
   418    typedef std::basic_string<charT> string_type;
       
   419    typedef charT char_type;
       
   420    //cpp_regex_traits_implementation();
       
   421    cpp_regex_traits_implementation(const std::locale& l)
       
   422       : cpp_regex_traits_char_layer<charT>(l)
       
   423    {
       
   424       init();
       
   425    }
       
   426    cpp_regex_traits_implementation(const cpp_regex_traits_base<charT>& l)
       
   427       : cpp_regex_traits_char_layer<charT>(l)
       
   428    {
       
   429       init();
       
   430    }
       
   431    std::string error_string(regex_constants::error_type n) const
       
   432    {
       
   433       if(!m_error_strings.empty())
       
   434       {
       
   435          std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
       
   436          return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
       
   437       }
       
   438       return get_default_error_string(n);
       
   439    }
       
   440    char_class_type lookup_classname(const charT* p1, const charT* p2) const
       
   441    {
       
   442       char_class_type result = lookup_classname_imp(p1, p2);
       
   443       if(result == 0)
       
   444       {
       
   445          string_type temp(p1, p2);
       
   446          this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size());
       
   447          result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
       
   448       }
       
   449       return result;
       
   450    }
       
   451    string_type lookup_collatename(const charT* p1, const charT* p2) const;
       
   452    string_type transform_primary(const charT* p1, const charT* p2) const;
       
   453    string_type transform(const charT* p1, const charT* p2) const;
       
   454 private:
       
   455    std::map<int, std::string>     m_error_strings;   // error messages indexed by numberic ID
       
   456    std::map<string_type, char_class_type>  m_custom_class_names; // character class names
       
   457    std::map<string_type, string_type>      m_custom_collate_names; // collating element names
       
   458    unsigned                       m_collate_type;    // the form of the collation string
       
   459    charT                          m_collate_delim;   // the collation group delimiter
       
   460    //
       
   461    // helpers:
       
   462    //
       
   463    char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
       
   464    void init();
       
   465 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   466 public:
       
   467    bool isctype(charT c, char_class_type m)const;
       
   468 #endif
       
   469 };
       
   470 
       
   471 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   472 #if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
       
   473 
       
   474 template <class charT>
       
   475 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_blank;
       
   476 template <class charT>
       
   477 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_word;
       
   478 template <class charT>
       
   479 typename cpp_regex_traits_implementation<charT>::char_class_type const cpp_regex_traits_implementation<charT>::mask_unicode;
       
   480 
       
   481 #endif
       
   482 #endif
       
   483 
       
   484 template <class charT>
       
   485 typename cpp_regex_traits_implementation<charT>::string_type 
       
   486    cpp_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
       
   487 {
       
   488    //
       
   489    // PRECONDITIONS:
       
   490    //
       
   491    // A bug in gcc 3.2 (and maybe other versions as well) treats
       
   492    // p1 as a null terminated string, for efficiency reasons 
       
   493    // we work around this elsewhere, but just assert here that
       
   494    // we adhere to gcc's (buggy) preconditions...
       
   495    //
       
   496    BOOST_ASSERT(*p2 == 0);
       
   497 
       
   498    string_type result;
       
   499    //
       
   500    // swallowing all exceptions here is a bad idea
       
   501    // however at least one std lib will always throw
       
   502    // std::bad_alloc for certain arguments...
       
   503    //
       
   504    try{
       
   505       //
       
   506       // What we do here depends upon the format of the sort key returned by
       
   507       // sort key returned by this->transform:
       
   508       //
       
   509       switch(m_collate_type)
       
   510       {
       
   511       case sort_C:
       
   512       case sort_unknown:
       
   513          // the best we can do is translate to lower case, then get a regular sort key:
       
   514          {
       
   515             result.assign(p1, p2);
       
   516             this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size());
       
   517             result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size());
       
   518             break;
       
   519          }
       
   520       case sort_fixed:
       
   521          {
       
   522             // get a regular sort key, and then truncate it:
       
   523             result.assign(this->m_pcollate->transform(p1, p2));
       
   524             result.erase(this->m_collate_delim);
       
   525             break;
       
   526          }
       
   527       case sort_delim:
       
   528             // get a regular sort key, and then truncate everything after the delim:
       
   529             result.assign(this->m_pcollate->transform(p1, p2));
       
   530             std::size_t i;
       
   531             for(i = 0; i < result.size(); ++i)
       
   532             {
       
   533                if(result[i] == m_collate_delim)
       
   534                   break;
       
   535             }
       
   536             result.erase(i);
       
   537             break;
       
   538       }
       
   539    }catch(...){}
       
   540    while(result.size() && (charT(0) == *result.rbegin()))
       
   541       result.erase(result.size() - 1);
       
   542    if(result.empty())
       
   543    {
       
   544       // character is ignorable at the primary level:
       
   545       result = string_type(1, charT(0));
       
   546    }
       
   547    return result;
       
   548 }
       
   549 
       
   550 template <class charT>
       
   551 typename cpp_regex_traits_implementation<charT>::string_type 
       
   552    cpp_regex_traits_implementation<charT>::transform(const charT* p1, const charT* p2) const
       
   553 {
       
   554    //
       
   555    // PRECONDITIONS:
       
   556    //
       
   557    // A bug in gcc 3.2 (and maybe other versions as well) treats
       
   558    // p1 as a null terminated string, for efficiency reasons 
       
   559    // we work around this elsewhere, but just assert here that
       
   560    // we adhere to gcc's (buggy) preconditions...
       
   561    //
       
   562    BOOST_ASSERT(*p2 == 0);
       
   563    //
       
   564    // swallowing all exceptions here is a bad idea
       
   565    // however at least one std lib will always throw
       
   566    // std::bad_alloc for certain arguments...
       
   567    //
       
   568    string_type result;
       
   569    try{
       
   570       result = this->m_pcollate->transform(p1, p2);
       
   571       //
       
   572       // Borland's STLPort version returns a NULL-terminated
       
   573       // string that has garbage at the end - each call to
       
   574       // std::collate<wchar_t>::transform returns a different string!
       
   575       // So as a workaround, we'll truncate the string at the first NULL
       
   576       // which _seems_ to work....
       
   577 #if BOOST_WORKAROUND(__BORLANDC__, < 0x580)
       
   578       result.erase(result.find(charT(0)));
       
   579 #else
       
   580       //
       
   581       // some implementations (Dinkumware) append unnecessary trailing \0's:
       
   582       while(result.size() && (charT(0) == *result.rbegin()))
       
   583          result.erase(result.size() - 1);
       
   584 #endif
       
   585       BOOST_ASSERT(std::find(result.begin(), result.end(), charT(0)) == result.end());
       
   586    }
       
   587    catch(...)
       
   588    {
       
   589    }
       
   590    return result;
       
   591 }
       
   592 
       
   593 
       
   594 template <class charT>
       
   595 typename cpp_regex_traits_implementation<charT>::string_type 
       
   596    cpp_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
       
   597 {
       
   598    typedef typename std::map<string_type, string_type>::const_iterator iter_type;
       
   599    if(m_custom_collate_names.size())
       
   600    {
       
   601       iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
       
   602       if(pos != m_custom_collate_names.end())
       
   603          return pos->second;
       
   604    }
       
   605 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
       
   606                && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
       
   607                && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
       
   608    std::string name(p1, p2);
       
   609 #else
       
   610    std::string name;
       
   611    const charT* p0 = p1;
       
   612    while(p0 != p2)
       
   613       name.append(1, char(*p0++));
       
   614 #endif
       
   615    name = lookup_default_collate_name(name);
       
   616 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
       
   617                && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
       
   618                && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
       
   619    if(name.size())
       
   620       return string_type(name.begin(), name.end());
       
   621 #else
       
   622    if(name.size())
       
   623    {
       
   624       string_type result;
       
   625       typedef std::string::const_iterator iter;
       
   626       iter b = name.begin();
       
   627       iter e = name.end();
       
   628       while(b != e)
       
   629          result.append(1, charT(*b++));
       
   630       return result;
       
   631    }
       
   632 #endif
       
   633    if(p2 - p1 == 1)
       
   634       return string_type(1, *p1);
       
   635    return string_type();
       
   636 }
       
   637 
       
   638 template <class charT>
       
   639 void cpp_regex_traits_implementation<charT>::init()
       
   640 {
       
   641 #ifndef BOOST_NO_STD_MESSAGES
       
   642 #ifndef __IBMCPP__
       
   643    typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
       
   644 #else
       
   645    typename std::messages<charT>::catalog cat = reinterpret_cast<std::messages<char>::catalog>(-1);
       
   646 #endif
       
   647    std::string cat_name(cpp_regex_traits<charT>::get_catalog_name());
       
   648    if(cat_name.size())
       
   649    {
       
   650       cat = this->m_pmessages->open(
       
   651          cat_name, 
       
   652          this->m_locale);
       
   653       if((int)cat < 0)
       
   654       {
       
   655          std::string m("Unable to open message catalog: ");
       
   656          std::runtime_error err(m + cat_name);
       
   657          boost::re_detail::raise_runtime_error(err);
       
   658       }
       
   659    }
       
   660    //
       
   661    // if we have a valid catalog then load our messages:
       
   662    //
       
   663    if((int)cat >= 0)
       
   664    {
       
   665       //
       
   666       // Error messages:
       
   667       //
       
   668       for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0); 
       
   669          i <= boost::regex_constants::error_unknown; 
       
   670          i = static_cast<boost::regex_constants::error_type>(i + 1))
       
   671       {
       
   672          const char* p = get_default_error_string(i);
       
   673          string_type default_message;
       
   674          while(*p)
       
   675          {
       
   676             default_message.append(1, this->m_pctype->widen(*p));
       
   677             ++p;
       
   678          }
       
   679          string_type s = this->m_pmessages->get(cat, 0, i+200, default_message);
       
   680          std::string result;
       
   681          for(std::string::size_type j = 0; j < s.size(); ++j)
       
   682          {
       
   683             result.append(1, this->m_pctype->narrow(s[j], 0));
       
   684          }
       
   685          m_error_strings[i] = result;
       
   686       }
       
   687       //
       
   688       // Custom class names:
       
   689       //
       
   690 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   691       static const char_class_type masks[14] = 
       
   692       {
       
   693          std::ctype<charT>::alnum,
       
   694          std::ctype<charT>::alpha,
       
   695          std::ctype<charT>::cntrl,
       
   696          std::ctype<charT>::digit,
       
   697          std::ctype<charT>::graph,
       
   698          std::ctype<charT>::lower,
       
   699          std::ctype<charT>::print,
       
   700          std::ctype<charT>::punct,
       
   701          std::ctype<charT>::space,
       
   702          std::ctype<charT>::upper,
       
   703          std::ctype<charT>::xdigit,
       
   704          cpp_regex_traits_implementation<charT>::mask_blank,
       
   705          cpp_regex_traits_implementation<charT>::mask_word,
       
   706          cpp_regex_traits_implementation<charT>::mask_unicode,
       
   707       };
       
   708 #else
       
   709       static const char_class_type masks[14] = 
       
   710       {
       
   711          ::boost::re_detail::char_class_alnum,
       
   712          ::boost::re_detail::char_class_alpha,
       
   713          ::boost::re_detail::char_class_cntrl,
       
   714          ::boost::re_detail::char_class_digit,
       
   715          ::boost::re_detail::char_class_graph,
       
   716          ::boost::re_detail::char_class_lower,
       
   717          ::boost::re_detail::char_class_print,
       
   718          ::boost::re_detail::char_class_punct,
       
   719          ::boost::re_detail::char_class_space,
       
   720          ::boost::re_detail::char_class_upper,
       
   721          ::boost::re_detail::char_class_xdigit,
       
   722          ::boost::re_detail::char_class_blank,
       
   723          ::boost::re_detail::char_class_word,
       
   724          ::boost::re_detail::char_class_unicode,
       
   725       };
       
   726 #endif
       
   727       static const string_type null_string;
       
   728       for(unsigned int j = 0; j <= 13; ++j)
       
   729       {
       
   730          string_type s(this->m_pmessages->get(cat, 0, j+300, null_string));
       
   731          if(s.size())
       
   732             this->m_custom_class_names[s] = masks[j];
       
   733       }
       
   734    }
       
   735 #endif
       
   736    //
       
   737    // get the collation format used by m_pcollate:
       
   738    //
       
   739    m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim);
       
   740 }
       
   741 
       
   742 template <class charT>
       
   743 typename cpp_regex_traits_implementation<charT>::char_class_type 
       
   744    cpp_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
       
   745 {
       
   746 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   747    static const char_class_type masks[20] = 
       
   748    {
       
   749       0,
       
   750       std::ctype<char>::alnum, 
       
   751       std::ctype<char>::alpha,
       
   752       cpp_regex_traits_implementation<charT>::mask_blank,
       
   753       std::ctype<char>::cntrl,
       
   754       std::ctype<char>::digit,
       
   755       std::ctype<char>::digit,
       
   756       std::ctype<char>::graph,
       
   757       std::ctype<char>::lower,
       
   758       std::ctype<char>::lower,
       
   759       std::ctype<char>::print,
       
   760       std::ctype<char>::punct,
       
   761       std::ctype<char>::space,
       
   762       std::ctype<char>::space,
       
   763       std::ctype<char>::upper,
       
   764       cpp_regex_traits_implementation<charT>::mask_unicode,
       
   765       std::ctype<char>::upper,
       
   766       std::ctype<char>::alnum | cpp_regex_traits_implementation<charT>::mask_word, 
       
   767       std::ctype<char>::alnum | cpp_regex_traits_implementation<charT>::mask_word, 
       
   768       std::ctype<char>::xdigit,
       
   769    };
       
   770 #else
       
   771    static const char_class_type masks[20] = 
       
   772    {
       
   773       0,
       
   774       ::boost::re_detail::char_class_alnum, 
       
   775       ::boost::re_detail::char_class_alpha,
       
   776       ::boost::re_detail::char_class_blank,
       
   777       ::boost::re_detail::char_class_cntrl,
       
   778       ::boost::re_detail::char_class_digit,
       
   779       ::boost::re_detail::char_class_digit,
       
   780       ::boost::re_detail::char_class_graph,
       
   781       ::boost::re_detail::char_class_lower,
       
   782       ::boost::re_detail::char_class_lower,
       
   783       ::boost::re_detail::char_class_print,
       
   784       ::boost::re_detail::char_class_punct,
       
   785       ::boost::re_detail::char_class_space,
       
   786       ::boost::re_detail::char_class_space,
       
   787       ::boost::re_detail::char_class_upper,
       
   788       ::boost::re_detail::char_class_unicode,
       
   789       ::boost::re_detail::char_class_upper,
       
   790       ::boost::re_detail::char_class_alnum | ::boost::re_detail::char_class_word, 
       
   791       ::boost::re_detail::char_class_alnum | ::boost::re_detail::char_class_word, 
       
   792       ::boost::re_detail::char_class_xdigit,
       
   793    };
       
   794 #endif
       
   795    if(m_custom_class_names.size())
       
   796    {
       
   797       typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
       
   798       map_iter pos = m_custom_class_names.find(string_type(p1, p2));
       
   799       if(pos != m_custom_class_names.end())
       
   800          return pos->second;
       
   801    }
       
   802    std::size_t state_id = 1 + re_detail::get_default_class_id(p1, p2);
       
   803    BOOST_ASSERT(state_id < sizeof(masks) / sizeof(masks[0]));
       
   804    return masks[state_id];
       
   805 }
       
   806 
       
   807 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   808 template <class charT>
       
   809 bool cpp_regex_traits_implementation<charT>::isctype(const charT c, char_class_type mask) const
       
   810 {
       
   811    return
       
   812       ((mask & ::boost::re_detail::char_class_space) && (m_pctype->is(std::ctype<charT>::space, c)))
       
   813       || ((mask & ::boost::re_detail::char_class_print) && (m_pctype->is(std::ctype<charT>::print, c)))
       
   814       || ((mask & ::boost::re_detail::char_class_cntrl) && (m_pctype->is(std::ctype<charT>::cntrl, c)))
       
   815       || ((mask & ::boost::re_detail::char_class_upper) && (m_pctype->is(std::ctype<charT>::upper, c)))
       
   816       || ((mask & ::boost::re_detail::char_class_lower) && (m_pctype->is(std::ctype<charT>::lower, c)))
       
   817       || ((mask & ::boost::re_detail::char_class_alpha) && (m_pctype->is(std::ctype<charT>::alpha, c)))
       
   818       || ((mask & ::boost::re_detail::char_class_digit) && (m_pctype->is(std::ctype<charT>::digit, c)))
       
   819       || ((mask & ::boost::re_detail::char_class_punct) && (m_pctype->is(std::ctype<charT>::punct, c)))
       
   820       || ((mask & ::boost::re_detail::char_class_xdigit) && (m_pctype->is(std::ctype<charT>::xdigit, c)))
       
   821       || ((mask & ::boost::re_detail::char_class_blank) && (m_pctype->is(std::ctype<charT>::space, c)) && !::boost::re_detail::is_separator(c))
       
   822       || ((mask & ::boost::re_detail::char_class_word) && (c == '_'))
       
   823       || ((mask & ::boost::re_detail::char_class_unicode) && ::boost::re_detail::is_extended(c));
       
   824 }
       
   825 #endif
       
   826 
       
   827 
       
   828 template <class charT>
       
   829 inline boost::shared_ptr<const cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT))
       
   830 {
       
   831    cpp_regex_traits_base<charT> key(l);
       
   832    return ::boost::object_cache<cpp_regex_traits_base<charT>, cpp_regex_traits_implementation<charT> >::get(key, 5);
       
   833 }
       
   834 
       
   835 } // re_detail
       
   836 
       
   837 template <class charT>
       
   838 class cpp_regex_traits
       
   839 {
       
   840 private:
       
   841    typedef std::ctype<charT>            ctype_type;
       
   842 public:
       
   843    typedef charT                        char_type;
       
   844    typedef std::size_t                  size_type;
       
   845    typedef std::basic_string<char_type> string_type;
       
   846    typedef std::locale                  locale_type;
       
   847    typedef boost::uint_least32_t        char_class_type;
       
   848 
       
   849    struct boost_extensions_tag{};
       
   850 
       
   851    cpp_regex_traits()
       
   852       : m_pimpl(re_detail::create_cpp_regex_traits<charT>(std::locale()))
       
   853    { }
       
   854    static size_type length(const char_type* p)
       
   855    {
       
   856       return std::char_traits<charT>::length(p);
       
   857    }
       
   858    regex_constants::syntax_type syntax_type(charT c)const
       
   859    {
       
   860       return m_pimpl->syntax_type(c);
       
   861    }
       
   862    regex_constants::escape_syntax_type escape_syntax_type(charT c) const
       
   863    {
       
   864       return m_pimpl->escape_syntax_type(c);
       
   865    }
       
   866    charT translate(charT c) const
       
   867    {
       
   868       return c;
       
   869    }
       
   870    charT translate_nocase(charT c) const
       
   871    {
       
   872       return m_pimpl->m_pctype->tolower(c);
       
   873    }
       
   874    charT translate(charT c, bool icase) const
       
   875    {
       
   876       return icase ? m_pimpl->m_pctype->tolower(c) : c;
       
   877    }
       
   878    charT tolower(charT c) const
       
   879    {
       
   880       return m_pimpl->m_pctype->tolower(c);
       
   881    }
       
   882    charT toupper(charT c) const
       
   883    {
       
   884       return m_pimpl->m_pctype->toupper(c);
       
   885    }
       
   886    string_type transform(const charT* p1, const charT* p2) const
       
   887    {
       
   888       return m_pimpl->transform(p1, p2);
       
   889    }
       
   890    string_type transform_primary(const charT* p1, const charT* p2) const
       
   891    {
       
   892       return m_pimpl->transform_primary(p1, p2);
       
   893    }
       
   894    char_class_type lookup_classname(const charT* p1, const charT* p2) const
       
   895    {
       
   896       return m_pimpl->lookup_classname(p1, p2);
       
   897    }
       
   898    string_type lookup_collatename(const charT* p1, const charT* p2) const
       
   899    {
       
   900       return m_pimpl->lookup_collatename(p1, p2);
       
   901    }
       
   902    bool isctype(charT c, char_class_type f) const
       
   903    {
       
   904 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
       
   905       typedef typename std::ctype<charT>::mask ctype_mask;
       
   906 
       
   907       static const ctype_mask mask_base = 
       
   908          static_cast<ctype_mask>(
       
   909             std::ctype<charT>::alnum 
       
   910             | std::ctype<charT>::alpha
       
   911             | std::ctype<charT>::cntrl
       
   912             | std::ctype<charT>::digit
       
   913             | std::ctype<charT>::graph
       
   914             | std::ctype<charT>::lower
       
   915             | std::ctype<charT>::print
       
   916             | std::ctype<charT>::punct
       
   917             | std::ctype<charT>::space
       
   918             | std::ctype<charT>::upper
       
   919             | std::ctype<charT>::xdigit);
       
   920 
       
   921       if((f & mask_base) 
       
   922          && (m_pimpl->m_pctype->is(
       
   923             static_cast<ctype_mask>(f & mask_base), c)))
       
   924          return true;
       
   925       else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c))
       
   926          return true;
       
   927       else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_word) && (c == '_'))
       
   928          return true;
       
   929       else if((f & re_detail::cpp_regex_traits_implementation<charT>::mask_blank) 
       
   930          && m_pimpl->m_pctype->is(std::ctype<charT>::space, c)
       
   931          && !re_detail::is_separator(c))
       
   932          return true;
       
   933       return false;
       
   934 #else
       
   935       return m_pimpl->isctype(c, f);
       
   936 #endif
       
   937    }
       
   938    int toi(const charT*& p1, const charT* p2, int radix)const;
       
   939    int value(charT c, int radix)const
       
   940    {
       
   941       const charT* pc = &c;
       
   942       return toi(pc, pc + 1, radix);
       
   943    }
       
   944    locale_type imbue(locale_type l)
       
   945    {
       
   946       std::locale result(getloc());
       
   947       m_pimpl = re_detail::create_cpp_regex_traits<charT>(l);
       
   948       return result;
       
   949    }
       
   950    locale_type getloc()const
       
   951    {
       
   952       return m_pimpl->m_locale;
       
   953    }
       
   954    std::string error_string(regex_constants::error_type n) const
       
   955    {
       
   956       return m_pimpl->error_string(n);
       
   957    }
       
   958 
       
   959    //
       
   960    // extension:
       
   961    // set the name of the message catalog in use (defaults to "boost_regex").
       
   962    //
       
   963    static std::string catalog_name(const std::string& name);
       
   964    static std::string get_catalog_name();
       
   965 
       
   966 private:
       
   967    boost::shared_ptr<const re_detail::cpp_regex_traits_implementation<charT> > m_pimpl;
       
   968    //
       
   969    // catalog name handler:
       
   970    //
       
   971    static std::string& get_catalog_name_inst();
       
   972 
       
   973 #ifdef BOOST_HAS_THREADS
       
   974    static static_mutex& get_mutex_inst();
       
   975 #endif
       
   976 };
       
   977 
       
   978 
       
   979 template <class charT>
       
   980 int cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const
       
   981 {
       
   982    re_detail::parser_buf<charT>   sbuf;            // buffer for parsing numbers.
       
   983    std::basic_istream<charT>      is(&sbuf);       // stream for parsing numbers.
       
   984 
       
   985    // we do NOT want to parse any thousands separators inside the stream:
       
   986    last = std::find(first, last, BOOST_USE_FACET(std::numpunct<charT>, is.getloc()).thousands_sep());
       
   987 
       
   988    sbuf.pubsetbuf(const_cast<charT*>(static_cast<const charT*>(first)), static_cast<std::streamsize>(last-first));
       
   989    is.clear();
       
   990    if(std::abs(radix) == 16) is >> std::hex;
       
   991    else if(std::abs(radix) == 8) is >> std::oct;
       
   992    else is >> std::dec;
       
   993    int val;
       
   994    if(is >> val)
       
   995    {
       
   996       first = first + ((last - first) - sbuf.in_avail());
       
   997       return val;
       
   998    }
       
   999    else
       
  1000       return -1;
       
  1001 }
       
  1002 
       
  1003 template <class charT>
       
  1004 std::string cpp_regex_traits<charT>::catalog_name(const std::string& name)
       
  1005 {
       
  1006 #ifdef BOOST_HAS_THREADS
       
  1007    static_mutex::scoped_lock lk(get_mutex_inst());
       
  1008 #endif
       
  1009    std::string result(get_catalog_name_inst());
       
  1010    get_catalog_name_inst() = name;
       
  1011    return result;
       
  1012 }
       
  1013 
       
  1014 template <class charT>
       
  1015 std::string& cpp_regex_traits<charT>::get_catalog_name_inst()
       
  1016 {
       
  1017    static std::string s_name;
       
  1018    return s_name;
       
  1019 }
       
  1020 
       
  1021 template <class charT>
       
  1022 std::string cpp_regex_traits<charT>::get_catalog_name()
       
  1023 {
       
  1024 #ifdef BOOST_HAS_THREADS
       
  1025    static_mutex::scoped_lock lk(get_mutex_inst());
       
  1026 #endif
       
  1027    std::string result(get_catalog_name_inst());
       
  1028    return result;
       
  1029 }
       
  1030 
       
  1031 #ifdef BOOST_HAS_THREADS
       
  1032 template <class charT>
       
  1033 static_mutex& cpp_regex_traits<charT>::get_mutex_inst()
       
  1034 {
       
  1035    static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
       
  1036    return s_mutex;
       
  1037 }
       
  1038 #endif
       
  1039 
       
  1040 
       
  1041 } // boost
       
  1042 
       
  1043 #ifdef BOOST_MSVC
       
  1044 #pragma warning(pop)
       
  1045 #endif
       
  1046 
       
  1047 #ifdef BOOST_MSVC
       
  1048 #pragma warning(push)
       
  1049 #pragma warning(disable: 4103)
       
  1050 #endif
       
  1051 #ifdef BOOST_HAS_ABI_HEADERS
       
  1052 #  include BOOST_ABI_SUFFIX
       
  1053 #endif
       
  1054 #ifdef BOOST_MSVC
       
  1055 #pragma warning(pop)
       
  1056 #endif
       
  1057 
       
  1058 #endif
       
  1059 
       
  1060 #endif
       
  1061 
       
  1062