Chris@16
|
1 /*
|
Chris@16
|
2 *
|
Chris@16
|
3 * Copyright (c) 2004
|
Chris@16
|
4 * John Maddock
|
Chris@16
|
5 *
|
Chris@16
|
6 * Use, modification and distribution are subject to the
|
Chris@16
|
7 * Boost Software License, Version 1.0. (See accompanying file
|
Chris@16
|
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 *
|
Chris@16
|
10 */
|
Chris@16
|
11
|
Chris@16
|
12 /*
|
Chris@16
|
13 * LOCATION: see http://www.boost.org for most recent version.
|
Chris@16
|
14 * FILE w32_regex_traits.hpp
|
Chris@16
|
15 * VERSION see <boost/version.hpp>
|
Chris@16
|
16 * DESCRIPTION: Declares regular expression traits class w32_regex_traits.
|
Chris@16
|
17 */
|
Chris@16
|
18
|
Chris@16
|
19 #ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
|
Chris@16
|
20 #define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
|
Chris@16
|
21
|
Chris@16
|
22 #ifndef BOOST_RE_PAT_EXCEPT_HPP
|
Chris@16
|
23 #include <boost/regex/pattern_except.hpp>
|
Chris@16
|
24 #endif
|
Chris@16
|
25 #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
|
Chris@16
|
26 #include <boost/regex/v4/regex_traits_defaults.hpp>
|
Chris@16
|
27 #endif
|
Chris@16
|
28 #ifdef BOOST_HAS_THREADS
|
Chris@16
|
29 #include <boost/regex/pending/static_mutex.hpp>
|
Chris@16
|
30 #endif
|
Chris@16
|
31 #ifndef BOOST_REGEX_PRIMARY_TRANSFORM
|
Chris@16
|
32 #include <boost/regex/v4/primary_transform.hpp>
|
Chris@16
|
33 #endif
|
Chris@16
|
34 #ifndef BOOST_REGEX_OBJECT_CACHE_HPP
|
Chris@16
|
35 #include <boost/regex/pending/object_cache.hpp>
|
Chris@16
|
36 #endif
|
Chris@16
|
37
|
Chris@16
|
38 #ifdef BOOST_MSVC
|
Chris@16
|
39 #pragma warning(push)
|
Chris@16
|
40 #pragma warning(disable: 4103)
|
Chris@16
|
41 #endif
|
Chris@16
|
42 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
43 # include BOOST_ABI_PREFIX
|
Chris@16
|
44 #endif
|
Chris@16
|
45 #ifdef BOOST_MSVC
|
Chris@16
|
46 #pragma warning(pop)
|
Chris@16
|
47 #endif
|
Chris@16
|
48
|
Chris@16
|
49 #ifdef BOOST_MSVC
|
Chris@16
|
50 #pragma warning(push)
|
Chris@16
|
51 #pragma warning(disable:4786)
|
Chris@16
|
52 #pragma warning(disable:4800)
|
Chris@16
|
53 #endif
|
Chris@16
|
54
|
Chris@16
|
55 namespace boost{
|
Chris@16
|
56
|
Chris@16
|
57 //
|
Chris@16
|
58 // forward declaration is needed by some compilers:
|
Chris@16
|
59 //
|
Chris@16
|
60 template <class charT>
|
Chris@16
|
61 class w32_regex_traits;
|
Chris@16
|
62
|
Chris@16
|
63 namespace re_detail{
|
Chris@16
|
64
|
Chris@16
|
65 //
|
Chris@16
|
66 // start by typedeffing the types we'll need:
|
Chris@16
|
67 //
|
Chris@16
|
68 typedef ::boost::uint32_t lcid_type; // placeholder for LCID.
|
Chris@16
|
69 typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE.
|
Chris@16
|
70
|
Chris@16
|
71 //
|
Chris@16
|
72 // then add wrappers around the actual Win32 API's (ie implementation hiding):
|
Chris@16
|
73 //
|
Chris@16
|
74 BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale();
|
Chris@16
|
75 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
|
Chris@16
|
76 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
77 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
|
Chris@16
|
78 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
|
Chris@16
|
79 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(unsigned short ca, lcid_type state_id);
|
Chris@16
|
80 #endif
|
Chris@16
|
81 #endif
|
Chris@16
|
82 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
|
Chris@16
|
83 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
84 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
|
Chris@16
|
85 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
|
Chris@16
|
86 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(unsigned short ca, lcid_type state_id);
|
Chris@16
|
87 #endif
|
Chris@16
|
88 #endif
|
Chris@16
|
89 BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
|
Chris@16
|
90 BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
|
Chris@16
|
91 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
92 BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
|
Chris@16
|
93 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
|
Chris@16
|
94 BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::basic_string<unsigned short>& def);
|
Chris@16
|
95 #endif
|
Chris@16
|
96 #endif
|
Chris@16
|
97 BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
|
Chris@16
|
98 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
99 BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
|
Chris@16
|
100 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
|
Chris@16
|
101 BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transform(lcid_type state_id, const unsigned short* p1, const unsigned short* p2);
|
Chris@16
|
102 #endif
|
Chris@16
|
103 #endif
|
Chris@16
|
104 BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
|
Chris@16
|
105 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
106 BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
|
Chris@16
|
107 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
|
Chris@16
|
108 BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_tolower(unsigned short c, lcid_type state_id);
|
Chris@16
|
109 #endif
|
Chris@16
|
110 #endif
|
Chris@16
|
111 BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
|
Chris@16
|
112 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
113 BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
|
Chris@16
|
114 #endif
|
Chris@16
|
115 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
|
Chris@16
|
116 #ifndef BOOST_NO_WREGEX
|
Chris@16
|
117 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
|
Chris@16
|
118 #ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
|
Chris@16
|
119 BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type state_id, boost::uint32_t m, unsigned short c);
|
Chris@16
|
120 #endif
|
Chris@16
|
121 #endif
|
Chris@16
|
122 //
|
Chris@16
|
123 // class w32_regex_traits_base:
|
Chris@16
|
124 // acts as a container for locale and the facets we are using.
|
Chris@16
|
125 //
|
Chris@16
|
126 template <class charT>
|
Chris@16
|
127 struct w32_regex_traits_base
|
Chris@16
|
128 {
|
Chris@16
|
129 w32_regex_traits_base(lcid_type l)
|
Chris@16
|
130 { imbue(l); }
|
Chris@16
|
131 lcid_type imbue(lcid_type l);
|
Chris@16
|
132
|
Chris@16
|
133 lcid_type m_locale;
|
Chris@16
|
134 };
|
Chris@16
|
135
|
Chris@16
|
136 template <class charT>
|
Chris@16
|
137 inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l)
|
Chris@16
|
138 {
|
Chris@16
|
139 lcid_type result(m_locale);
|
Chris@16
|
140 m_locale = l;
|
Chris@16
|
141 return result;
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 //
|
Chris@16
|
145 // class w32_regex_traits_char_layer:
|
Chris@16
|
146 // implements methods that require specialisation for narrow characters:
|
Chris@16
|
147 //
|
Chris@16
|
148 template <class charT>
|
Chris@16
|
149 class w32_regex_traits_char_layer : public w32_regex_traits_base<charT>
|
Chris@16
|
150 {
|
Chris@16
|
151 typedef std::basic_string<charT> string_type;
|
Chris@16
|
152 typedef std::map<charT, regex_constants::syntax_type> map_type;
|
Chris@16
|
153 typedef typename map_type::const_iterator map_iterator_type;
|
Chris@16
|
154 public:
|
Chris@16
|
155 w32_regex_traits_char_layer(const lcid_type l);
|
Chris@16
|
156
|
Chris@16
|
157 regex_constants::syntax_type syntax_type(charT c)const
|
Chris@16
|
158 {
|
Chris@16
|
159 map_iterator_type i = m_char_map.find(c);
|
Chris@16
|
160 return ((i == m_char_map.end()) ? 0 : i->second);
|
Chris@16
|
161 }
|
Chris@16
|
162 regex_constants::escape_syntax_type escape_syntax_type(charT c) const
|
Chris@16
|
163 {
|
Chris@16
|
164 map_iterator_type i = m_char_map.find(c);
|
Chris@16
|
165 if(i == m_char_map.end())
|
Chris@16
|
166 {
|
Chris@16
|
167 if(::boost::re_detail::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class;
|
Chris@16
|
168 if(::boost::re_detail::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class;
|
Chris@16
|
169 return 0;
|
Chris@16
|
170 }
|
Chris@16
|
171 return i->second;
|
Chris@16
|
172 }
|
Chris@16
|
173 charT tolower(charT c)const
|
Chris@16
|
174 {
|
Chris@16
|
175 return ::boost::re_detail::w32_tolower(c, this->m_locale);
|
Chris@16
|
176 }
|
Chris@16
|
177 bool isctype(boost::uint32_t mask, charT c)const
|
Chris@16
|
178 {
|
Chris@16
|
179 return ::boost::re_detail::w32_is(this->m_locale, mask, c);
|
Chris@16
|
180 }
|
Chris@16
|
181
|
Chris@16
|
182 private:
|
Chris@16
|
183 string_type get_default_message(regex_constants::syntax_type);
|
Chris@16
|
184 // TODO: use a hash table when available!
|
Chris@16
|
185 map_type m_char_map;
|
Chris@16
|
186 };
|
Chris@16
|
187
|
Chris@16
|
188 template <class charT>
|
Chris@16
|
189 w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::re_detail::lcid_type l)
|
Chris@16
|
190 : w32_regex_traits_base<charT>(l)
|
Chris@16
|
191 {
|
Chris@16
|
192 // we need to start by initialising our syntax map so we know which
|
Chris@16
|
193 // character is used for which purpose:
|
Chris@16
|
194 cat_type cat;
|
Chris@16
|
195 std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
|
Chris@16
|
196 if(cat_name.size())
|
Chris@16
|
197 {
|
Chris@16
|
198 cat = ::boost::re_detail::w32_cat_open(cat_name);
|
Chris@16
|
199 if(!cat)
|
Chris@16
|
200 {
|
Chris@16
|
201 std::string m("Unable to open message catalog: ");
|
Chris@16
|
202 std::runtime_error err(m + cat_name);
|
Chris@16
|
203 boost::re_detail::raise_runtime_error(err);
|
Chris@16
|
204 }
|
Chris@16
|
205 }
|
Chris@16
|
206 //
|
Chris@16
|
207 // if we have a valid catalog then load our messages:
|
Chris@16
|
208 //
|
Chris@16
|
209 if(cat)
|
Chris@16
|
210 {
|
Chris@16
|
211 for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
|
Chris@16
|
212 {
|
Chris@16
|
213 string_type mss = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i, get_default_message(i));
|
Chris@16
|
214 for(typename string_type::size_type j = 0; j < mss.size(); ++j)
|
Chris@16
|
215 {
|
Chris@16
|
216 this->m_char_map[mss[j]] = i;
|
Chris@16
|
217 }
|
Chris@16
|
218 }
|
Chris@16
|
219 }
|
Chris@16
|
220 else
|
Chris@16
|
221 {
|
Chris@16
|
222 for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
|
Chris@16
|
223 {
|
Chris@16
|
224 const char* ptr = get_default_syntax(i);
|
Chris@16
|
225 while(ptr && *ptr)
|
Chris@16
|
226 {
|
Chris@16
|
227 this->m_char_map[static_cast<charT>(*ptr)] = i;
|
Chris@16
|
228 ++ptr;
|
Chris@16
|
229 }
|
Chris@16
|
230 }
|
Chris@16
|
231 }
|
Chris@16
|
232 }
|
Chris@16
|
233
|
Chris@16
|
234 template <class charT>
|
Chris@16
|
235 typename w32_regex_traits_char_layer<charT>::string_type
|
Chris@16
|
236 w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
|
Chris@16
|
237 {
|
Chris@16
|
238 const char* ptr = get_default_syntax(i);
|
Chris@16
|
239 string_type result;
|
Chris@16
|
240 while(ptr && *ptr)
|
Chris@16
|
241 {
|
Chris@16
|
242 result.append(1, static_cast<charT>(*ptr));
|
Chris@16
|
243 ++ptr;
|
Chris@16
|
244 }
|
Chris@16
|
245 return result;
|
Chris@16
|
246 }
|
Chris@16
|
247
|
Chris@16
|
248 //
|
Chris@16
|
249 // specialised version for narrow characters:
|
Chris@16
|
250 //
|
Chris@16
|
251 template <>
|
Chris@16
|
252 class BOOST_REGEX_DECL w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
|
Chris@16
|
253 {
|
Chris@16
|
254 typedef std::string string_type;
|
Chris@16
|
255 public:
|
Chris@16
|
256 w32_regex_traits_char_layer(::boost::re_detail::lcid_type l)
|
Chris@16
|
257 : w32_regex_traits_base<char>(l)
|
Chris@16
|
258 {
|
Chris@16
|
259 init();
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 regex_constants::syntax_type syntax_type(char c)const
|
Chris@16
|
263 {
|
Chris@16
|
264 return m_char_map[static_cast<unsigned char>(c)];
|
Chris@16
|
265 }
|
Chris@16
|
266 regex_constants::escape_syntax_type escape_syntax_type(char c) const
|
Chris@16
|
267 {
|
Chris@16
|
268 return m_char_map[static_cast<unsigned char>(c)];
|
Chris@16
|
269 }
|
Chris@16
|
270 char tolower(char c)const
|
Chris@16
|
271 {
|
Chris@16
|
272 return m_lower_map[static_cast<unsigned char>(c)];
|
Chris@16
|
273 }
|
Chris@16
|
274 bool isctype(boost::uint32_t mask, char c)const
|
Chris@16
|
275 {
|
Chris@16
|
276 return m_type_map[static_cast<unsigned char>(c)] & mask;
|
Chris@16
|
277 }
|
Chris@16
|
278
|
Chris@16
|
279 private:
|
Chris@16
|
280 regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
|
Chris@16
|
281 char m_lower_map[1u << CHAR_BIT];
|
Chris@16
|
282 boost::uint16_t m_type_map[1u << CHAR_BIT];
|
Chris@16
|
283 void init();
|
Chris@16
|
284 };
|
Chris@16
|
285
|
Chris@16
|
286 //
|
Chris@16
|
287 // class w32_regex_traits_implementation:
|
Chris@16
|
288 // provides pimpl implementation for w32_regex_traits.
|
Chris@16
|
289 //
|
Chris@16
|
290 template <class charT>
|
Chris@16
|
291 class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT>
|
Chris@16
|
292 {
|
Chris@16
|
293 public:
|
Chris@16
|
294 typedef typename w32_regex_traits<charT>::char_class_type char_class_type;
|
Chris@16
|
295 BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1
|
Chris@16
|
296 BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2
|
Chris@16
|
297 BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3
|
Chris@16
|
298 BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4
|
Chris@16
|
299 BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff); // all the masks used by the CT_CTYPE1 group
|
Chris@16
|
300
|
Chris@16
|
301 typedef std::basic_string<charT> string_type;
|
Chris@16
|
302 typedef charT char_type;
|
Chris@16
|
303 w32_regex_traits_implementation(::boost::re_detail::lcid_type l);
|
Chris@16
|
304 std::string error_string(regex_constants::error_type n) const
|
Chris@16
|
305 {
|
Chris@16
|
306 if(!m_error_strings.empty())
|
Chris@16
|
307 {
|
Chris@16
|
308 std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
|
Chris@16
|
309 return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
|
Chris@16
|
310 }
|
Chris@16
|
311 return get_default_error_string(n);
|
Chris@16
|
312 }
|
Chris@16
|
313 char_class_type lookup_classname(const charT* p1, const charT* p2) const
|
Chris@16
|
314 {
|
Chris@16
|
315 char_class_type result = lookup_classname_imp(p1, p2);
|
Chris@16
|
316 if(result == 0)
|
Chris@16
|
317 {
|
Chris@16
|
318 typedef typename string_type::size_type size_type;
|
Chris@16
|
319 string_type temp(p1, p2);
|
Chris@16
|
320 for(size_type i = 0; i < temp.size(); ++i)
|
Chris@16
|
321 temp[i] = this->tolower(temp[i]);
|
Chris@16
|
322 result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
|
Chris@16
|
323 }
|
Chris@16
|
324 return result;
|
Chris@16
|
325 }
|
Chris@16
|
326 string_type lookup_collatename(const charT* p1, const charT* p2) const;
|
Chris@16
|
327 string_type transform_primary(const charT* p1, const charT* p2) const;
|
Chris@16
|
328 string_type transform(const charT* p1, const charT* p2) const
|
Chris@16
|
329 {
|
Chris@16
|
330 return ::boost::re_detail::w32_transform(this->m_locale, p1, p2);
|
Chris@16
|
331 }
|
Chris@16
|
332 private:
|
Chris@16
|
333 std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID
|
Chris@16
|
334 std::map<string_type, char_class_type> m_custom_class_names; // character class names
|
Chris@16
|
335 std::map<string_type, string_type> m_custom_collate_names; // collating element names
|
Chris@16
|
336 unsigned m_collate_type; // the form of the collation string
|
Chris@16
|
337 charT m_collate_delim; // the collation group delimiter
|
Chris@16
|
338 //
|
Chris@16
|
339 // helpers:
|
Chris@16
|
340 //
|
Chris@16
|
341 char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
|
Chris@16
|
342 };
|
Chris@16
|
343
|
Chris@16
|
344 template <class charT>
|
Chris@16
|
345 typename w32_regex_traits_implementation<charT>::string_type
|
Chris@16
|
346 w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
|
Chris@16
|
347 {
|
Chris@16
|
348 string_type result;
|
Chris@16
|
349 //
|
Chris@16
|
350 // What we do here depends upon the format of the sort key returned by
|
Chris@16
|
351 // sort key returned by this->transform:
|
Chris@16
|
352 //
|
Chris@16
|
353 switch(m_collate_type)
|
Chris@16
|
354 {
|
Chris@16
|
355 case sort_C:
|
Chris@16
|
356 case sort_unknown:
|
Chris@16
|
357 // the best we can do is translate to lower case, then get a regular sort key:
|
Chris@16
|
358 {
|
Chris@16
|
359 result.assign(p1, p2);
|
Chris@16
|
360 typedef typename string_type::size_type size_type;
|
Chris@16
|
361 for(size_type i = 0; i < result.size(); ++i)
|
Chris@16
|
362 result[i] = this->tolower(result[i]);
|
Chris@16
|
363 result = this->transform(&*result.begin(), &*result.begin() + result.size());
|
Chris@16
|
364 break;
|
Chris@16
|
365 }
|
Chris@16
|
366 case sort_fixed:
|
Chris@16
|
367 {
|
Chris@16
|
368 // get a regular sort key, and then truncate it:
|
Chris@16
|
369 result.assign(this->transform(p1, p2));
|
Chris@16
|
370 result.erase(this->m_collate_delim);
|
Chris@16
|
371 break;
|
Chris@16
|
372 }
|
Chris@16
|
373 case sort_delim:
|
Chris@16
|
374 // get a regular sort key, and then truncate everything after the delim:
|
Chris@16
|
375 result.assign(this->transform(p1, p2));
|
Chris@16
|
376 std::size_t i;
|
Chris@16
|
377 for(i = 0; i < result.size(); ++i)
|
Chris@16
|
378 {
|
Chris@16
|
379 if(result[i] == m_collate_delim)
|
Chris@16
|
380 break;
|
Chris@16
|
381 }
|
Chris@16
|
382 result.erase(i);
|
Chris@16
|
383 break;
|
Chris@16
|
384 }
|
Chris@16
|
385 if(result.empty())
|
Chris@16
|
386 result = string_type(1, charT(0));
|
Chris@16
|
387 return result;
|
Chris@16
|
388 }
|
Chris@16
|
389
|
Chris@16
|
390 template <class charT>
|
Chris@16
|
391 typename w32_regex_traits_implementation<charT>::string_type
|
Chris@16
|
392 w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
|
Chris@16
|
393 {
|
Chris@16
|
394 typedef typename std::map<string_type, string_type>::const_iterator iter_type;
|
Chris@16
|
395 if(m_custom_collate_names.size())
|
Chris@16
|
396 {
|
Chris@16
|
397 iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
|
Chris@16
|
398 if(pos != m_custom_collate_names.end())
|
Chris@16
|
399 return pos->second;
|
Chris@16
|
400 }
|
Chris@16
|
401 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
|
Chris@16
|
402 && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
|
Chris@16
|
403 std::string name(p1, p2);
|
Chris@16
|
404 #else
|
Chris@16
|
405 std::string name;
|
Chris@16
|
406 const charT* p0 = p1;
|
Chris@16
|
407 while(p0 != p2)
|
Chris@16
|
408 name.append(1, char(*p0++));
|
Chris@16
|
409 #endif
|
Chris@16
|
410 name = lookup_default_collate_name(name);
|
Chris@16
|
411 #if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
|
Chris@16
|
412 && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
|
Chris@16
|
413 if(name.size())
|
Chris@16
|
414 return string_type(name.begin(), name.end());
|
Chris@16
|
415 #else
|
Chris@16
|
416 if(name.size())
|
Chris@16
|
417 {
|
Chris@16
|
418 string_type result;
|
Chris@16
|
419 typedef std::string::const_iterator iter;
|
Chris@16
|
420 iter b = name.begin();
|
Chris@16
|
421 iter e = name.end();
|
Chris@16
|
422 while(b != e)
|
Chris@16
|
423 result.append(1, charT(*b++));
|
Chris@16
|
424 return result;
|
Chris@16
|
425 }
|
Chris@16
|
426 #endif
|
Chris@16
|
427 if(p2 - p1 == 1)
|
Chris@16
|
428 return string_type(1, *p1);
|
Chris@16
|
429 return string_type();
|
Chris@16
|
430 }
|
Chris@16
|
431
|
Chris@16
|
432 template <class charT>
|
Chris@16
|
433 w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::re_detail::lcid_type l)
|
Chris@16
|
434 : w32_regex_traits_char_layer<charT>(l)
|
Chris@16
|
435 {
|
Chris@16
|
436 cat_type cat;
|
Chris@16
|
437 std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
|
Chris@16
|
438 if(cat_name.size())
|
Chris@16
|
439 {
|
Chris@16
|
440 cat = ::boost::re_detail::w32_cat_open(cat_name);
|
Chris@16
|
441 if(!cat)
|
Chris@16
|
442 {
|
Chris@16
|
443 std::string m("Unable to open message catalog: ");
|
Chris@16
|
444 std::runtime_error err(m + cat_name);
|
Chris@16
|
445 boost::re_detail::raise_runtime_error(err);
|
Chris@16
|
446 }
|
Chris@16
|
447 }
|
Chris@16
|
448 //
|
Chris@16
|
449 // if we have a valid catalog then load our messages:
|
Chris@16
|
450 //
|
Chris@16
|
451 if(cat)
|
Chris@16
|
452 {
|
Chris@16
|
453 //
|
Chris@16
|
454 // Error messages:
|
Chris@16
|
455 //
|
Chris@16
|
456 for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
|
Chris@16
|
457 i <= boost::regex_constants::error_unknown;
|
Chris@16
|
458 i = static_cast<boost::regex_constants::error_type>(i + 1))
|
Chris@16
|
459 {
|
Chris@16
|
460 const char* p = get_default_error_string(i);
|
Chris@16
|
461 string_type default_message;
|
Chris@16
|
462 while(*p)
|
Chris@16
|
463 {
|
Chris@16
|
464 default_message.append(1, static_cast<charT>(*p));
|
Chris@16
|
465 ++p;
|
Chris@16
|
466 }
|
Chris@16
|
467 string_type s = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i+200, default_message);
|
Chris@16
|
468 std::string result;
|
Chris@16
|
469 for(std::string::size_type j = 0; j < s.size(); ++j)
|
Chris@16
|
470 {
|
Chris@16
|
471 result.append(1, static_cast<char>(s[j]));
|
Chris@16
|
472 }
|
Chris@16
|
473 m_error_strings[i] = result;
|
Chris@16
|
474 }
|
Chris@16
|
475 //
|
Chris@16
|
476 // Custom class names:
|
Chris@16
|
477 //
|
Chris@16
|
478 static const char_class_type masks[14] =
|
Chris@16
|
479 {
|
Chris@16
|
480 0x0104u, // C1_ALPHA | C1_DIGIT
|
Chris@16
|
481 0x0100u, // C1_ALPHA
|
Chris@16
|
482 0x0020u, // C1_CNTRL
|
Chris@16
|
483 0x0004u, // C1_DIGIT
|
Chris@16
|
484 (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE
|
Chris@16
|
485 0x0002u, // C1_LOWER
|
Chris@16
|
486 (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
|
Chris@16
|
487 0x0010u, // C1_PUNCT
|
Chris@16
|
488 0x0008u, // C1_SPACE
|
Chris@16
|
489 0x0001u, // C1_UPPER
|
Chris@16
|
490 0x0080u, // C1_XDIGIT
|
Chris@16
|
491 0x0040u, // C1_BLANK
|
Chris@16
|
492 w32_regex_traits_implementation<charT>::mask_word,
|
Chris@16
|
493 w32_regex_traits_implementation<charT>::mask_unicode,
|
Chris@16
|
494 };
|
Chris@16
|
495 static const string_type null_string;
|
Chris@16
|
496 for(unsigned int j = 0; j <= 13; ++j)
|
Chris@16
|
497 {
|
Chris@16
|
498 string_type s(::boost::re_detail::w32_cat_get(cat, this->m_locale, j+300, null_string));
|
Chris@16
|
499 if(s.size())
|
Chris@16
|
500 this->m_custom_class_names[s] = masks[j];
|
Chris@16
|
501 }
|
Chris@16
|
502 }
|
Chris@16
|
503 //
|
Chris@16
|
504 // get the collation format used by m_pcollate:
|
Chris@16
|
505 //
|
Chris@16
|
506 m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim);
|
Chris@16
|
507 }
|
Chris@16
|
508
|
Chris@16
|
509 template <class charT>
|
Chris@16
|
510 typename w32_regex_traits_implementation<charT>::char_class_type
|
Chris@16
|
511 w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
|
Chris@16
|
512 {
|
Chris@16
|
513 static const char_class_type masks[22] =
|
Chris@16
|
514 {
|
Chris@16
|
515 0,
|
Chris@16
|
516 0x0104u, // C1_ALPHA | C1_DIGIT
|
Chris@16
|
517 0x0100u, // C1_ALPHA
|
Chris@16
|
518 0x0040u, // C1_BLANK
|
Chris@16
|
519 0x0020u, // C1_CNTRL
|
Chris@16
|
520 0x0004u, // C1_DIGIT
|
Chris@16
|
521 0x0004u, // C1_DIGIT
|
Chris@16
|
522 (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK
|
Chris@16
|
523 w32_regex_traits_implementation<charT>::mask_horizontal,
|
Chris@16
|
524 0x0002u, // C1_LOWER
|
Chris@16
|
525 0x0002u, // C1_LOWER
|
Chris@16
|
526 (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
|
Chris@16
|
527 0x0010u, // C1_PUNCT
|
Chris@16
|
528 0x0008u, // C1_SPACE
|
Chris@16
|
529 0x0008u, // C1_SPACE
|
Chris@16
|
530 0x0001u, // C1_UPPER
|
Chris@16
|
531 w32_regex_traits_implementation<charT>::mask_unicode,
|
Chris@16
|
532 0x0001u, // C1_UPPER
|
Chris@16
|
533 w32_regex_traits_implementation<charT>::mask_vertical,
|
Chris@16
|
534 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
|
Chris@16
|
535 0x0104u | w32_regex_traits_implementation<charT>::mask_word,
|
Chris@16
|
536 0x0080u, // C1_XDIGIT
|
Chris@16
|
537 };
|
Chris@16
|
538 if(m_custom_class_names.size())
|
Chris@16
|
539 {
|
Chris@16
|
540 typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
|
Chris@16
|
541 map_iter pos = m_custom_class_names.find(string_type(p1, p2));
|
Chris@16
|
542 if(pos != m_custom_class_names.end())
|
Chris@16
|
543 return pos->second;
|
Chris@16
|
544 }
|
Chris@16
|
545 std::size_t state_id = 1 + re_detail::get_default_class_id(p1, p2);
|
Chris@16
|
546 if(state_id < sizeof(masks) / sizeof(masks[0]))
|
Chris@16
|
547 return masks[state_id];
|
Chris@16
|
548 return masks[0];
|
Chris@16
|
549 }
|
Chris@16
|
550
|
Chris@16
|
551
|
Chris@16
|
552 template <class charT>
|
Chris@101
|
553 boost::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::re_detail::lcid_type l)
|
Chris@16
|
554 {
|
Chris@16
|
555 // TODO: create a cache for previously constructed objects.
|
Chris@16
|
556 return boost::object_cache< ::boost::re_detail::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
|
Chris@16
|
557 }
|
Chris@16
|
558
|
Chris@16
|
559 } // re_detail
|
Chris@16
|
560
|
Chris@16
|
561 template <class charT>
|
Chris@16
|
562 class w32_regex_traits
|
Chris@16
|
563 {
|
Chris@16
|
564 public:
|
Chris@16
|
565 typedef charT char_type;
|
Chris@16
|
566 typedef std::size_t size_type;
|
Chris@16
|
567 typedef std::basic_string<char_type> string_type;
|
Chris@16
|
568 typedef ::boost::re_detail::lcid_type locale_type;
|
Chris@16
|
569 typedef boost::uint_least32_t char_class_type;
|
Chris@16
|
570
|
Chris@16
|
571 struct boost_extensions_tag{};
|
Chris@16
|
572
|
Chris@16
|
573 w32_regex_traits()
|
Chris@16
|
574 : m_pimpl(re_detail::create_w32_regex_traits<charT>(::boost::re_detail::w32_get_default_locale()))
|
Chris@16
|
575 { }
|
Chris@16
|
576 static size_type length(const char_type* p)
|
Chris@16
|
577 {
|
Chris@16
|
578 return std::char_traits<charT>::length(p);
|
Chris@16
|
579 }
|
Chris@16
|
580 regex_constants::syntax_type syntax_type(charT c)const
|
Chris@16
|
581 {
|
Chris@16
|
582 return m_pimpl->syntax_type(c);
|
Chris@16
|
583 }
|
Chris@16
|
584 regex_constants::escape_syntax_type escape_syntax_type(charT c) const
|
Chris@16
|
585 {
|
Chris@16
|
586 return m_pimpl->escape_syntax_type(c);
|
Chris@16
|
587 }
|
Chris@16
|
588 charT translate(charT c) const
|
Chris@16
|
589 {
|
Chris@16
|
590 return c;
|
Chris@16
|
591 }
|
Chris@16
|
592 charT translate_nocase(charT c) const
|
Chris@16
|
593 {
|
Chris@16
|
594 return this->m_pimpl->tolower(c);
|
Chris@16
|
595 }
|
Chris@16
|
596 charT translate(charT c, bool icase) const
|
Chris@16
|
597 {
|
Chris@16
|
598 return icase ? this->m_pimpl->tolower(c) : c;
|
Chris@16
|
599 }
|
Chris@16
|
600 charT tolower(charT c) const
|
Chris@16
|
601 {
|
Chris@16
|
602 return this->m_pimpl->tolower(c);
|
Chris@16
|
603 }
|
Chris@16
|
604 charT toupper(charT c) const
|
Chris@16
|
605 {
|
Chris@16
|
606 return ::boost::re_detail::w32_toupper(c, this->m_pimpl->m_locale);
|
Chris@16
|
607 }
|
Chris@16
|
608 string_type transform(const charT* p1, const charT* p2) const
|
Chris@16
|
609 {
|
Chris@16
|
610 return ::boost::re_detail::w32_transform(this->m_pimpl->m_locale, p1, p2);
|
Chris@16
|
611 }
|
Chris@16
|
612 string_type transform_primary(const charT* p1, const charT* p2) const
|
Chris@16
|
613 {
|
Chris@16
|
614 return m_pimpl->transform_primary(p1, p2);
|
Chris@16
|
615 }
|
Chris@16
|
616 char_class_type lookup_classname(const charT* p1, const charT* p2) const
|
Chris@16
|
617 {
|
Chris@16
|
618 return m_pimpl->lookup_classname(p1, p2);
|
Chris@16
|
619 }
|
Chris@16
|
620 string_type lookup_collatename(const charT* p1, const charT* p2) const
|
Chris@16
|
621 {
|
Chris@16
|
622 return m_pimpl->lookup_collatename(p1, p2);
|
Chris@16
|
623 }
|
Chris@16
|
624 bool isctype(charT c, char_class_type f) const
|
Chris@16
|
625 {
|
Chris@16
|
626 if((f & re_detail::w32_regex_traits_implementation<charT>::mask_base)
|
Chris@16
|
627 && (this->m_pimpl->isctype(f & re_detail::w32_regex_traits_implementation<charT>::mask_base, c)))
|
Chris@16
|
628 return true;
|
Chris@16
|
629 else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c))
|
Chris@16
|
630 return true;
|
Chris@16
|
631 else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_word) && (c == '_'))
|
Chris@16
|
632 return true;
|
Chris@16
|
633 else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_vertical)
|
Chris@16
|
634 && (::boost::re_detail::is_separator(c) || (c == '\v')))
|
Chris@16
|
635 return true;
|
Chris@16
|
636 else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_horizontal)
|
Chris@16
|
637 && this->isctype(c, 0x0008u) && !this->isctype(c, re_detail::w32_regex_traits_implementation<charT>::mask_vertical))
|
Chris@16
|
638 return true;
|
Chris@16
|
639 return false;
|
Chris@16
|
640 }
|
Chris@16
|
641 int toi(const charT*& p1, const charT* p2, int radix)const
|
Chris@16
|
642 {
|
Chris@16
|
643 return ::boost::re_detail::global_toi(p1, p2, radix, *this);
|
Chris@16
|
644 }
|
Chris@16
|
645 int value(charT c, int radix)const
|
Chris@16
|
646 {
|
Chris@16
|
647 int result = ::boost::re_detail::global_value(c);
|
Chris@16
|
648 return result < radix ? result : -1;
|
Chris@16
|
649 }
|
Chris@16
|
650 locale_type imbue(locale_type l)
|
Chris@16
|
651 {
|
Chris@16
|
652 ::boost::re_detail::lcid_type result(getloc());
|
Chris@16
|
653 m_pimpl = re_detail::create_w32_regex_traits<charT>(l);
|
Chris@16
|
654 return result;
|
Chris@16
|
655 }
|
Chris@16
|
656 locale_type getloc()const
|
Chris@16
|
657 {
|
Chris@16
|
658 return m_pimpl->m_locale;
|
Chris@16
|
659 }
|
Chris@16
|
660 std::string error_string(regex_constants::error_type n) const
|
Chris@16
|
661 {
|
Chris@16
|
662 return m_pimpl->error_string(n);
|
Chris@16
|
663 }
|
Chris@16
|
664
|
Chris@16
|
665 //
|
Chris@16
|
666 // extension:
|
Chris@16
|
667 // set the name of the message catalog in use (defaults to "boost_regex").
|
Chris@16
|
668 //
|
Chris@16
|
669 static std::string catalog_name(const std::string& name);
|
Chris@16
|
670 static std::string get_catalog_name();
|
Chris@16
|
671
|
Chris@16
|
672 private:
|
Chris@16
|
673 boost::shared_ptr<const re_detail::w32_regex_traits_implementation<charT> > m_pimpl;
|
Chris@16
|
674 //
|
Chris@16
|
675 // catalog name handler:
|
Chris@16
|
676 //
|
Chris@16
|
677 static std::string& get_catalog_name_inst();
|
Chris@16
|
678
|
Chris@16
|
679 #ifdef BOOST_HAS_THREADS
|
Chris@16
|
680 static static_mutex& get_mutex_inst();
|
Chris@16
|
681 #endif
|
Chris@16
|
682 };
|
Chris@16
|
683
|
Chris@16
|
684 template <class charT>
|
Chris@16
|
685 std::string w32_regex_traits<charT>::catalog_name(const std::string& name)
|
Chris@16
|
686 {
|
Chris@16
|
687 #ifdef BOOST_HAS_THREADS
|
Chris@16
|
688 static_mutex::scoped_lock lk(get_mutex_inst());
|
Chris@16
|
689 #endif
|
Chris@16
|
690 std::string result(get_catalog_name_inst());
|
Chris@16
|
691 get_catalog_name_inst() = name;
|
Chris@16
|
692 return result;
|
Chris@16
|
693 }
|
Chris@16
|
694
|
Chris@16
|
695 template <class charT>
|
Chris@16
|
696 std::string& w32_regex_traits<charT>::get_catalog_name_inst()
|
Chris@16
|
697 {
|
Chris@16
|
698 static std::string s_name;
|
Chris@16
|
699 return s_name;
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702 template <class charT>
|
Chris@16
|
703 std::string w32_regex_traits<charT>::get_catalog_name()
|
Chris@16
|
704 {
|
Chris@16
|
705 #ifdef BOOST_HAS_THREADS
|
Chris@16
|
706 static_mutex::scoped_lock lk(get_mutex_inst());
|
Chris@16
|
707 #endif
|
Chris@16
|
708 std::string result(get_catalog_name_inst());
|
Chris@16
|
709 return result;
|
Chris@16
|
710 }
|
Chris@16
|
711
|
Chris@16
|
712 #ifdef BOOST_HAS_THREADS
|
Chris@16
|
713 template <class charT>
|
Chris@16
|
714 static_mutex& w32_regex_traits<charT>::get_mutex_inst()
|
Chris@16
|
715 {
|
Chris@16
|
716 static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
|
Chris@16
|
717 return s_mutex;
|
Chris@16
|
718 }
|
Chris@16
|
719 #endif
|
Chris@16
|
720
|
Chris@16
|
721
|
Chris@16
|
722 } // boost
|
Chris@16
|
723
|
Chris@16
|
724 #ifdef BOOST_MSVC
|
Chris@16
|
725 #pragma warning(pop)
|
Chris@16
|
726 #endif
|
Chris@16
|
727
|
Chris@16
|
728 #ifdef BOOST_MSVC
|
Chris@16
|
729 #pragma warning(push)
|
Chris@16
|
730 #pragma warning(disable: 4103)
|
Chris@16
|
731 #endif
|
Chris@16
|
732 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
733 # include BOOST_ABI_SUFFIX
|
Chris@16
|
734 #endif
|
Chris@16
|
735 #ifdef BOOST_MSVC
|
Chris@16
|
736 #pragma warning(pop)
|
Chris@16
|
737 #endif
|
Chris@16
|
738
|
Chris@16
|
739 #endif
|