mirror of
https://github.com/boostorg/regex.git
synced 2025-07-04 16:16:32 +02:00
751 lines
22 KiB
C++
751 lines
22 KiB
C++
/*
|
|
*
|
|
* Copyright (c) 1998-2000
|
|
* Dr John Maddock
|
|
*
|
|
* Permission to use, copy, modify, distribute and sell this software
|
|
* and its documentation for any purpose is hereby granted without fee,
|
|
* provided that the above copyright notice appear in all copies and
|
|
* that both that copyright notice and this permission notice appear
|
|
* in supporting documentation. Dr John Maddock makes no representations
|
|
* about the suitability of this software for any purpose.
|
|
* It is provided "as is" without express or implied warranty.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
*
|
|
* FILE tests.cpp
|
|
* VERSION 3.03
|
|
*
|
|
* the actual tests conducted by regress.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <boost/regex.hpp>
|
|
#include "regress.h"
|
|
|
|
using namespace boost;
|
|
|
|
template <class M1, class M2>
|
|
bool compare_result(const M1& sm, const M2& m)
|
|
{
|
|
if(sm.size() != m.size())
|
|
return false;
|
|
if(sm.line() != m.line())
|
|
return false;
|
|
for(unsigned int i = 0; i < sm.size(); ++i)
|
|
{
|
|
if(sm.position(i) != m.position(i))
|
|
return false;
|
|
if(sm.length(i) != m.length(i))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <class M1>
|
|
bool compare_result(const M1& sm, const M1& m)
|
|
{
|
|
return sm == m;
|
|
}
|
|
|
|
|
|
template <class C, class T, class A>
|
|
void cpp_eh_tests(const reg_expression<C, T, A>& )
|
|
{
|
|
#ifndef __GNUC__
|
|
bool thrown = false;
|
|
// try set_expression form first:
|
|
try
|
|
{
|
|
A a;
|
|
reg_expression<C, T, A> e(a);
|
|
e.set_expression(expression.c_str(), flags[2] | regbase::use_except);
|
|
}
|
|
catch(const boost::bad_expression&)
|
|
{
|
|
thrown = true;
|
|
}
|
|
catch(...){}
|
|
if(!thrown)
|
|
{
|
|
begin_error();
|
|
cout << "Error: expected exception not thrown" << endl;
|
|
}
|
|
|
|
// now try constructor form:
|
|
thrown = false;
|
|
try
|
|
{
|
|
A a;
|
|
reg_expression<C, T, A> e(expression.c_str(), flags[2] | regbase::use_except, a);
|
|
}
|
|
catch(const boost::bad_expression&)
|
|
{
|
|
thrown = true;
|
|
}
|
|
catch(...){}
|
|
if(!thrown)
|
|
{
|
|
begin_error();
|
|
cout << "Error: expected exception not thrown" << endl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
template <class iterator>
|
|
iterator find_last_line(iterator start, iterator end)
|
|
{
|
|
iterator result = start;
|
|
while(start != end)
|
|
{
|
|
if(*start == '\n')
|
|
{
|
|
++start;
|
|
result = start;
|
|
}
|
|
else
|
|
++start;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <class iterator>
|
|
unsigned int count_lines(iterator start, iterator end)
|
|
{
|
|
unsigned int result = 0;
|
|
while(start != end)
|
|
{
|
|
if(*start == '\n')
|
|
++result;
|
|
++start;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <class iterator, class Alloc>
|
|
class grep_test_predicate
|
|
{
|
|
int match_id;
|
|
iterator base, term;
|
|
public:
|
|
grep_test_predicate(iterator i, iterator j) : base(i), term(j) { match_id = 0; }
|
|
~grep_test_predicate(){}
|
|
bool operator()(const boost::match_results< iterator, Alloc >& m);
|
|
};
|
|
|
|
template <class iterator, class Alloc>
|
|
bool grep_test_predicate<iterator, Alloc>::operator()(const boost::match_results< iterator, Alloc >& m)
|
|
{
|
|
int start, end;
|
|
start = m[0].first - base;
|
|
end = m[0].second - base;
|
|
if((matches[match_id] != start) || (matches[match_id + 1] != end))
|
|
{
|
|
begin_error();
|
|
cout << "regex++ grep match error: found [" << start << "," << end << "] expected [" << matches[match_id] << "," << matches[match_id+1] << "]" << endl;
|
|
}
|
|
|
|
//
|
|
// check $`:
|
|
start = m[-1].first - base;
|
|
end = m[-1].second - base;
|
|
if(match_id &&
|
|
( (end != matches[match_id]) || (start != matches[match_id - 1]) )
|
|
)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ grep error in $`: found [" << start << "," << end << "] expected [" << matches[match_id-1] << "," << matches[match_id] << "]" << endl;
|
|
}
|
|
else if((!match_id) && ((start != 0) || (end != matches[0])))
|
|
{
|
|
begin_error();
|
|
cout << "regex++ grep error in $`: found [" << start << "," << end << "] expected [" << 0 << "," << matches[0] << "]" << endl;
|
|
}
|
|
|
|
//
|
|
// check $':
|
|
start = m[-2].first - base;
|
|
end = m[-2].second - base;
|
|
if((start != matches[match_id + 1]) || (end != (term-base)))
|
|
{
|
|
begin_error();
|
|
cout << "regex++ grep error in $': found [" << start << "," << end << "] expected [" << matches[match_id + 1] << "," << (term-base) << "]" << endl;
|
|
}
|
|
|
|
//
|
|
// now check line()
|
|
start = m.line();
|
|
end = count_lines(base, iterator(m[0].first)) + 1;
|
|
if(start != end)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ grep error in line(): found " << start << " expected " << end << endl;
|
|
}
|
|
|
|
//
|
|
// now check line_start()
|
|
start = m.line_start() - base;
|
|
end = find_last_line(base, iterator(m[0].first)) - base;
|
|
if(start != end)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ grep error in line_start(): found " << start << " expected " << end << endl;
|
|
}
|
|
|
|
match_id += 2;
|
|
return true;
|
|
}
|
|
|
|
template <class C, class T, class A>
|
|
void cpp_tests(const reg_expression<C, T, A>& e, bool recurse = true)
|
|
{
|
|
typedef typename reg_expression<C, T, A>::allocator_type allocator_type;
|
|
if(flags[4] & REG_MERGE)
|
|
{
|
|
//
|
|
// test merge code:
|
|
//
|
|
string_type s;
|
|
s = regex_merge(search_text, e, format_string.c_str(), flags[3]);
|
|
if(s != merge_string)
|
|
{
|
|
begin_error();
|
|
cout << "merge result mismatch: found \"" << s.c_str() << "\" expected \"" << merge_string.c_str() << "\"" << endl;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
if(recurse)
|
|
{
|
|
// copy and assign test:
|
|
reg_expression<C, T, A> e2(e);
|
|
cpp_tests(e2, false);
|
|
e2 = e;
|
|
cpp_tests(e2, false);
|
|
}
|
|
|
|
if(e.error_code())
|
|
{
|
|
// verify that we don't expect expression to compile
|
|
if(search_text != BOOST_RE_STR("!"))
|
|
{
|
|
begin_error();
|
|
cout << "Expression did not compile using regex++ API" << endl;
|
|
}
|
|
else if((recurse) && ((flags[3] & match_partial) == 0))
|
|
cpp_eh_tests(e);
|
|
}
|
|
else if(flags[4] & REG_GREP)
|
|
{
|
|
// try to do grep:
|
|
debug_iterator<string_type::iterator> x(search_text.begin(), search_text.begin(), search_text.end());
|
|
debug_iterator<string_type::iterator> y(search_text.end(), search_text.begin(), search_text.end());
|
|
grep_test_predicate<debug_iterator<string_type::iterator>, allocator_type> oi(x, y);
|
|
regex_grep(oi, x, y, e, flags[3]);
|
|
#if !defined(BOOST_RE_NO_PARTIAL_FUNC_SPEC) && !defined(BOOST_RE_NO_STRING_H) && !defined(BOOST_RE_NO_STRING_DEF_ARGS)
|
|
if(!recurse)
|
|
{
|
|
std::basic_string<char_t> s(search_text.begin(), search_text.end());
|
|
grep_test_predicate<std::basic_string<char_t>::const_iterator, allocator_type> oi2(s.begin(), s.end());
|
|
regex_grep(oi2, s, e, flags[3]);
|
|
grep_test_predicate<const char_t*, allocator_type> oi3(s.c_str(), s.c_str()+s.size());
|
|
regex_grep(oi3, s.c_str(), e, flags[3]);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// try to find match
|
|
match_results< debug_iterator<string_type::iterator>, allocator_type> m;
|
|
debug_iterator<string_type::iterator> x(search_text.begin(), search_text.begin(), search_text.end());
|
|
debug_iterator<string_type::iterator> y(search_text.end(), search_text.begin(), search_text.end());
|
|
if(regex_search(x, y, m, e, flags[3]))
|
|
{
|
|
// match found compare what matched with what we expect:
|
|
int j = 0;
|
|
for(unsigned int i = 0; i < m.size(); ++i, j += 2)
|
|
{
|
|
if(m[i].matched == false)
|
|
{
|
|
if(matches[j] != -1)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in sub-expression " << i <<
|
|
", found (" << (m[i].first - x) << "," <<
|
|
(m[i].second - x) << ") expected (" <<
|
|
matches[j] << "," << matches[j+1] << ")" << endl;
|
|
}
|
|
}
|
|
else if(((m[i].first - x) != matches[j]) || ((m[i].second - x) != matches[j+1]))
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in sub-expression " << i <<
|
|
", found (" << (m[i].first - x) << "," <<
|
|
(m[i].second - x) << ") expected (" <<
|
|
matches[j] << "," << matches[j+1] << ")" << endl;
|
|
}
|
|
}
|
|
//
|
|
// now check $` and $':
|
|
//
|
|
if((m[-1].first != x) || (m[-1].second != m[0].first))
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in $` (match -1), found (" <<
|
|
(m[-1].first - x) << "," << (m[-1].second - x) << ") expected (0" <<
|
|
"," << matches[0] << ")" << endl;
|
|
}
|
|
if(((flags[3] & match_partial) == 0) && ((m[-2].first != m[0].second) || (m[-2].second != y)))
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in $' (match -2), found (" <<
|
|
(m[-2].first - x) << "," << (m[-2].second - x) << ") expected (" <<
|
|
matches[1] << "," << (y-x) << ")" << endl;
|
|
}
|
|
|
|
//
|
|
// now try alternative forms of regex_search if available:
|
|
#if !defined(BOOST_RE_NO_PARTIAL_FUNC_SPEC) && !defined(BOOST_RE_NO_STRING_H) && !defined(BOOST_RE_NO_STRING_DEF_ARGS)
|
|
if(!recurse)
|
|
{
|
|
std::basic_string<char_t> s(search_text.begin(), search_text.end());
|
|
match_results<std::basic_string<char_t>::const_iterator> sm;
|
|
if(regex_search(s, sm, e, flags[3]))
|
|
{
|
|
if(compare_result(sm, m) == false)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_search(const std::string&, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_search(const std::string&, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
//
|
|
// partial match should give same result as full match
|
|
// provided a full match is expected:
|
|
//
|
|
if(matches[0] > 0)
|
|
{
|
|
if(regex_search(x, y, m, e, flags[3] | boost::match_partial))
|
|
{
|
|
if(compare_result(sm, m) == false)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_search when enabling match_partial" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result: match not found when match_partial specified" << endl;
|
|
}
|
|
}
|
|
if(s.find(char_t(0)) == std::basic_string<char_t>::npos)
|
|
{
|
|
match_results<const char_t*> ssm;
|
|
if(regex_search(search_text.c_str(), ssm, e, flags[3]))
|
|
{
|
|
if(compare_result(ssm, m) == false)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_search(const char_t*, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_search(const char_t*, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
}
|
|
if((false == recurse) && (matches[0] == 0) && (matches[1] == search_text.size()))
|
|
{
|
|
//
|
|
// match expected on whole string, so all versions
|
|
// of regex_match should also succeed:
|
|
//
|
|
match_results< debug_iterator<string_type::iterator>, allocator_type> m1;
|
|
debug_iterator<string_type::iterator> x1(search_text.begin(), search_text.begin(), search_text.end());
|
|
debug_iterator<string_type::iterator> y1(search_text.end(), search_text.begin(), search_text.end());
|
|
if(regex_match(x1, y1, m1, e, flags[3]))
|
|
{
|
|
if(compare_result(m1, m) == false)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_match(iterator, iterator, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_match(iterator, iterator, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
std::basic_string<char_t> s(search_text.begin(), search_text.end());
|
|
match_results<std::basic_string<char_t>::const_iterator> sm;
|
|
if(regex_match(s, sm, e, flags[3]))
|
|
{
|
|
if(compare_result(sm, m) == false)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_match(const std::string&, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_match(const std::string&, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
if(s.find(char_t(0)) == std::basic_string<char_t>::npos)
|
|
{
|
|
match_results<const char_t*> ssm;
|
|
if(regex_match(search_text.c_str(), ssm, e, flags[3]))
|
|
{
|
|
if(compare_result(ssm, m) == false)
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_match(const char_t*, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
begin_error();
|
|
cout << "regex++ API result mismatch in regex_match(const char_t*, match_results&, const reg_expression&, int)" << endl;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// match not found
|
|
if(matches[0] != -1)
|
|
{
|
|
begin_error();
|
|
cout << "Match expected but not found using regex++ API" << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !defined(TEST_UNICODE)
|
|
|
|
unsigned int hl_match_id;
|
|
|
|
bool hl_grep_test_proc(const RegEx& e)
|
|
{
|
|
int start, end;
|
|
start = e.Position(0);
|
|
end = start + e.Length();
|
|
if((matches[hl_match_id] != start) || (matches[hl_match_id + 1] != end))
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep match error: found [" << start << "," << end << "] expected [" << matches[hl_match_id] << "," << matches[hl_match_id+1] << "]" << endl;
|
|
}
|
|
|
|
//
|
|
// check $`:
|
|
start = e.Position(-1);
|
|
end = start + e.Length(-1);
|
|
if(start == -1)
|
|
{
|
|
if(hl_match_id &&
|
|
( matches[hl_match_id] != matches[hl_match_id - 1] )
|
|
)
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << matches[hl_match_id-1] << "," << matches[hl_match_id] << "]" << endl;
|
|
}
|
|
else if((!hl_match_id) && (0 != matches[0]))
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << 0 << "," << matches[0] << "]" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(hl_match_id &&
|
|
( (end != matches[hl_match_id]) || (start != matches[hl_match_id - 1]) )
|
|
)
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << matches[hl_match_id-1] << "," << matches[hl_match_id] << "]" << endl;
|
|
}
|
|
else if((!hl_match_id) && ((start != 0) || (end != matches[0])))
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep error in $`: found [" << start << "," << end << "] expected [" << 0 << "," << matches[0] << "]" << endl;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check $':
|
|
start = e.Position(-2);
|
|
end = start + e.Length(-2);
|
|
if(start == -1)
|
|
{
|
|
if(matches[hl_match_id + 1] != search_text.size())
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep error in $': found [" << start << "," << end << "] expected [" << matches[hl_match_id + 1] << "," << (search_text.size()) << "]" << endl;
|
|
}
|
|
}
|
|
else if((start != matches[hl_match_id + 1]) || (end != search_text.size()))
|
|
{
|
|
begin_error();
|
|
cout << "class RegEx grep error in $': found [" << start << "," << end << "] expected [" << matches[hl_match_id + 1] << "," << (search_text.size()) << "]" << endl;
|
|
}
|
|
|
|
hl_match_id += 2;
|
|
return true;
|
|
}
|
|
|
|
void cpp_hl_tests(RegEx& e, bool recurse = true)
|
|
{
|
|
if(flags[4] & REG_MERGE)
|
|
return;
|
|
|
|
if(recurse)
|
|
{
|
|
// copy and assign test:
|
|
RegEx e2(e);
|
|
cpp_hl_tests(e2, false);
|
|
e2 = e;
|
|
cpp_hl_tests(e2, false);
|
|
}
|
|
|
|
if(flags[4] & REG_GREP)
|
|
{
|
|
// try to do grep:
|
|
hl_match_id = 0;
|
|
GrepCallback cb = hl_grep_test_proc;
|
|
e.Grep(cb, search_text.c_str(), flags[3]);
|
|
}
|
|
else
|
|
{
|
|
if(e.Search(search_text.c_str(), flags[3]))
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int j = 0;
|
|
while(matches[j] != -2)
|
|
{
|
|
if( (matches[j] != e.Position(i)) || (matches[j+1] - matches[j] != e.Length(i)) )
|
|
{
|
|
begin_error();
|
|
cout << "RegEx::Search error in subexpression " << i << ": found [" << e.Position(i) << "," << (e.Position(i) + e.Length(i)) << "] expected [" << matches[j] << "," << matches[j+1] << "]" << endl;
|
|
}
|
|
++i;
|
|
j += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(matches[0] != -1)
|
|
{
|
|
begin_error();
|
|
cout << "match expected but not found with RexEx::Search" << endl;
|
|
}
|
|
}
|
|
|
|
if((matches[0] == 0) && (e.Match(search_text.c_str(), flags[3])))
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int j = 0;
|
|
while(matches[j] != -2)
|
|
{
|
|
if( (matches[j] != e.Position(i)) || (matches[j+1] - matches[j] != e.Length(i)) )
|
|
{
|
|
begin_error();
|
|
cout << "RegEx::Match error in subexpression " << i << ": found [" << e.Position(i) << "," << (e.Position(i) + e.Length(i)) << "] expected [" << matches[j] << "," << matches[j+1] << "]" << endl;
|
|
}
|
|
++i;
|
|
j += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
template <class iterator>
|
|
bool has_nulls(iterator i, iterator j)
|
|
{
|
|
while(i != j)
|
|
{
|
|
if(*i == 0)
|
|
return true;
|
|
++i;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#ifdef TEST_UNICODE
|
|
#undef regcomp
|
|
#undef regerror
|
|
#undef regexec
|
|
#undef regfree
|
|
#undef regex_t
|
|
#define regcomp regcompW
|
|
#define regerror regerrorW
|
|
#define regexec regexecW
|
|
#define regfree regfreeW
|
|
#define regex_t regex_tW
|
|
#endif
|
|
|
|
|
|
void run_tests()
|
|
{
|
|
#ifndef TEST_UNICODE
|
|
if(flags[4] & REG_UNICODE_ONLY)
|
|
return;
|
|
#endif
|
|
#ifndef NO_CPP_TEST
|
|
try
|
|
{
|
|
unsigned int f = flags[2] & ~regbase::use_except;
|
|
if(flags[0] & REG_ICASE)
|
|
f |= regbase::icase;
|
|
re_type e(expression.c_str(), f);
|
|
cpp_tests(e, true);
|
|
}
|
|
#ifndef BOOST_RE_NO_EXCEPTION_H
|
|
catch(const std::exception& e)
|
|
{
|
|
//
|
|
// this is only an error if the expression is expected to be valid:
|
|
if(search_text != BOOST_RE_STR("!"))
|
|
{
|
|
begin_error();
|
|
cout << "Unexpected exception thrown from C++ library: " << e.what() << endl;
|
|
}
|
|
}
|
|
#endif
|
|
catch(...)
|
|
{
|
|
begin_error();
|
|
cout << "Unexpected exception thrown from C++ library" << endl;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(TEST_UNICODE)
|
|
try
|
|
{
|
|
if(((flags[3] & match_partial) == 0) && (flags[2] == regbase::normal) && (has_nulls(search_text.begin(), search_text.end()) == false))
|
|
{
|
|
RegEx e;
|
|
e.SetExpression(expression.c_str(), flags[0] & REG_ICASE);
|
|
cpp_hl_tests(e, true);
|
|
}
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
if(search_text != BOOST_RE_STR("!"))
|
|
{
|
|
begin_error();
|
|
cout << "Expression did not compile with class RegEx" << endl;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
begin_error();
|
|
cout << "Unexpected exception thrown from RegEx::SetExpression" << endl;
|
|
}
|
|
#endif
|
|
|
|
if(flags[4] & (REG_NO_POSIX_TEST | REG_GREP | REG_MERGE | REG_MERGE_COPY))
|
|
return;
|
|
regex_t posix_expression;
|
|
regmatch_t m[MAX_MATCHES];
|
|
if(regcomp(&posix_expression, expression.c_str(), flags[0]) == 0)
|
|
{
|
|
if(flags[1] & REG_STARTEND)
|
|
{
|
|
m[0].rm_so = 0;
|
|
m[0].rm_eo = search_text.size();
|
|
}
|
|
if(regexec(&posix_expression, search_text.c_str(), MAX_MATCHES, m, flags[1]))
|
|
{
|
|
// match not found
|
|
if(matches[0] != -1)
|
|
{
|
|
begin_error();
|
|
cout << "Match expected but not found using POSIX API" << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// match found compare what matched with what we expect:
|
|
int j = 0;
|
|
for(unsigned int i = 0; i <= posix_expression.re_nsub; ++i, j += 2)
|
|
{
|
|
if((m[i].rm_so != matches[j]) || (m[i].rm_eo != matches[j+1]))
|
|
{
|
|
begin_error();
|
|
cout << "POSIX API result mismatch in sub-expression " << i << ", found (" << m[i].rm_so << "," << m[i].rm_eo <<
|
|
") expected (" << matches[j] << "," << matches[j+1] << ")" << endl;
|
|
}
|
|
}
|
|
}
|
|
regfree(&posix_expression);
|
|
}
|
|
else
|
|
{
|
|
// expression did not compile
|
|
if(search_text != BOOST_RE_STR("!"))
|
|
{
|
|
begin_error();
|
|
cout << "Expression did not compile using POSIX API" << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// error reporting:
|
|
int last_line = 0;
|
|
|
|
void begin_error()
|
|
{
|
|
if(line != last_line)
|
|
{
|
|
cout << "Error in line " << line << " of file " << file << endl;
|
|
cout << "Expression: " << expression.c_str() << endl;
|
|
cout << "Search text: " << search_text.c_str() << endl;
|
|
cout << "Flags: ";
|
|
bool started = false;
|
|
unsigned int id = 0;
|
|
while(flag_data[id].len != 0)
|
|
{
|
|
if(flags[flag_data[id].id] & flag_data[id].value)
|
|
{
|
|
if(started)
|
|
cout << " | ";
|
|
cout << flag_data[id].name;
|
|
started = true;
|
|
}
|
|
++id;
|
|
}
|
|
cout << endl;
|
|
last_line = line;
|
|
++error_count;
|
|
}
|
|
}
|
|
|
|
void reset_error()
|
|
{
|
|
last_line = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|