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