## include/boost/regex/v5/cpp_regex_traits.hpp

61.7% Lines (211/342) 88.9% List of functions (72/81)
cpp_regex_traits.hpp
f(x) Functions (81)
Function Calls Lines Blocks
boost::re_detail_600::parser_buf<char, std::char_traits<char> >::parser_buf() :73 221186x 100.0% 100.0% boost::re_detail_600::parser_buf<wchar_t, std::char_traits<wchar_t> >::parser_buf() :73 28490x 100.0% 100.0% boost::re_detail_600::parser_buf<char, std::char_traits<char> >::setbuf(char*, long) :86 442372x 100.0% 100.0% boost::re_detail_600::parser_buf<wchar_t, std::char_traits<wchar_t> >::setbuf(wchar_t*, long) :86 56980x 100.0% 100.0% boost::re_detail_600::parser_buf<char, std::char_traits<char> >::seekoff(long, std::_Ios_Seekdir, std::_Ios_Openmode) :94 0 0.0% 0.0% boost::re_detail_600::parser_buf<wchar_t, std::char_traits<wchar_t> >::seekoff(long, std::_Ios_Seekdir, std::_Ios_Openmode) :94 0 0.0% 0.0% boost::re_detail_600::parser_buf<char, std::char_traits<char> >::seekpos(std::fpos<__mbstate_t>, std::_Ios_Openmode) :138 0 0.0% 0.0% boost::re_detail_600::parser_buf<wchar_t, std::char_traits<wchar_t> >::seekpos(std::fpos<__mbstate_t>, std::_Ios_Openmode) :138 0 0.0% 0.0% boost::re_detail_600::cpp_regex_traits_base<char>::cpp_regex_traits_base(std::locale const&) :158 28745x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_base<wchar_t>::cpp_regex_traits_base(std::locale const&) :158 28787x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_base<char>::operator<(boost::re_detail_600::cpp_regex_traits_base<char> const&) const :167 57706x 66.7% 67.0% boost::re_detail_600::cpp_regex_traits_base<wchar_t>::operator<(boost::re_detail_600::cpp_regex_traits_base<wchar_t> const&) const :167 57622x 66.7% 67.0% boost::re_detail_600::cpp_regex_traits_base<char>::operator==(boost::re_detail_600::cpp_regex_traits_base<char> const&) const :179 36x 100.0% 86.0% boost::re_detail_600::cpp_regex_traits_base<wchar_t>::operator==(boost::re_detail_600::cpp_regex_traits_base<wchar_t> const&) const :179 8x 100.0% 86.0% boost::re_detail_600::cpp_regex_traits_base<char>::imbue(std::locale const&) :188 28745x 87.5% 90.0% boost::re_detail_600::cpp_regex_traits_base<wchar_t>::imbue(std::locale const&) :188 28787x 87.5% 90.0% boost::re_detail_600::cpp_regex_traits_char_layer<wchar_t>::cpp_regex_traits_char_layer(boost::re_detail_600::cpp_regex_traits_base<wchar_t> const&) :214 8x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_char_layer<wchar_t>::syntax_type(wchar_t) const :221 993008x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_char_layer<wchar_t>::escape_syntax_type(wchar_t) const :226 46770x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_char_layer<wchar_t>::init() :245 8x 40.7% 38.0% boost::re_detail_600::cpp_regex_traits_char_layer<wchar_t>::get_default_message[abi:cxx11](unsigned char) :310 0 0.0% 0.0% boost::re_detail_600::cpp_regex_traits_char_layer<char>::cpp_regex_traits_char_layer(boost::re_detail_600::cpp_regex_traits_base<char> const&) :335 36x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_char_layer<char>::syntax_type(char) const :341 3314561x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_char_layer<char>::escape_syntax_type(char) const :345 693035x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::cpp_regex_traits_implementation(boost::re_detail_600::cpp_regex_traits_base<char> const&) :380 36x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::cpp_regex_traits_implementation(boost::re_detail_600::cpp_regex_traits_base<wchar_t> const&) :380 8x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::error_string[abi:cxx11](boost::regex_constants::error_type) const :385 4619x 60.0% 39.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::error_string[abi:cxx11](boost::regex_constants::error_type) const :385 4596x 60.0% 39.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::lookup_classname(char const*, char const*) const :394 290842x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::lookup_classname(wchar_t const*, wchar_t const*) const :394 291661x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::transform_primary[abi:cxx11](char const*, char const*) const :434 31229x 51.9% 69.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::transform_primary[abi:cxx11](wchar_t const*, wchar_t const*) const :434 31709x 51.9% 69.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::transform[abi:cxx11](char const*, char const*) const :514 137540x 93.3% 95.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::transform[abi:cxx11](wchar_t const*, wchar_t const*) const :514 129140x 86.7% 89.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::lookup_collatename[abi:cxx11](char const*, char const*) const :585 3168x 76.9% 68.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::lookup_collatename[abi:cxx11](wchar_t const*, wchar_t const*) const :585 3168x 76.9% 68.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::init() :604 36x 21.9% 15.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::init() :604 8x 21.9% 15.0% boost::re_detail_600::cpp_regex_traits_implementation<char>::lookup_classname_imp(char const*, char const*) const :689 292419x 62.5% 30.0% boost::re_detail_600::cpp_regex_traits_implementation<wchar_t>::lookup_classname_imp(wchar_t const*, wchar_t const*) const :689 293228x 62.5% 30.0% std::shared_ptr<boost::re_detail_600::cpp_regex_traits_implementation<char> const> boost::re_detail_600::create_cpp_regex_traits<char>(std::locale const&) :729 28745x 100.0% 100.0% std::shared_ptr<boost::re_detail_600::cpp_regex_traits_implementation<wchar_t> const> boost::re_detail_600::create_cpp_regex_traits<wchar_t>(std::locale const&) :729 28787x 100.0% 100.0% boost::cpp_regex_traits<char>::cpp_regex_traits() :751 28745x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::cpp_regex_traits() :751 28787x 100.0% 100.0% boost::cpp_regex_traits<char>::length(char const*) :754 526x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::length(wchar_t const*) :754 578x 100.0% 100.0% boost::cpp_regex_traits<char>::syntax_type(char) const :758 3314561x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::syntax_type(wchar_t) const :758 993008x 100.0% 100.0% boost::cpp_regex_traits<char>::escape_syntax_type(char) const :762 693035x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::escape_syntax_type(wchar_t) const :762 46770x 100.0% 100.0% boost::cpp_regex_traits<char>::translate(char, bool) const :774 329623837x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::translate(wchar_t, bool) const :774 33704576x 100.0% 100.0% boost::cpp_regex_traits<char>::tolower(char) const :778 180x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::tolower(wchar_t) const :778 180x 100.0% 100.0% boost::cpp_regex_traits<char>::toupper(char) const :782 132x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::toupper(wchar_t) const :782 132x 100.0% 100.0% boost::cpp_regex_traits<char>::transform[abi:cxx11](char const*, char const*) const :786 137432x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::transform[abi:cxx11](wchar_t const*, wchar_t const*) const :786 129116x 100.0% 100.0% boost::cpp_regex_traits<char>::transform_primary[abi:cxx11](char const*, char const*) const :790 31229x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::transform_primary[abi:cxx11](wchar_t const*, wchar_t const*) const :790 31709x 100.0% 100.0% boost::cpp_regex_traits<char>::lookup_classname(char const*, char const*) const :794 290842x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::lookup_classname(wchar_t const*, wchar_t const*) const :794 291661x 100.0% 100.0% boost::cpp_regex_traits<char>::lookup_collatename[abi:cxx11](char const*, char const*) const :798 3168x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::lookup_collatename[abi:cxx11](wchar_t const*, wchar_t const*) const :798 3168x 100.0% 100.0% boost::cpp_regex_traits<char>::isctype(char, unsigned int) const :802 4436610x 95.0% 91.0% boost::cpp_regex_traits<wchar_t>::isctype(wchar_t, unsigned int) const :802 6184820x 100.0% 100.0% boost::cpp_regex_traits<char>::imbue(std::locale) :858 0 0.0% 0.0% boost::cpp_regex_traits<wchar_t>::imbue(std::locale) :858 0 0.0% 0.0% boost::cpp_regex_traits<char>::getloc() const :864 0 0.0% 0.0% boost::cpp_regex_traits<wchar_t>::getloc() const :864 0 0.0% 0.0% boost::cpp_regex_traits<char>::error_string[abi:cxx11](boost::regex_constants::error_type) const :868 4619x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::error_string[abi:cxx11](boost::regex_constants::error_type) const :868 4596x 100.0% 100.0% boost::cpp_regex_traits<char>::toi(char const*&, char const*, int) const :894 221186x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::toi(wchar_t const*&, wchar_t const*, int) const :894 28490x 100.0% 100.0% boost::cpp_regex_traits<char>::get_catalog_name_inst[abi:cxx11]() :929 72x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::get_catalog_name_inst[abi:cxx11]() :929 16x 100.0% 100.0% boost::cpp_regex_traits<char>::get_catalog_name[abi:cxx11]() :936 72x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::get_catalog_name[abi:cxx11]() :936 16x 100.0% 100.0% boost::cpp_regex_traits<char>::get_mutex_inst() :947 72x 100.0% 100.0% boost::cpp_regex_traits<wchar_t>::get_mutex_inst() :947 16x 100.0% 100.0% boost::re_detail_600::cpp_regex_traits_char_layer<char>::init() :956 36x 52.8% 44.0%

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