1 /*
2 *
3 * Copyright (c) 2004
4 * John Maddock
5 *
6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 *
10 */
11
12 /*
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE test_icu.cpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: Test code for Unicode regexes with ICU support.
17 */
18
19 //
20 // We can only build this if we have ICU support:
21 //
22 #include <boost/regex/config.hpp>
23 #if defined(BOOST_HAS_ICU) && !defined(BOOST_NO_STD_WSTRING)
24
25 #include <boost/regex/icu.hpp>
26 #include "test.hpp"
27
28 namespace unnecessary_fix{
29 //
30 // Some outrageously broken std lib's don't have a conforming
31 // back_insert_iterator, which means we can't use the std version
32 // as an argument to regex_replace, sigh... use our own:
33 //
34 template <class Seq>
35 class back_insert_iterator
36 {
37 private:
38 Seq* container;
39 public:
40 typedef const typename Seq::value_type value_type;
41 typedef Seq container_type;
42 typedef void difference_type;
43 typedef void pointer;
44 typedef void reference;
45 typedef std::output_iterator_tag iterator_category;
46
back_insert_iterator(Seq & x)47 explicit back_insert_iterator(Seq& x) : container(&x) {}
operator =(const value_type & val)48 back_insert_iterator& operator=(const value_type& val)
49 {
50 container->push_back(val);
51 return *this;
52 }
operator *()53 back_insert_iterator& operator*() { return *this; }
operator ++()54 back_insert_iterator& operator++() { return *this; }
operator ++(int)55 back_insert_iterator operator++(int) { return *this; }
56 };
57
58 template <class Seq>
back_inserter(Seq & x)59 inline back_insert_iterator<Seq> back_inserter(Seq& x)
60 {
61 return back_insert_iterator<Seq>(x);
62 }
63
64 }
65
66 //
67 // compare two match_results struct's for equality,
68 // converting the iterator as needed:
69 //
70 template <class MR1, class MR2>
compare_result(const MR1 & w1,const MR2 & w2,boost::mpl::int_<2> const *)71 void compare_result(const MR1& w1, const MR2& w2, boost::mpl::int_<2> const*)
72 {
73 typedef typename MR2::value_type MR2_value_type;
74 typedef typename MR2_value_type::const_iterator MR2_iterator_type;
75 typedef boost::u16_to_u32_iterator<MR2_iterator_type> iterator_type;
76 //typedef typename MR1::size_type size_type;
77 if(w1.size() != w2.size())
78 {
79 BOOST_REGEX_TEST_ERROR("Size mismatch in match_results class", UChar32);
80 }
81 for(int i = 0; i < (int)w1.size(); ++i)
82 {
83 if(w1[i].matched)
84 {
85 if(w2[i].matched == 0)
86 {
87 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
88 }
89 if((w1.position(i) != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2.prefix().first), iterator_type(w2[i].first))) || (w1.length(i) != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2[i].first), iterator_type(w2[i].second))))
90 {
91 BOOST_REGEX_TEST_ERROR("Iterator mismatch in match_results class", UChar32);
92 }
93 }
94 else if(w2[i].matched)
95 {
96 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
97 }
98 }
99 //
100 // We don't have a way to access a list of named sub-expressions since we only store
101 // hashes, but "abc" and "N" are common names used in our tests, so check those:
102 //
103 if (w1["abc"].matched)
104 {
105 if (w2["abc"].matched == 0)
106 {
107 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
108 }
109 if ((w1.position("abc") != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2.prefix().first), iterator_type(w2["abc"].first))) || (w1.length("abc") != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2["abc"].first), iterator_type(w2["abc"].second))))
110 {
111 BOOST_REGEX_TEST_ERROR("Iterator mismatch in match_results class", UChar32);
112 }
113 }
114 else if (w2["abc"].matched)
115 {
116 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
117 }
118 if (w1["N"].matched)
119 {
120 if (w2["N"].matched == 0)
121 {
122 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
123 }
124 if ((w1.position("N") != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2.prefix().first), iterator_type(w2["N"].first))) || (w1.length("N") != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2["N"].first), iterator_type(w2["N"].second))))
125 {
126 BOOST_REGEX_TEST_ERROR("Iterator mismatch in match_results class", UChar32);
127 }
128 }
129 else if (w2["N"].matched)
130 {
131 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
132 }
133 }
134 template <class MR1, class MR2>
compare_result(const MR1 & w1,const MR2 & w2,boost::mpl::int_<1> const *)135 void compare_result(const MR1& w1, const MR2& w2, boost::mpl::int_<1> const*)
136 {
137 typedef typename MR2::value_type MR2_value_type;
138 typedef typename MR2_value_type::const_iterator MR2_iterator_type;
139 typedef boost::u8_to_u32_iterator<MR2_iterator_type> iterator_type;
140 //typedef typename MR1::size_type size_type;
141 if(w1.size() != w2.size())
142 {
143 BOOST_REGEX_TEST_ERROR("Size mismatch in match_results class", UChar32);
144 }
145 for(int i = 0; i < (int)w1.size(); ++i)
146 {
147 if(w1[i].matched)
148 {
149 if(w2[i].matched == 0)
150 {
151 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
152 }
153 if((w1.position(i) != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2.prefix().first), iterator_type(w2[i].first))) || (w1.length(i) != boost::BOOST_REGEX_DETAIL_NS::distance(iterator_type(w2[i].first), iterator_type(w2[i].second))))
154 {
155 BOOST_REGEX_TEST_ERROR("Iterator mismatch in match_results class", UChar32);
156 }
157 }
158 else if(w2[i].matched)
159 {
160 BOOST_REGEX_TEST_ERROR("Matched mismatch in match_results class", UChar32);
161 }
162 }
163 }
164
test_icu_grep(const boost::u32regex & r,const std::vector<::UChar32> & search_text)165 void test_icu_grep(const boost::u32regex& r, const std::vector< ::UChar32>& search_text)
166 {
167 typedef std::vector< ::UChar32>::const_iterator const_iterator;
168 typedef boost::u32regex_iterator<const_iterator> test_iterator;
169 boost::regex_constants::match_flag_type opts = test_info<wchar_t>::match_options();
170 const int* answer_table = test_info<wchar_t>::answer_table();
171 test_iterator start(search_text.begin(), search_text.end(), r, opts), end;
172 test_iterator copy(start);
173 const_iterator last_end = search_text.begin();
174 while(start != end)
175 {
176 if(start != copy)
177 {
178 BOOST_REGEX_TEST_ERROR("Failed iterator != comparison.", wchar_t);
179 }
180 if(!(start == copy))
181 {
182 BOOST_REGEX_TEST_ERROR("Failed iterator == comparison.", wchar_t);
183 }
184 test_result(*start, search_text.begin(), answer_table);
185 // test $` and $' :
186 if(start->prefix().first != last_end)
187 {
188 BOOST_REGEX_TEST_ERROR("Incorrect position for start of $`", wchar_t);
189 }
190 if(start->prefix().second != (*start)[0].first)
191 {
192 BOOST_REGEX_TEST_ERROR("Incorrect position for end of $`", wchar_t);
193 }
194 if(start->prefix().matched != (start->prefix().first != start->prefix().second))
195 {
196 BOOST_REGEX_TEST_ERROR("Incorrect position for matched member of $`", wchar_t);
197 }
198 if(start->suffix().first != (*start)[0].second)
199 {
200 BOOST_REGEX_TEST_ERROR("Incorrect position for start of $'", wchar_t);
201 }
202 if(start->suffix().second != search_text.end())
203 {
204 BOOST_REGEX_TEST_ERROR("Incorrect position for end of $'", wchar_t);
205 }
206 if(start->suffix().matched != (start->suffix().first != start->suffix().second))
207 {
208 BOOST_REGEX_TEST_ERROR("Incorrect position for matched member of $'", wchar_t);
209 }
210 last_end = (*start)[0].second;
211 ++start;
212 ++copy;
213 // move on the answer table to next set of answers;
214 if(*answer_table != -2)
215 while(*answer_table++ != -2){}
216 }
217 if(answer_table[0] >= 0)
218 {
219 // we should have had a match but didn't:
220 BOOST_REGEX_TEST_ERROR("Expected match was not found.", wchar_t);
221 }
222 }
223
test_icu(const wchar_t &,const test_regex_search_tag &)224 void test_icu(const wchar_t&, const test_regex_search_tag& )
225 {
226 boost::u32regex r;
227 if(*test_locale::c_str())
228 {
229 U_NAMESPACE_QUALIFIER Locale l(test_locale::c_str());
230 if(l.isBogus())
231 return;
232 r.imbue(l);
233 }
234
235 std::vector< ::UChar32> expression;
236 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
237 expression.assign(test_info<wchar_t>::expression().begin(), test_info<wchar_t>::expression().end());
238 #else
239 std::copy(test_info<wchar_t>::expression().begin(), test_info<wchar_t>::expression().end(), std::back_inserter(expression));
240 #endif
241 boost::regex_constants::syntax_option_type syntax_options = test_info<UChar32>::syntax_options();
242 #ifndef BOOST_NO_EXCEPTIONS
243 try
244 #endif
245 {
246 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
247 r.assign(expression.begin(), expression.end(), syntax_options);
248 #else
249 if(expression.size())
250 r.assign(&*expression.begin(), expression.size(), syntax_options);
251 else
252 r.assign(static_cast<UChar32 const*>(0), expression.size(), syntax_options);
253 #endif
254 if(r.status())
255 {
256 BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done, error code = " << r.status(), UChar32);
257 }
258 std::vector< ::UChar32> search_text;
259 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
260 search_text.assign(test_info<wchar_t>::search_text().begin(), test_info<wchar_t>::search_text().end());
261 #else
262 std::copy(test_info<wchar_t>::search_text().begin(), test_info<wchar_t>::search_text().end(), std::back_inserter(search_text));
263 #endif
264 boost::regex_constants::match_flag_type opts = test_info<wchar_t>::match_options();
265 const int* answer_table = test_info<wchar_t>::answer_table();
266 boost::match_results<std::vector< ::UChar32>::const_iterator> what;
267 if(boost::u32regex_search(
268 const_cast<std::vector< ::UChar32>const&>(search_text).begin(),
269 const_cast<std::vector< ::UChar32>const&>(search_text).end(),
270 what,
271 r,
272 opts))
273 {
274 test_result(what, const_cast<std::vector< ::UChar32>const&>(search_text).begin(), answer_table);
275 }
276 else if(answer_table[0] >= 0)
277 {
278 // we should have had a match but didn't:
279 BOOST_REGEX_TEST_ERROR("Expected match was not found.", UChar32);
280 }
281
282 if(0 == *test_locale::c_str())
283 {
284 //
285 // Now try UTF-16 construction:
286 //
287 typedef boost::u32_to_u16_iterator<std::vector<UChar32>::const_iterator> u16_conv;
288 std::vector<UChar> expression16, text16;
289 boost::match_results<std::vector<UChar>::const_iterator> what16;
290 boost::match_results<const UChar*> what16c;
291 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
292 expression16.assign(u16_conv(expression.begin()), u16_conv(expression.end()));
293 text16.assign(u16_conv(search_text.begin()), u16_conv(search_text.end()));
294 #else
295 expression16.clear();
296 std::copy(u16_conv(expression.begin()), u16_conv(expression.end()), std::back_inserter(expression16));
297 text16.clear();
298 std::copy(u16_conv(search_text.begin()), u16_conv(search_text.end()), std::back_inserter(text16));
299 #endif
300 r = boost::make_u32regex(expression16.begin(), expression16.end(), syntax_options);
301 if(boost::u32regex_search(const_cast<const std::vector<UChar>&>(text16).begin(), const_cast<const std::vector<UChar>&>(text16).end(), what16, r, opts))
302 {
303 compare_result(what, what16, static_cast<boost::mpl::int_<2> const*>(0));
304 }
305 else if(answer_table[0] >= 0)
306 {
307 // we should have had a match but didn't:
308 BOOST_REGEX_TEST_ERROR("Expected match was not found.", UChar32);
309 }
310 if(std::find(expression16.begin(), expression16.end(), 0) == expression16.end())
311 {
312 expression16.push_back(0);
313 r = boost::make_u32regex(&*expression16.begin(), syntax_options);
314 if(std::find(text16.begin(), text16.end(), 0) == text16.end())
315 {
316 text16.push_back(0);
317 if(boost::u32regex_search((const UChar*)&*text16.begin(), what16c, r, opts))
318 {
319 compare_result(what, what16c, static_cast<boost::mpl::int_<2> const*>(0));
320 }
321 else if(answer_table[0] >= 0)
322 {
323 // we should have had a match but didn't:
324 BOOST_REGEX_TEST_ERROR("Expected match was not found.", UChar32);
325 }
326 }
327 }
328 //
329 // Now try UTF-8 construction:
330 //
331 typedef boost::u32_to_u8_iterator<std::vector<UChar32>::const_iterator, unsigned char> u8_conv;
332 std::vector<unsigned char> expression8, text8;
333 boost::match_results<std::vector<unsigned char>::const_iterator> what8;
334 boost::match_results<const unsigned char*> what8c;
335 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
336 expression8.assign(u8_conv(expression.begin()), u8_conv(expression.end()));
337 text8.assign(u8_conv(search_text.begin()), u8_conv(search_text.end()));
338 #else
339 expression8.clear();
340 std::copy(u8_conv(expression.begin()), u8_conv(expression.end()), std::back_inserter(expression8));
341 text8.clear();
342 std::copy(u8_conv(search_text.begin()), u8_conv(search_text.end()), std::back_inserter(text8));
343 #endif
344 r = boost::make_u32regex(expression8.begin(), expression8.end(), syntax_options);
345 if(boost::u32regex_search(const_cast<const std::vector<unsigned char>&>(text8).begin(), const_cast<const std::vector<unsigned char>&>(text8).end(), what8, r, opts))
346 {
347 compare_result(what, what8, static_cast<boost::mpl::int_<1> const*>(0));
348 }
349 else if(answer_table[0] >= 0)
350 {
351 // we should have had a match but didn't:
352 BOOST_REGEX_TEST_ERROR("Expected match was not found.", UChar32);
353 }
354 if(std::find(expression8.begin(), expression8.end(), 0) == expression8.end())
355 {
356 expression8.push_back(0);
357 r = boost::make_u32regex(&*expression8.begin(), syntax_options);
358 if(std::find(text8.begin(), text8.end(), 0) == text8.end())
359 {
360 text8.push_back(0);
361 if(boost::u32regex_search((const unsigned char*)&*text8.begin(), what8c, r, opts))
362 {
363 compare_result(what, what8c, static_cast<boost::mpl::int_<1> const*>(0));
364 }
365 else if(answer_table[0] >= 0)
366 {
367 // we should have had a match but didn't:
368 BOOST_REGEX_TEST_ERROR("Expected match was not found.", UChar32);
369 }
370 }
371 }
372 }
373 //
374 // finally try a grep:
375 //
376 test_icu_grep(r, search_text);
377 }
378 #ifndef BOOST_NO_EXCEPTIONS
379 catch(const boost::bad_expression& e)
380 {
381 BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done: " << e.what(), UChar32);
382 }
383 catch(const std::runtime_error& e)
384 {
385 BOOST_REGEX_TEST_ERROR("Received an unexpected std::runtime_error: " << e.what(), UChar32);
386 }
387 catch(const std::exception& e)
388 {
389 BOOST_REGEX_TEST_ERROR("Received an unexpected std::exception: " << e.what(), UChar32);
390 }
391 catch(...)
392 {
393 BOOST_REGEX_TEST_ERROR("Received an unexpected exception of unknown type", UChar32);
394 }
395 #endif
396 }
397
test_icu(const wchar_t &,const test_invalid_regex_tag &)398 void test_icu(const wchar_t&, const test_invalid_regex_tag&)
399 {
400 //typedef boost::u16_to_u32_iterator<std::wstring::const_iterator, ::UChar32> conv_iterator;
401 std::vector< ::UChar32> expression;
402 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
403 expression.assign(test_info<wchar_t>::expression().begin(), test_info<wchar_t>::expression().end());
404 #else
405 std::copy(test_info<wchar_t>::expression().begin(), test_info<wchar_t>::expression().end(), std::back_inserter(expression));
406 #endif
407 boost::regex_constants::syntax_option_type syntax_options = test_info<wchar_t>::syntax_options();
408 boost::u32regex r;
409 if(*test_locale::c_str())
410 {
411 U_NAMESPACE_QUALIFIER Locale l(test_locale::c_str());
412 if(l.isBogus())
413 return;
414 r.imbue(l);
415 }
416 //
417 // try it with exceptions disabled first:
418 //
419 #ifndef BOOST_NO_EXCEPTIONS
420 try
421 #endif
422 {
423 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
424 if(0 == r.assign(expression.begin(), expression.end(), syntax_options | boost::regex_constants::no_except).status())
425 #else
426 if(expression.size())
427 r.assign(&*expression.begin(), expression.size(), syntax_options | boost::regex_constants::no_except);
428 else
429 r.assign(static_cast<UChar32 const*>(0), static_cast<boost::u32regex::size_type>(0), syntax_options | boost::regex_constants::no_except);
430 if(0 == r.status())
431 #endif
432 {
433 BOOST_REGEX_TEST_ERROR("Expression compiled when it should not have done so.", wchar_t);
434 }
435 }
436 #ifndef BOOST_NO_EXCEPTIONS
437 catch(...)
438 {
439 BOOST_REGEX_TEST_ERROR("Unexpected exception thrown.", wchar_t);
440 }
441 #endif
442 //
443 // now try again with exceptions:
444 //
445 bool have_catch = false;
446 #ifndef BOOST_NO_EXCEPTIONS
447 try
448 #endif
449 {
450 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
451 r.assign(expression.begin(), expression.end(), syntax_options);
452 #else
453 if(expression.size())
454 r.assign(&*expression.begin(), expression.size(), syntax_options);
455 else
456 r.assign(static_cast<UChar32 const*>(0), static_cast<boost::u32regex::size_type>(0), syntax_options);
457 #endif
458 #ifdef BOOST_NO_EXCEPTIONS
459 if(r.status())
460 have_catch = true;
461 #endif
462 }
463 #ifndef BOOST_NO_EXCEPTIONS
464 catch(const boost::bad_expression&)
465 {
466 have_catch = true;
467 }
468 catch(const std::runtime_error& e)
469 {
470 have_catch = true;
471 BOOST_REGEX_TEST_ERROR("Expected a bad_expression exception, but a std::runtime_error instead: " << e.what(), wchar_t);
472 }
473 catch(const std::exception& e)
474 {
475 have_catch = true;
476 BOOST_REGEX_TEST_ERROR("Expected a bad_expression exception, but a std::exception instead: " << e.what(), wchar_t);
477 }
478 catch(...)
479 {
480 have_catch = true;
481 BOOST_REGEX_TEST_ERROR("Expected a bad_expression exception, but got an exception of unknown type instead", wchar_t);
482 }
483 #endif
484 if(!have_catch)
485 {
486 // oops expected exception was not thrown:
487 BOOST_REGEX_TEST_ERROR("Expected an exception, but didn't find one.", wchar_t);
488 }
489
490 if(0 == *test_locale::c_str())
491 {
492 //
493 // Now try UTF-16 construction:
494 //
495 typedef boost::u32_to_u16_iterator<std::vector<UChar32>::const_iterator> u16_conv;
496 std::vector<UChar> expression16;
497 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
498 expression16.assign(u16_conv(expression.begin()), u16_conv(expression.end()));
499 #else
500 std::copy(u16_conv(expression.begin()), u16_conv(expression.end()), std::back_inserter(expression16));
501 #endif
502 if(0 == boost::make_u32regex(expression16.begin(), expression16.end(), syntax_options | boost::regex_constants::no_except).status())
503 {
504 BOOST_REGEX_TEST_ERROR("Expression compiled when it should not have done so.", wchar_t);
505 }
506 if(std::find(expression16.begin(), expression16.end(), 0) == expression16.end())
507 {
508 expression16.push_back(0);
509 if(0 == boost::make_u32regex(&*expression16.begin(), syntax_options | boost::regex_constants::no_except).status())
510 {
511 BOOST_REGEX_TEST_ERROR("Expression compiled when it should not have done so.", wchar_t);
512 }
513 }
514 //
515 // Now try UTF-8 construction:
516 //
517 typedef boost::u32_to_u8_iterator<std::vector<UChar32>::const_iterator> u8_conv;
518 std::vector<unsigned char> expression8;
519 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
520 expression8.assign(u8_conv(expression.begin()), u8_conv(expression.end()));
521 #else
522 std::copy(u8_conv(expression.begin()), u8_conv(expression.end()), std::back_inserter(expression8));
523 #endif
524 if(0 == boost::make_u32regex(expression8.begin(), expression8.end(), syntax_options | boost::regex_constants::no_except).status())
525 {
526 BOOST_REGEX_TEST_ERROR("Expression compiled when it should not have done so.", wchar_t);
527 }
528 if(std::find(expression8.begin(), expression8.end(), 0) == expression8.end())
529 {
530 expression8.push_back(0);
531 if(0 == boost::make_u32regex(&*expression8.begin(), syntax_options | boost::regex_constants::no_except).status())
532 {
533 BOOST_REGEX_TEST_ERROR("Expression compiled when it should not have done so.", wchar_t);
534 }
535 }
536 }
537 }
538
test_icu(const wchar_t &,const test_regex_replace_tag &)539 void test_icu(const wchar_t&, const test_regex_replace_tag&)
540 {
541 std::vector< ::UChar32> expression;
542 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
543 expression.assign(test_info<wchar_t>::expression().begin(), test_info<wchar_t>::expression().end());
544 #else
545 std::copy(test_info<wchar_t>::expression().begin(), test_info<wchar_t>::expression().end(), std::back_inserter(expression));
546 #endif
547 boost::regex_constants::syntax_option_type syntax_options = test_info<UChar32>::syntax_options();
548 boost::u32regex r;
549 #ifndef BOOST_NO_EXCEPTIONS
550 try
551 #endif
552 {
553 #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__)
554 r.assign(expression.begin(), expression.end(), syntax_options);
555 #else
556 if(expression.size())
557 r.assign(&*expression.begin(), expression.size(), syntax_options);
558 else
559 r.assign(static_cast<UChar32 const*>(0), static_cast<boost::u32regex::size_type>(0), syntax_options);
560 #endif
561 if(r.status())
562 {
563 BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done, error code = " << r.status(), UChar32);
564 }
565 typedef std::vector<UChar32> string_type;
566 string_type search_text;
567 boost::regex_constants::match_flag_type opts = test_info<UChar32>::match_options();
568 string_type format_string;
569 string_type result_string;
570 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
571 search_text.assign(test_info<UChar32>::search_text().begin(), test_info<UChar32>::search_text().end());
572 format_string.assign(test_info<UChar32>::format_string().begin(), test_info<UChar32>::format_string().end());
573 format_string.push_back(0);
574 result_string.assign(test_info<UChar32>::result_string().begin(), test_info<UChar32>::result_string().end());
575 #else
576 std::copy(test_info<UChar32>::search_text().begin(), test_info<UChar32>::search_text().end(), std::back_inserter(search_text));
577 std::copy(test_info<UChar32>::format_string().begin(), test_info<UChar32>::format_string().end(), std::back_inserter(format_string));
578 format_string.push_back(0);
579 std::copy(test_info<UChar32>::result_string().begin(), test_info<UChar32>::result_string().end(), std::back_inserter(result_string));
580 #endif
581 string_type result;
582
583 boost::u32regex_replace(unnecessary_fix::back_inserter(result), search_text.begin(), search_text.end(), r, &*format_string.begin(), opts);
584 if(result != result_string)
585 {
586 BOOST_REGEX_TEST_ERROR("regex_replace generated an incorrect string result", UChar32);
587 }
588 //
589 // Mixed mode character encoding:
590 //
591 if(0 == *test_locale::c_str())
592 {
593 //
594 // Now try UTF-16 construction:
595 //
596 typedef boost::u32_to_u16_iterator<std::vector<UChar32>::const_iterator> u16_conv;
597 std::vector<UChar> expression16, text16, format16, result16, found16;
598 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
599 expression16.assign(u16_conv(expression.begin()), u16_conv(expression.end()));
600 text16.assign(u16_conv(search_text.begin()), u16_conv(search_text.end()));
601 format16.assign(u16_conv(format_string.begin()), u16_conv(format_string.end()));
602 result16.assign(u16_conv(result_string.begin()), u16_conv(result_string.end()));
603 #else
604 std::copy(u16_conv(expression.begin()), u16_conv(expression.end()), std::back_inserter(expression16));
605 std::copy(u16_conv(search_text.begin()), u16_conv(search_text.end()), std::back_inserter(text16));
606 std::copy(u16_conv(format_string.begin()), u16_conv(format_string.end()), std::back_inserter(format16));
607 std::copy(u16_conv(result_string.begin()), u16_conv(result_string.end()), std::back_inserter(result16));
608 #endif
609 r = boost::make_u32regex(expression16.begin(), expression16.end(), syntax_options);
610 boost::u32regex_replace(unnecessary_fix::back_inserter(found16), text16.begin(), text16.end(), r, &*format16.begin(), opts);
611 if(result16 != found16)
612 {
613 BOOST_REGEX_TEST_ERROR("u32regex_replace with UTF-16 string returned incorrect result", UChar32);
614 }
615 //
616 // Now with UnicodeString:
617 //
618 U_NAMESPACE_QUALIFIER UnicodeString expression16u, text16u, format16u, result16u, found16u;
619 if(expression16.size())
620 expression16u.setTo(&*expression16.begin(), expression16.size());
621 if(text16.size())
622 text16u.setTo(&*text16.begin(), text16.size());
623 format16u.setTo(&*format16.begin(), format16.size()-1);
624 if(result16.size())
625 result16u.setTo(&*result16.begin(), result16.size());
626 r = boost::make_u32regex(expression16.begin(), expression16.end(), syntax_options);
627 found16u = boost::u32regex_replace(text16u, r, format16u, opts);
628 if(result16u != found16u)
629 {
630 BOOST_REGEX_TEST_ERROR("u32regex_replace with UTF-16 string returned incorrect result", UChar32);
631 }
632
633 //
634 // Now try UTF-8 construction:
635 //
636 typedef boost::u32_to_u8_iterator<std::vector<UChar32>::const_iterator, unsigned char> u8_conv;
637 std::vector<char> expression8, text8, format8, result8, found8;
638 #ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
639 expression8.assign(u8_conv(expression.begin()), u8_conv(expression.end()));
640 text8.assign(u8_conv(search_text.begin()), u8_conv(search_text.end()));
641 format8.assign(u8_conv(format_string.begin()), u8_conv(format_string.end()));
642 result8.assign(u8_conv(result_string.begin()), u8_conv(result_string.end()));
643 #else
644 std::copy(u8_conv(expression.begin()), u8_conv(expression.end()), std::back_inserter(expression8));
645 std::copy(u8_conv(search_text.begin()), u8_conv(search_text.end()), std::back_inserter(text8));
646 std::copy(u8_conv(format_string.begin()), u8_conv(format_string.end()), std::back_inserter(format8));
647 std::copy(u8_conv(result_string.begin()), u8_conv(result_string.end()), std::back_inserter(result8));
648 #endif
649 r = boost::make_u32regex(expression8.begin(), expression8.end(), syntax_options);
650 boost::u32regex_replace(unnecessary_fix::back_inserter(found8), text8.begin(), text8.end(), r, &*format8.begin(), opts);
651 if(result8 != found8)
652 {
653 BOOST_REGEX_TEST_ERROR("u32regex_replace with UTF-8 string returned incorrect result", UChar32);
654 }
655 //
656 // Now with std::string and UTF-8:
657 //
658 std::string expression8s, text8s, format8s, result8s, found8s;
659 if(expression8.size())
660 expression8s.assign(&*expression8.begin(), expression8.size());
661 if(text8.size())
662 text8s.assign(&*text8.begin(), text8.size());
663 format8s.assign(&*format8.begin(), format8.size()-1);
664 if(result8.size())
665 result8s.assign(&*result8.begin(), result8.size());
666 r = boost::make_u32regex(expression8.begin(), expression8.end(), syntax_options);
667 found8s = boost::u32regex_replace(text8s, r, format8s, opts);
668 if(result8s != found8s)
669 {
670 BOOST_REGEX_TEST_ERROR("u32regex_replace with UTF-8 string returned incorrect result", UChar32);
671 }
672 }
673 }
674 #ifndef BOOST_NO_EXCEPTIONS
675 catch(const boost::bad_expression& e)
676 {
677 BOOST_REGEX_TEST_ERROR("Expression did not compile when it should have done: " << e.what(), UChar32);
678 }
679 catch(const std::runtime_error& e)
680 {
681 BOOST_REGEX_TEST_ERROR("Received an unexpected std::runtime_error: " << e.what(), UChar32);
682 }
683 catch(const std::exception& e)
684 {
685 BOOST_REGEX_TEST_ERROR("Received an unexpected std::exception: " << e.what(), UChar32);
686 }
687 catch(...)
688 {
689 BOOST_REGEX_TEST_ERROR("Received an unexpected exception of unknown type", UChar32);
690 }
691 #endif
692 }
693
694 #else
695
696 #include "test.hpp"
697
test_icu(const wchar_t &,const test_regex_search_tag &)698 void test_icu(const wchar_t&, const test_regex_search_tag&){}
test_icu(const wchar_t &,const test_invalid_regex_tag &)699 void test_icu(const wchar_t&, const test_invalid_regex_tag&){}
test_icu(const wchar_t &,const test_regex_replace_tag &)700 void test_icu(const wchar_t&, const test_regex_replace_tag&){}
701
702 #endif
703
704