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)
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.
19 #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
20 #define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED
22 #include <boost/config.hpp>
24 #ifndef BOOST_NO_STD_LOCALE
26 #ifndef BOOST_RE_PAT_EXCEPT_HPP
27 #include <boost/regex/pattern_except.hpp>
29 #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
30 #include <boost/regex/v4/regex_traits_defaults.hpp>
32 #ifdef BOOST_HAS_THREADS
33 #include <boost/regex/pending/static_mutex.hpp>
35 #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
36 #include <boost/regex/v4/primary_transform.hpp>
38 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
39 #include <boost/regex/pending/object_cache.hpp>
48 #pragma warning(disable: 4103)
50 #ifdef BOOST_HAS_ABI_HEADERS
51 # include BOOST_ABI_PREFIX
59 #pragma warning(disable:4786)
65 // forward declaration is needed by some compilers:
67 template <class charT
>
68 class cpp_regex_traits
;
74 // acts as a stream buffer which wraps around a pair of pointers:
76 template <class charT
,
77 class traits
= ::std::char_traits
<charT
> >
78 class parser_buf
: public ::std::basic_streambuf
<charT
, traits
>
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
;
87 parser_buf() : base_type() { setbuf(0, 0); }
88 const charT
* getnext() { return this->gptr(); }
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
);
94 parser_buf
& operator=(const parser_buf
&);
95 parser_buf(const parser_buf
&);
98 template<class charT
, class traits
>
99 std::basic_streambuf
<charT
, traits
>*
100 parser_buf
<charT
, traits
>::setbuf(char_type
* s
, streamsize n
)
102 this->setg(s
, s
, s
+ n
);
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
)
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();
117 case ::std::ios_base::beg
:
118 if((off
< 0) || (off
> size
))
119 return pos_type(off_type(-1));
121 this->setg(g
, g
+ off
, g
+ size
);
123 case ::std::ios_base::end
:
124 if((off
< 0) || (off
> size
))
125 return pos_type(off_type(-1));
127 this->setg(g
, g
+ size
- off
, g
+ size
);
129 case ::std::ios_base::cur
:
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));
135 this->setg(g
, g
+ newpos
, g
+ size
);
141 #pragma warning(push)
142 #pragma warning(disable:4244)
144 return static_cast<pos_type
>(this->gptr() - this->eback());
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
)
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
)
160 this->setg(g
, g
+ off_type(sp
), g
+ size
);
162 return pos_type(off_type(-1));
166 // class cpp_regex_traits_base:
167 // acts as a container for locale and the facets we are using.
169 template <class charT
>
170 struct cpp_regex_traits_base
172 cpp_regex_traits_base(const std::locale
& l
)
174 std::locale
imbue(const std::locale
& l
);
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
;
181 std::collate
<charT
> const* m_pcollate
;
183 bool operator<(const cpp_regex_traits_base
& b
)const
185 if(m_pctype
== b
.m_pctype
)
187 #ifndef BOOST_NO_STD_MESSAGES
188 if(m_pmessages
== b
.m_pmessages
)
191 return m_pmessages
< b
.m_pmessages
;
193 return m_pcollate
< b
.m_pcollate
;
196 return m_pctype
< b
.m_pctype
;
198 bool operator==(const cpp_regex_traits_base
& b
)const
200 return (m_pctype
== b
.m_pctype
)
201 #ifndef BOOST_NO_STD_MESSAGES
202 && (m_pmessages
== b
.m_pmessages
)
204 && (m_pcollate
== b
.m_pcollate
);
208 template <class charT
>
209 std::locale cpp_regex_traits_base
<charT
>::imbue(const std::locale
& l
)
211 std::locale
result(m_locale
);
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
);
217 m_pcollate
= &BOOST_USE_FACET(std::collate
<charT
>, l
);
222 // class cpp_regex_traits_char_layer:
223 // implements methods that require specialisation for narrow characters:
225 template <class charT
>
226 class cpp_regex_traits_char_layer
: public cpp_regex_traits_base
<charT
>
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
;
232 cpp_regex_traits_char_layer(const std::locale
& l
)
233 : cpp_regex_traits_base
<charT
>(l
)
237 cpp_regex_traits_char_layer(const cpp_regex_traits_base
<charT
>& b
)
238 : cpp_regex_traits_base
<charT
>(b
)
244 regex_constants::syntax_type
syntax_type(charT c
)const
246 map_iterator_type i
= m_char_map
.find(c
);
247 return ((i
== m_char_map
.end()) ? 0 : i
->second
);
249 regex_constants::escape_syntax_type
escape_syntax_type(charT c
) const
251 map_iterator_type i
= m_char_map
.find(c
);
252 if(i
== m_char_map
.end())
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
;
262 string_type
get_default_message(regex_constants::syntax_type
);
263 // TODO: use a hash table when available!
267 template <class charT
>
268 void cpp_regex_traits_char_layer
<charT
>::init()
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
274 typename
std::messages
<charT
>::catalog cat
= static_cast<std::messages
<char>::catalog
>(-1);
276 typename
std::messages
<charT
>::catalog cat
= reinterpret_cast<std::messages
<char>::catalog
>(-1);
278 std::string
cat_name(cpp_regex_traits
<charT
>::get_catalog_name());
281 cat
= this->m_pmessages
->open(
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
);
292 // if we have a valid catalog then load our messages:
296 #ifndef BOOST_NO_EXCEPTIONS
299 for(regex_constants::syntax_type i
= 1; i
< regex_constants::syntax_max
; ++i
)
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
)
304 m_char_map
[mss
[j
]] = i
;
307 this->m_pmessages
->close(cat
);
308 #ifndef BOOST_NO_EXCEPTIONS
312 this->m_pmessages
->close(cat
);
320 for(regex_constants::syntax_type i
= 1; i
< regex_constants::syntax_max
; ++i
)
322 const char* ptr
= get_default_syntax(i
);
325 m_char_map
[this->m_pctype
->widen(*ptr
)] = i
;
329 #ifndef BOOST_NO_STD_MESSAGES
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
)
338 const char* ptr
= get_default_syntax(i
);
342 result
.append(1, this->m_pctype
->widen(*ptr
));
349 // specialised version for narrow characters:
352 class BOOST_REGEX_DECL cpp_regex_traits_char_layer
<char> : public cpp_regex_traits_base
<char>
354 typedef std::string string_type
;
356 cpp_regex_traits_char_layer(const std::locale
& l
)
357 : cpp_regex_traits_base
<char>(l
)
361 cpp_regex_traits_char_layer(const cpp_regex_traits_base
<char>& l
)
362 : cpp_regex_traits_base
<char>(l
)
367 regex_constants::syntax_type
syntax_type(char c
)const
369 return m_char_map
[static_cast<unsigned char>(c
)];
371 regex_constants::escape_syntax_type
escape_syntax_type(char c
) const
373 return m_char_map
[static_cast<unsigned char>(c
)];
377 regex_constants::syntax_type m_char_map
[1u << CHAR_BIT
];
381 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
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 char_class_horizontal_space
=1<<12,
399 char_class_vertical_space
=1<<13
405 // class cpp_regex_traits_implementation:
406 // provides pimpl implementation for cpp_regex_traits.
408 template <class charT
>
409 class cpp_regex_traits_implementation
: public cpp_regex_traits_char_layer
<charT
>
412 typedef typename cpp_regex_traits
<charT
>::char_class_type char_class_type
;
413 typedef typename
std::ctype
<charT
>::mask native_mask_type
;
414 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
415 BOOST_STATIC_CONSTANT(char_class_type
, mask_blank
= 1u << 24);
416 BOOST_STATIC_CONSTANT(char_class_type
, mask_word
= 1u << 25);
417 BOOST_STATIC_CONSTANT(char_class_type
, mask_unicode
= 1u << 26);
418 BOOST_STATIC_CONSTANT(char_class_type
, mask_horizontal
= 1u << 27);
419 BOOST_STATIC_CONSTANT(char_class_type
, mask_vertical
= 1u << 28);
422 typedef std::basic_string
<charT
> string_type
;
423 typedef charT char_type
;
424 //cpp_regex_traits_implementation();
425 cpp_regex_traits_implementation(const std::locale
& l
)
426 : cpp_regex_traits_char_layer
<charT
>(l
)
430 cpp_regex_traits_implementation(const cpp_regex_traits_base
<charT
>& l
)
431 : cpp_regex_traits_char_layer
<charT
>(l
)
435 std::string
error_string(regex_constants::error_type n
) const
437 if(!m_error_strings
.empty())
439 std::map
<int, std::string
>::const_iterator p
= m_error_strings
.find(n
);
440 return (p
== m_error_strings
.end()) ? std::string(get_default_error_string(n
)) : p
->second
;
442 return get_default_error_string(n
);
444 char_class_type
lookup_classname(const charT
* p1
, const charT
* p2
) const
446 char_class_type result
= lookup_classname_imp(p1
, p2
);
449 string_type
temp(p1
, p2
);
450 this->m_pctype
->tolower(&*temp
.begin(), &*temp
.begin() + temp
.size());
451 result
= lookup_classname_imp(&*temp
.begin(), &*temp
.begin() + temp
.size());
455 string_type
lookup_collatename(const charT
* p1
, const charT
* p2
) const;
456 string_type
transform_primary(const charT
* p1
, const charT
* p2
) const;
457 string_type
transform(const charT
* p1
, const charT
* p2
) const;
459 std::map
<int, std::string
> m_error_strings
; // error messages indexed by numberic ID
460 std::map
<string_type
, char_class_type
> m_custom_class_names
; // character class names
461 std::map
<string_type
, string_type
> m_custom_collate_names
; // collating element names
462 unsigned m_collate_type
; // the form of the collation string
463 charT m_collate_delim
; // the collation group delimiter
467 char_class_type
lookup_classname_imp(const charT
* p1
, const charT
* p2
) const;
469 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
471 bool isctype(charT c
, char_class_type m
)const;
475 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
476 #if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
478 template <class charT
>
479 typename cpp_regex_traits_implementation
<charT
>::char_class_type
const cpp_regex_traits_implementation
<charT
>::mask_blank
;
480 template <class charT
>
481 typename cpp_regex_traits_implementation
<charT
>::char_class_type
const cpp_regex_traits_implementation
<charT
>::mask_word
;
482 template <class charT
>
483 typename cpp_regex_traits_implementation
<charT
>::char_class_type
const cpp_regex_traits_implementation
<charT
>::mask_unicode
;
484 template <class charT
>
485 typename cpp_regex_traits_implementation
<charT
>::char_class_type
const cpp_regex_traits_implementation
<charT
>::mask_vertical
;
486 template <class charT
>
487 typename cpp_regex_traits_implementation
<charT
>::char_class_type
const cpp_regex_traits_implementation
<charT
>::mask_horizontal
;
492 template <class charT
>
493 typename cpp_regex_traits_implementation
<charT
>::string_type
494 cpp_regex_traits_implementation
<charT
>::transform_primary(const charT
* p1
, const charT
* p2
) const
499 // A bug in gcc 3.2 (and maybe other versions as well) treats
500 // p1 as a null terminated string, for efficiency reasons
501 // we work around this elsewhere, but just assert here that
502 // we adhere to gcc's (buggy) preconditions...
504 BOOST_ASSERT(*p2
== 0);
508 // swallowing all exceptions here is a bad idea
509 // however at least one std lib will always throw
510 // std::bad_alloc for certain arguments...
514 // What we do here depends upon the format of the sort key returned by
515 // sort key returned by this->transform:
517 switch(m_collate_type
)
521 // the best we can do is translate to lower case, then get a regular sort key:
523 result
.assign(p1
, p2
);
524 this->m_pctype
->tolower(&*result
.begin(), &*result
.begin() + result
.size());
525 result
= this->m_pcollate
->transform(&*result
.begin(), &*result
.begin() + result
.size());
530 // get a regular sort key, and then truncate it:
531 result
.assign(this->m_pcollate
->transform(p1
, p2
));
532 result
.erase(this->m_collate_delim
);
536 // get a regular sort key, and then truncate everything after the delim:
537 result
.assign(this->m_pcollate
->transform(p1
, p2
));
539 for(i
= 0; i
< result
.size(); ++i
)
541 if(result
[i
] == m_collate_delim
)
548 while(result
.size() && (charT(0) == *result
.rbegin()))
549 result
.erase(result
.size() - 1);
552 // character is ignorable at the primary level:
553 result
= string_type(1, charT(0));
558 template <class charT
>
559 typename cpp_regex_traits_implementation
<charT
>::string_type
560 cpp_regex_traits_implementation
<charT
>::transform(const charT
* p1
, const charT
* p2
) const
565 // A bug in gcc 3.2 (and maybe other versions as well) treats
566 // p1 as a null terminated string, for efficiency reasons
567 // we work around this elsewhere, but just assert here that
568 // we adhere to gcc's (buggy) preconditions...
570 BOOST_ASSERT(*p2
== 0);
572 // swallowing all exceptions here is a bad idea
573 // however at least one std lib will always throw
574 // std::bad_alloc for certain arguments...
578 result
= this->m_pcollate
->transform(p1
, p2
);
580 // Borland's STLPort version returns a NULL-terminated
581 // string that has garbage at the end - each call to
582 // std::collate<wchar_t>::transform returns a different string!
583 // So as a workaround, we'll truncate the string at the first NULL
584 // which _seems_ to work....
585 #if BOOST_WORKAROUND(__BORLANDC__, < 0x580)
586 result
.erase(result
.find(charT(0)));
589 // some implementations (Dinkumware) append unnecessary trailing \0's:
590 while(result
.size() && (charT(0) == *result
.rbegin()))
591 result
.erase(result
.size() - 1);
593 BOOST_ASSERT(std::find(result
.begin(), result
.end(), charT(0)) == result
.end());
602 template <class charT
>
603 typename cpp_regex_traits_implementation
<charT
>::string_type
604 cpp_regex_traits_implementation
<charT
>::lookup_collatename(const charT
* p1
, const charT
* p2
) const
606 typedef typename
std::map
<string_type
, string_type
>::const_iterator iter_type
;
607 if(m_custom_collate_names
.size())
609 iter_type pos
= m_custom_collate_names
.find(string_type(p1
, p2
));
610 if(pos
!= m_custom_collate_names
.end())
613 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
614 && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
615 && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
616 std::string
name(p1
, p2
);
619 const charT
* p0
= p1
;
621 name
.append(1, char(*p0
++));
623 name
= lookup_default_collate_name(name
);
624 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
625 && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
626 && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
628 return string_type(name
.begin(), name
.end());
633 typedef std::string::const_iterator iter
;
634 iter b
= name
.begin();
637 result
.append(1, charT(*b
++));
642 return string_type(1, *p1
);
643 return string_type();
646 template <class charT
>
647 void cpp_regex_traits_implementation
<charT
>::init()
649 #ifndef BOOST_NO_STD_MESSAGES
651 typename
std::messages
<charT
>::catalog cat
= static_cast<std::messages
<char>::catalog
>(-1);
653 typename
std::messages
<charT
>::catalog cat
= reinterpret_cast<std::messages
<char>::catalog
>(-1);
655 std::string
cat_name(cpp_regex_traits
<charT
>::get_catalog_name());
658 cat
= this->m_pmessages
->open(
663 std::string
m("Unable to open message catalog: ");
664 std::runtime_error
err(m
+ cat_name
);
665 boost::re_detail::raise_runtime_error(err
);
669 // if we have a valid catalog then load our messages:
676 for(boost::regex_constants::error_type i
= static_cast<boost::regex_constants::error_type
>(0);
677 i
<= boost::regex_constants::error_unknown
;
678 i
= static_cast<boost::regex_constants::error_type
>(i
+ 1))
680 const char* p
= get_default_error_string(i
);
681 string_type default_message
;
684 default_message
.append(1, this->m_pctype
->widen(*p
));
687 string_type s
= this->m_pmessages
->get(cat
, 0, i
+200, default_message
);
689 for(std::string::size_type j
= 0; j
< s
.size(); ++j
)
691 result
.append(1, this->m_pctype
->narrow(s
[j
], 0));
693 m_error_strings
[i
] = result
;
696 // Custom class names:
698 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
699 static const char_class_type masks
[16] =
701 std::ctype
<charT
>::alnum
,
702 std::ctype
<charT
>::alpha
,
703 std::ctype
<charT
>::cntrl
,
704 std::ctype
<charT
>::digit
,
705 std::ctype
<charT
>::graph
,
706 cpp_regex_traits_implementation
<charT
>::mask_horizontal
,
707 std::ctype
<charT
>::lower
,
708 std::ctype
<charT
>::print
,
709 std::ctype
<charT
>::punct
,
710 std::ctype
<charT
>::space
,
711 std::ctype
<charT
>::upper
,
712 cpp_regex_traits_implementation
<charT
>::mask_vertical
,
713 std::ctype
<charT
>::xdigit
,
714 cpp_regex_traits_implementation
<charT
>::mask_blank
,
715 cpp_regex_traits_implementation
<charT
>::mask_word
,
716 cpp_regex_traits_implementation
<charT
>::mask_unicode
,
719 static const char_class_type masks
[14] =
721 ::boost::re_detail::char_class_alnum
,
722 ::boost::re_detail::char_class_alpha
,
723 ::boost::re_detail::char_class_cntrl
,
724 ::boost::re_detail::char_class_digit
,
725 ::boost::re_detail::char_class_graph
,
726 ::boost::re_detail::char_class_horizontal_space
,
727 ::boost::re_detail::char_class_lower
,
728 ::boost::re_detail::char_class_print
,
729 ::boost::re_detail::char_class_punct
,
730 ::boost::re_detail::char_class_space
,
731 ::boost::re_detail::char_class_upper
,
732 ::boost::re_detail::char_class_vertical_space
,
733 ::boost::re_detail::char_class_xdigit
,
734 ::boost::re_detail::char_class_blank
,
735 ::boost::re_detail::char_class_word
,
736 ::boost::re_detail::char_class_unicode
,
739 static const string_type null_string
;
740 for(unsigned int j
= 0; j
<= 13; ++j
)
742 string_type
s(this->m_pmessages
->get(cat
, 0, j
+300, null_string
));
744 this->m_custom_class_names
[s
] = masks
[j
];
749 // get the collation format used by m_pcollate:
751 m_collate_type
= re_detail::find_sort_syntax(this, &m_collate_delim
);
754 template <class charT
>
755 typename cpp_regex_traits_implementation
<charT
>::char_class_type
756 cpp_regex_traits_implementation
<charT
>::lookup_classname_imp(const charT
* p1
, const charT
* p2
) const
758 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
759 static const char_class_type masks
[22] =
762 std::ctype
<char>::alnum
,
763 std::ctype
<char>::alpha
,
764 cpp_regex_traits_implementation
<charT
>::mask_blank
,
765 std::ctype
<char>::cntrl
,
766 std::ctype
<char>::digit
,
767 std::ctype
<char>::digit
,
768 std::ctype
<char>::graph
,
769 cpp_regex_traits_implementation
<charT
>::mask_horizontal
,
770 std::ctype
<char>::lower
,
771 std::ctype
<char>::lower
,
772 std::ctype
<char>::print
,
773 std::ctype
<char>::punct
,
774 std::ctype
<char>::space
,
775 std::ctype
<char>::space
,
776 std::ctype
<char>::upper
,
777 cpp_regex_traits_implementation
<charT
>::mask_unicode
,
778 std::ctype
<char>::upper
,
779 cpp_regex_traits_implementation
<charT
>::mask_vertical
,
780 std::ctype
<char>::alnum
| cpp_regex_traits_implementation
<charT
>::mask_word
,
781 std::ctype
<char>::alnum
| cpp_regex_traits_implementation
<charT
>::mask_word
,
782 std::ctype
<char>::xdigit
,
785 static const char_class_type masks
[22] =
788 ::boost::re_detail::char_class_alnum
,
789 ::boost::re_detail::char_class_alpha
,
790 ::boost::re_detail::char_class_blank
,
791 ::boost::re_detail::char_class_cntrl
,
792 ::boost::re_detail::char_class_digit
,
793 ::boost::re_detail::char_class_digit
,
794 ::boost::re_detail::char_class_graph
,
795 ::boost::re_detail::char_class_horizontal_space
,
796 ::boost::re_detail::char_class_lower
,
797 ::boost::re_detail::char_class_lower
,
798 ::boost::re_detail::char_class_print
,
799 ::boost::re_detail::char_class_punct
,
800 ::boost::re_detail::char_class_space
,
801 ::boost::re_detail::char_class_space
,
802 ::boost::re_detail::char_class_upper
,
803 ::boost::re_detail::char_class_unicode
,
804 ::boost::re_detail::char_class_upper
,
805 ::boost::re_detail::char_class_vertical_space
,
806 ::boost::re_detail::char_class_alnum
| ::boost::re_detail::char_class_word
,
807 ::boost::re_detail::char_class_alnum
| ::boost::re_detail::char_class_word
,
808 ::boost::re_detail::char_class_xdigit
,
811 if(m_custom_class_names
.size())
813 typedef typename
std::map
<std::basic_string
<charT
>, char_class_type
>::const_iterator map_iter
;
814 map_iter pos
= m_custom_class_names
.find(string_type(p1
, p2
));
815 if(pos
!= m_custom_class_names
.end())
818 std::size_t state_id
= 1 + re_detail::get_default_class_id(p1
, p2
);
819 BOOST_ASSERT(state_id
< sizeof(masks
) / sizeof(masks
[0]));
820 return masks
[state_id
];
823 #ifdef BOOST_REGEX_BUGGY_CTYPE_FACET
824 template <class charT
>
825 bool cpp_regex_traits_implementation
<charT
>::isctype(const charT c
, char_class_type mask
) const
828 ((mask
& ::boost::re_detail::char_class_space
) && (m_pctype
->is(std::ctype
<charT
>::space
, c
)))
829 || ((mask
& ::boost::re_detail::char_class_print
) && (m_pctype
->is(std::ctype
<charT
>::print
, c
)))
830 || ((mask
& ::boost::re_detail::char_class_cntrl
) && (m_pctype
->is(std::ctype
<charT
>::cntrl
, c
)))
831 || ((mask
& ::boost::re_detail::char_class_upper
) && (m_pctype
->is(std::ctype
<charT
>::upper
, c
)))
832 || ((mask
& ::boost::re_detail::char_class_lower
) && (m_pctype
->is(std::ctype
<charT
>::lower
, c
)))
833 || ((mask
& ::boost::re_detail::char_class_alpha
) && (m_pctype
->is(std::ctype
<charT
>::alpha
, c
)))
834 || ((mask
& ::boost::re_detail::char_class_digit
) && (m_pctype
->is(std::ctype
<charT
>::digit
, c
)))
835 || ((mask
& ::boost::re_detail::char_class_punct
) && (m_pctype
->is(std::ctype
<charT
>::punct
, c
)))
836 || ((mask
& ::boost::re_detail::char_class_xdigit
) && (m_pctype
->is(std::ctype
<charT
>::xdigit
, c
)))
837 || ((mask
& ::boost::re_detail::char_class_blank
) && (m_pctype
->is(std::ctype
<charT
>::space
, c
)) && !::boost::re_detail::is_separator(c
))
838 || ((mask
& ::boost::re_detail::char_class_word
) && (c
== '_'))
839 || ((mask
& ::boost::re_detail::char_class_unicode
) && ::boost::re_detail::is_extended(c
))
840 || ((mask
& ::boost::re_detail::char_class_vertical
) && (is_separator(c
) || (c
== '\v')))
841 || ((mask
& ::boost::re_detail::char_class_horizontal
) && m_pctype
->is(std::ctype
<charT
>::space
, c
) && !(is_separator(c
) || (c
== '\v')));
846 template <class charT
>
847 inline boost::shared_ptr
<const cpp_regex_traits_implementation
<charT
> > create_cpp_regex_traits(const std::locale
& l
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT
))
849 cpp_regex_traits_base
<charT
> key(l
);
850 return ::boost::object_cache
<cpp_regex_traits_base
<charT
>, cpp_regex_traits_implementation
<charT
> >::get(key
, 5);
855 template <class charT
>
856 class cpp_regex_traits
859 typedef std::ctype
<charT
> ctype_type
;
861 typedef charT char_type
;
862 typedef std::size_t size_type
;
863 typedef std::basic_string
<char_type
> string_type
;
864 typedef std::locale locale_type
;
865 typedef boost::uint_least32_t char_class_type
;
867 struct boost_extensions_tag
{};
870 : m_pimpl(re_detail::create_cpp_regex_traits
<charT
>(std::locale()))
872 static size_type
length(const char_type
* p
)
874 return std::char_traits
<charT
>::length(p
);
876 regex_constants::syntax_type
syntax_type(charT c
)const
878 return m_pimpl
->syntax_type(c
);
880 regex_constants::escape_syntax_type
escape_syntax_type(charT c
) const
882 return m_pimpl
->escape_syntax_type(c
);
884 charT
translate(charT c
) const
888 charT
translate_nocase(charT c
) const
890 return m_pimpl
->m_pctype
->tolower(c
);
892 charT
translate(charT c
, bool icase
) const
894 return icase
? m_pimpl
->m_pctype
->tolower(c
) : c
;
896 charT
tolower(charT c
) const
898 return m_pimpl
->m_pctype
->tolower(c
);
900 charT
toupper(charT c
) const
902 return m_pimpl
->m_pctype
->toupper(c
);
904 string_type
transform(const charT
* p1
, const charT
* p2
) const
906 return m_pimpl
->transform(p1
, p2
);
908 string_type
transform_primary(const charT
* p1
, const charT
* p2
) const
910 return m_pimpl
->transform_primary(p1
, p2
);
912 char_class_type
lookup_classname(const charT
* p1
, const charT
* p2
) const
914 return m_pimpl
->lookup_classname(p1
, p2
);
916 string_type
lookup_collatename(const charT
* p1
, const charT
* p2
) const
918 return m_pimpl
->lookup_collatename(p1
, p2
);
920 bool isctype(charT c
, char_class_type f
) const
922 #ifndef BOOST_REGEX_BUGGY_CTYPE_FACET
923 typedef typename
std::ctype
<charT
>::mask ctype_mask
;
925 static const ctype_mask mask_base
=
926 static_cast<ctype_mask
>(
927 std::ctype
<charT
>::alnum
928 | std::ctype
<charT
>::alpha
929 | std::ctype
<charT
>::cntrl
930 | std::ctype
<charT
>::digit
931 | std::ctype
<charT
>::graph
932 | std::ctype
<charT
>::lower
933 | std::ctype
<charT
>::print
934 | std::ctype
<charT
>::punct
935 | std::ctype
<charT
>::space
936 | std::ctype
<charT
>::upper
937 | std::ctype
<charT
>::xdigit
);
940 && (m_pimpl
->m_pctype
->is(
941 static_cast<ctype_mask
>(f
& mask_base
), c
)))
943 else if((f
& re_detail::cpp_regex_traits_implementation
<charT
>::mask_unicode
) && re_detail::is_extended(c
))
945 else if((f
& re_detail::cpp_regex_traits_implementation
<charT
>::mask_word
) && (c
== '_'))
947 else if((f
& re_detail::cpp_regex_traits_implementation
<charT
>::mask_blank
)
948 && m_pimpl
->m_pctype
->is(std::ctype
<charT
>::space
, c
)
949 && !re_detail::is_separator(c
))
951 else if((f
& re_detail::cpp_regex_traits_implementation
<charT
>::mask_vertical
)
952 && (::boost::re_detail::is_separator(c
) || (c
== '\v')))
954 else if((f
& re_detail::cpp_regex_traits_implementation
<charT
>::mask_horizontal
)
955 && this->isctype(c
, std::ctype
<charT
>::space
) && !this->isctype(c
, re_detail::cpp_regex_traits_implementation
<charT
>::mask_vertical
))
959 return m_pimpl
->isctype(c
, f
);
962 int toi(const charT
*& p1
, const charT
* p2
, int radix
)const;
963 int value(charT c
, int radix
)const
965 const charT
* pc
= &c
;
966 return toi(pc
, pc
+ 1, radix
);
968 locale_type
imbue(locale_type l
)
970 std::locale
result(getloc());
971 m_pimpl
= re_detail::create_cpp_regex_traits
<charT
>(l
);
974 locale_type
getloc()const
976 return m_pimpl
->m_locale
;
978 std::string
error_string(regex_constants::error_type n
) const
980 return m_pimpl
->error_string(n
);
985 // set the name of the message catalog in use (defaults to "boost_regex").
987 static std::string
catalog_name(const std::string
& name
);
988 static std::string
get_catalog_name();
991 boost::shared_ptr
<const re_detail::cpp_regex_traits_implementation
<charT
> > m_pimpl
;
993 // catalog name handler:
995 static std::string
& get_catalog_name_inst();
997 #ifdef BOOST_HAS_THREADS
998 static static_mutex
& get_mutex_inst();
1003 template <class charT
>
1004 int cpp_regex_traits
<charT
>::toi(const charT
*& first
, const charT
* last
, int radix
)const
1006 re_detail::parser_buf
<charT
> sbuf
; // buffer for parsing numbers.
1007 std::basic_istream
<charT
> is(&sbuf
); // stream for parsing numbers.
1009 // we do NOT want to parse any thousands separators inside the stream:
1010 last
= std::find(first
, last
, BOOST_USE_FACET(std::numpunct
<charT
>, is
.getloc()).thousands_sep());
1012 sbuf
.pubsetbuf(const_cast<charT
*>(static_cast<const charT
*>(first
)), static_cast<std::streamsize
>(last
-first
));
1014 if(std::abs(radix
) == 16) is
>> std::hex
;
1015 else if(std::abs(radix
) == 8) is
>> std::oct
;
1016 else is
>> std::dec
;
1020 first
= first
+ ((last
- first
) - sbuf
.in_avail());
1027 template <class charT
>
1028 std::string cpp_regex_traits
<charT
>::catalog_name(const std::string
& name
)
1030 #ifdef BOOST_HAS_THREADS
1031 static_mutex::scoped_lock
lk(get_mutex_inst());
1033 std::string
result(get_catalog_name_inst());
1034 get_catalog_name_inst() = name
;
1038 template <class charT
>
1039 std::string
& cpp_regex_traits
<charT
>::get_catalog_name_inst()
1041 static std::string s_name
;
1045 template <class charT
>
1046 std::string cpp_regex_traits
<charT
>::get_catalog_name()
1048 #ifdef BOOST_HAS_THREADS
1049 static_mutex::scoped_lock
lk(get_mutex_inst());
1051 std::string
result(get_catalog_name_inst());
1055 #ifdef BOOST_HAS_THREADS
1056 template <class charT
>
1057 static_mutex
& cpp_regex_traits
<charT
>::get_mutex_inst()
1059 static static_mutex s_mutex
= BOOST_STATIC_MUTEX_INIT
;
1068 #pragma warning(pop)
1072 #pragma warning(push)
1073 #pragma warning(disable: 4103)
1075 #ifdef BOOST_HAS_ABI_HEADERS
1076 # include BOOST_ABI_SUFFIX
1079 #pragma warning(pop)