mirror of
https://github.com/boostorg/regex.git
synced 2025-07-25 10:07:23 +02:00
1) Disabled recursive implementation for VC8: stack overflows can't be reliably detected unless the whole program is compiled with asynchronous exceptions.
2) Changed std::copy calls on VC8 to avoid "dangerous code" warnings. 3) Moved backreference and octal escape code into line with POSIX-extended requirements. 4) Changed match_results leftmost-longest rules to stop unnecessary std::distance computations (an optimisation for non-random access iterators). 5) Changed C lib calls to use "safe" versions of string API's where available. 6) Added many new POSIX-extended leftmost-longest tests, to verify the above. [SVN r27880]
This commit is contained in:
@ -319,7 +319,7 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page();
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE)
|
||||
# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG)
|
||||
# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(BOOST_MSVC) && (BOOST_MSVC >= 1400))
|
||||
# define BOOST_REGEX_RECURSIVE
|
||||
# else
|
||||
# define BOOST_REGEX_NON_RECURSIVE
|
||||
|
@ -728,7 +728,7 @@ OutputIterator do_regex_replace(OutputIterator out,
|
||||
if(i == j)
|
||||
{
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = std::copy(in.first, in.second, out);
|
||||
out = re_detail::copy(in.first, in.second, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -736,7 +736,7 @@ OutputIterator do_regex_replace(OutputIterator out,
|
||||
while(i != j)
|
||||
{
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = std::copy(i->prefix().first, i->prefix().second, out);
|
||||
out = re_detail::copy(i->prefix().first, i->prefix().second, out);
|
||||
out = ::boost::re_detail::regex_format_imp(out, *i, &*f.begin(), &*f.end(), flags, e.get_traits());
|
||||
last_m = (*i)[0].second;
|
||||
if(flags & regex_constants::format_first_only)
|
||||
@ -744,7 +744,7 @@ OutputIterator do_regex_replace(OutputIterator out,
|
||||
++i;
|
||||
}
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = std::copy(last_m, in.second, out);
|
||||
out = re_detail::copy(last_m, in.second, out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -435,10 +435,10 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
|
||||
return 0;
|
||||
}
|
||||
charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) );
|
||||
std::copy(s1.begin(), s1.end(), p);
|
||||
re_detail::copy(s1.begin(), s1.end(), p);
|
||||
p[s1.size()] = charT(0);
|
||||
p += s1.size() + 1;
|
||||
std::copy(s2.begin(), s2.end(), p);
|
||||
re_detail::copy(s2.begin(), s2.end(), p);
|
||||
p[s2.size()] = charT(0);
|
||||
}
|
||||
//
|
||||
@ -459,7 +459,7 @@ re_syntax_base* basic_regex_creator<charT, traits>::append_set(
|
||||
if(s.empty())
|
||||
return 0; // invalid or unsupported equivalence class
|
||||
charT* p = static_cast<charT*>(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) );
|
||||
std::copy(s.begin(), s.end(), p);
|
||||
re_detail::copy(s.begin(), s.end(), p);
|
||||
p[s.size()] = charT(0);
|
||||
++first;
|
||||
}
|
||||
@ -620,7 +620,7 @@ void basic_regex_creator<charT, traits>::finalize(const charT* p1, const charT*
|
||||
m_pdata->m_expression_len = len;
|
||||
charT* ps = static_cast<charT*>(m_pdata->m_data.extend(sizeof(charT) * (1 + (p2 - p1))));
|
||||
m_pdata->m_expression = ps;
|
||||
std::copy(p1, p2, ps);
|
||||
re_detail::copy(p1, p2, ps);
|
||||
ps[p2 - p1] = 0;
|
||||
// fill in our other data...
|
||||
// successful parsing implies a zero status:
|
||||
|
@ -1422,7 +1422,15 @@ charT basic_regex_parser<charT, traits>::unescape_character()
|
||||
// an octal escape sequence, the first character must be a zero
|
||||
// followed by up to 3 octal digits:
|
||||
std::ptrdiff_t len = (std::min)(::boost::re_detail::distance(m_position, m_end), static_cast<std::ptrdiff_t>(4));
|
||||
int val = this->m_traits.toi(m_position, m_position + len, 8);
|
||||
const charT* bp = m_position;
|
||||
int val = this->m_traits.toi(bp, bp + 1, 8);
|
||||
if(val != 0)
|
||||
{
|
||||
// Oops not an octal escape after all:
|
||||
fail(regex_constants::error_escape, m_position - m_base);
|
||||
return result;
|
||||
}
|
||||
val = this->m_traits.toi(m_position, m_position + len, 8);
|
||||
if(val < 0)
|
||||
{
|
||||
fail(regex_constants::error_escape, m_position - m_base);
|
||||
@ -1477,19 +1485,20 @@ template <class charT, class traits>
|
||||
bool basic_regex_parser<charT, traits>::parse_backref()
|
||||
{
|
||||
BOOST_ASSERT(m_position != m_end);
|
||||
int i = this->m_traits.toi(m_position, m_position + 1, 10);
|
||||
if((i > 0) && (this->m_backrefs & (1u << (i-1))))
|
||||
{
|
||||
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
|
||||
pb->index = i;
|
||||
}
|
||||
else if(i == 0)
|
||||
const charT* pc = m_position;
|
||||
int i = this->m_traits.toi(pc, pc + 1, 10);
|
||||
if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs)))
|
||||
{
|
||||
// not a backref at all but an octal escape sequence:
|
||||
--m_position;
|
||||
charT c = unescape_character();
|
||||
this->append_literal(c);
|
||||
}
|
||||
else if((i > 0) && (this->m_backrefs & (1u << (i-1))))
|
||||
{
|
||||
m_position = pc;
|
||||
re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
|
||||
pb->index = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
fail(regex_constants::error_backref, m_position - m_end);
|
||||
|
@ -300,29 +300,73 @@ void BOOST_REGEX_CALL match_results<BidiIterator, Allocator>::maybe_assign(const
|
||||
const_iterator p1, p2;
|
||||
p1 = begin();
|
||||
p2 = m.begin();
|
||||
BidiIterator base = (*this)[-1].first;
|
||||
std::size_t len1 = 0;
|
||||
std::size_t len2 = 0;
|
||||
std::size_t base1 = 0;
|
||||
std::size_t base2 = 0;
|
||||
//
|
||||
// Distances are measured from the start of *this* match, unless this isn't
|
||||
// a valid match in which case we use the start of the whole sequence. Note that
|
||||
// no subsequent match-candidate can ever be to the left of the first match found.
|
||||
// This ensures that when we are using bidirectional iterators, that distances
|
||||
// measured are as short as possible, and therefore as efficient as possible
|
||||
// to compute. Finally note that we don't use the "matched" data member to test
|
||||
// whether a sub-expression is a valid match, because partial matches set this
|
||||
// to false for sub-expression 0.
|
||||
//
|
||||
BidiIterator end = this->suffix().second;
|
||||
BidiIterator base = (p1->first == end) ? this->prefix().first : (*this)[0].first;
|
||||
difference_type len1 = 0;
|
||||
difference_type len2 = 0;
|
||||
difference_type base1 = 0;
|
||||
difference_type base2 = 0;
|
||||
std::size_t i;
|
||||
for(i = 0; i < size(); ++i)
|
||||
for(i = 0; i < size(); ++i, ++p1, ++p2)
|
||||
{
|
||||
//
|
||||
// leftmost takes priority over longest:
|
||||
// Leftmost takes priority over longest; handle special cases
|
||||
// where distances need not be computed first (an optimisation
|
||||
// for bidirectional iterators: ensure that we don't accidently
|
||||
// compute the length of the whole sequence, as this can be really
|
||||
// expensive).
|
||||
//
|
||||
if(p1->first == end)
|
||||
{
|
||||
if(p2->first != end)
|
||||
{
|
||||
// p2 must be better than p1, and no need to calculate
|
||||
// actual distances:
|
||||
base1 = 1;
|
||||
base2 = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// *p1 and *p2 are either unmatched or match end-of sequence,
|
||||
// either way no need to calculate distances:
|
||||
if((p1->matched == false) && (p2->matched == true))
|
||||
break;
|
||||
if((p1->matched == true) && (p2->matched == false))
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(p2->first == end)
|
||||
{
|
||||
// p1 better than p2, and no need to calculate distances:
|
||||
return;
|
||||
}
|
||||
base1 = ::boost::re_detail::distance(base, p1->first);
|
||||
base2 = ::boost::re_detail::distance(base, p2->first);
|
||||
BOOST_ASSERT(base1 >= 0);
|
||||
BOOST_ASSERT(base2 >= 0);
|
||||
if(base1 < base2) return;
|
||||
if(base2 < base1) break;
|
||||
|
||||
len1 = ::boost::re_detail::distance((BidiIterator)p1->first, (BidiIterator)p1->second);
|
||||
len2 = ::boost::re_detail::distance((BidiIterator)p2->first, (BidiIterator)p2->second);
|
||||
BOOST_ASSERT(len1 >= 0);
|
||||
BOOST_ASSERT(len2 >= 0);
|
||||
if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
|
||||
break;
|
||||
if((p1->matched == true) && (p2->matched == false))
|
||||
return;
|
||||
++p1;
|
||||
++p2;
|
||||
}
|
||||
if(i == size())
|
||||
return;
|
||||
|
@ -524,6 +524,9 @@ void basic_regex_formatter<OutputIterator, Results, traits>::put(const sub_match
|
||||
|
||||
template <class S>
|
||||
class string_out_iterator
|
||||
#ifndef BOOST_NO_STD_ITERATOR
|
||||
: public std::iterator<std::output_iterator_tag, typename S::value_type>
|
||||
#endif
|
||||
{
|
||||
S* out;
|
||||
public:
|
||||
@ -537,11 +540,13 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_STD_ITERATOR
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef typename S::value_type value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class OutputIterator, class Iterator, class Alloc, class charT, class traits>
|
||||
@ -554,7 +559,7 @@ OutputIterator regex_format_imp(OutputIterator out,
|
||||
{
|
||||
if(flags & regex_constants::format_literal)
|
||||
{
|
||||
return std::copy(p1, p2, out);
|
||||
return re_detail::copy(p1, p2, out);
|
||||
}
|
||||
|
||||
re_detail::basic_regex_formatter<
|
||||
|
@ -41,7 +41,7 @@ OutputIterator regex_replace(OutputIterator out,
|
||||
if(i == j)
|
||||
{
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = std::copy(first, last, out);
|
||||
out = re_detail::copy(first, last, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -49,7 +49,7 @@ OutputIterator regex_replace(OutputIterator out,
|
||||
while(i != j)
|
||||
{
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = std::copy(i->prefix().first, i->prefix().second, out);
|
||||
out = re_detail::copy(i->prefix().first, i->prefix().second, out);
|
||||
out = i->format(out, fmt, flags, e);
|
||||
last_m = (*i)[0].second;
|
||||
if(flags & regex_constants::format_first_only)
|
||||
@ -57,7 +57,7 @@ OutputIterator regex_replace(OutputIterator out,
|
||||
++i;
|
||||
}
|
||||
if(!(flags & regex_constants::format_no_copy))
|
||||
out = std::copy(last_m, last, out);
|
||||
out = re_detail::copy(last_m, last, out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1998-2004
|
||||
* Copyright (c) 1998-2005
|
||||
* John Maddock
|
||||
*
|
||||
* Use, modification and distribution are subject to the
|
||||
@ -43,6 +43,12 @@
|
||||
# include <locale>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_STDC_NAMESPACE)
|
||||
namespace std{
|
||||
using ::sprintf; using ::strcpy; using ::strcat; using ::strlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace re_detail{
|
||||
#ifdef BOOST_NO_STD_DISTANCE
|
||||
template <class T>
|
||||
@ -112,4 +118,73 @@ inline void pointer_construct(T* p, const T& t)
|
||||
}} // namespaces
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* helper function copy:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace boost{ namespace re_detail{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,>=1400)
|
||||
//
|
||||
// MSVC 8 will either emit warnings or else refuse to compile
|
||||
// code that makes perfectly legitimate use of std::copy, when
|
||||
// the OutputIterator type is a user-defined class (apparently all user
|
||||
// defined iterators are "unsafe"). This code works around that:
|
||||
//
|
||||
template<class InputIterator, class OutputIterator>
|
||||
inline OutputIterator copy(
|
||||
InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator dest
|
||||
)
|
||||
{
|
||||
return stdext::unchecked_copy(first, last, dest);
|
||||
}
|
||||
|
||||
// use safe versions of strcpy etc:
|
||||
using ::strcpy_s;
|
||||
using ::strcat_s;
|
||||
#else
|
||||
using std::copy;
|
||||
|
||||
inline std::size_t strcpy_s(
|
||||
char *strDestination,
|
||||
std::size_t sizeInBytes,
|
||||
const char *strSource
|
||||
)
|
||||
{
|
||||
if(std::strlen(strSource)+1 > sizeInBytes)
|
||||
return 1;
|
||||
std::strcpy(strDestination, strSource);
|
||||
return 0;
|
||||
}
|
||||
inline std::size_t strcat_s(
|
||||
char *strDestination,
|
||||
std::size_t sizeInBytes,
|
||||
const char *strSource
|
||||
)
|
||||
{
|
||||
if(std::strlen(strSource) + std::strlen(strDestination) + 1 > sizeInBytes)
|
||||
return 1;
|
||||
std::strcat(strDestination, strSource);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void overflow_error_if_not_zero(std::size_t i)
|
||||
{
|
||||
if(i)
|
||||
{
|
||||
std::overflow_error e("String buffer too small");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespaces
|
||||
#endif
|
||||
|
||||
#endif // include guard
|
||||
|
||||
|
@ -33,12 +33,6 @@ typedef boost::match_flag_type match_flag_type;
|
||||
#endif
|
||||
#include <cstdio>
|
||||
|
||||
#if defined(BOOST_NO_STDC_NAMESPACE)
|
||||
namespace std{
|
||||
using ::sprintf; using ::strcpy; using ::strcat;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
@ -342,17 +336,17 @@ void BuildFileList(std::list<std::string>* pl, const char* files, bool recurse)
|
||||
{
|
||||
// go through sub directories:
|
||||
char buf[MAX_PATH];
|
||||
std::strcpy(buf, start.root());
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(buf, MAX_PATH, start.root()));
|
||||
if(*buf == 0)
|
||||
{
|
||||
std::strcpy(buf, ".");
|
||||
std::strcat(buf, directory_iterator::separator());
|
||||
std::strcat(buf, "*");
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(buf, MAX_PATH, "."));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, directory_iterator::separator()));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, "*"));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::strcat(buf, directory_iterator::separator());
|
||||
std::strcat(buf, "*");
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, directory_iterator::separator()));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, "*"));
|
||||
}
|
||||
directory_iterator dstart(buf);
|
||||
directory_iterator dend;
|
||||
@ -365,7 +359,11 @@ void BuildFileList(std::list<std::string>* pl, const char* files, bool recurse)
|
||||
|
||||
while(dstart != dend)
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
(::sprintf_s)(buf, sizeof(buf), "%s%s%s", dstart.path(), directory_iterator::separator(), ptr);
|
||||
#else
|
||||
(std::sprintf)(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr);
|
||||
#endif
|
||||
BuildFileList(pl, buf, recurse);
|
||||
++dstart;
|
||||
}
|
||||
|
@ -23,11 +23,8 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#ifdef BOOST_REGEX_V3
|
||||
#include <boost/regex/v3/fileiter.hpp>
|
||||
#else
|
||||
#include <boost/regex/v4/fileiter.hpp>
|
||||
#endif
|
||||
#include <boost/regex/v4/regex_workaround.hpp>
|
||||
#include <boost/regex/pattern_except.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
@ -395,34 +392,24 @@ file_iterator::file_iterator(const char* wild)
|
||||
BOOST_REGEX_NOEH_ASSERT(_root)
|
||||
_path = new char[MAX_PATH];
|
||||
BOOST_REGEX_NOEH_ASSERT(_path)
|
||||
std::strcpy(_root, wild);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild));
|
||||
ptr = _root;
|
||||
while(*ptr)++ptr;
|
||||
while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
|
||||
#if 0
|
||||
*ptr = 0;
|
||||
std::strcpy(_path, _root);
|
||||
if(*_path == 0)
|
||||
std::strcpy(_path, ".");
|
||||
std::strcat(_path, _fi_sep);
|
||||
ptr = _path + std::strlen(_path);
|
||||
#else
|
||||
if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
|
||||
{
|
||||
_root[1]='\0';
|
||||
std::strcpy(_path, _root);
|
||||
ptr = _path + std::strlen(_path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr = 0;
|
||||
std::strcpy(_path, _root);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
|
||||
if(*_path == 0)
|
||||
std::strcpy(_path, ".");
|
||||
std::strcat(_path, _fi_sep);
|
||||
ptr = _path + std::strlen(_path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, "."));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcat_s(_path, MAX_PATH, _fi_sep));
|
||||
}
|
||||
#endif
|
||||
ptr = _path + std::strlen(_path);
|
||||
|
||||
ref = new file_iterator_ref();
|
||||
BOOST_REGEX_NOEH_ASSERT(ref)
|
||||
@ -436,7 +423,7 @@ file_iterator::file_iterator(const char* wild)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::strcpy(ptr, ref->_data.cFileName);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, (MAX_PATH - (ptr - _path)), ref->_data.cFileName));
|
||||
if(ref->_data.dwFileAttributes & _fi_dir)
|
||||
next();
|
||||
}
|
||||
@ -463,8 +450,8 @@ file_iterator::file_iterator(const file_iterator& other)
|
||||
BOOST_REGEX_NOEH_ASSERT(_root)
|
||||
_path = new char[MAX_PATH];
|
||||
BOOST_REGEX_NOEH_ASSERT(_path)
|
||||
std::strcpy(_root, other._root);
|
||||
std::strcpy(_path, other._path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
|
||||
ptr = _path + (other.ptr - other._path);
|
||||
ref = other.ref;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
@ -481,8 +468,8 @@ file_iterator::file_iterator(const file_iterator& other)
|
||||
|
||||
file_iterator& file_iterator::operator=(const file_iterator& other)
|
||||
{
|
||||
std::strcpy(_root, other._root);
|
||||
std::strcpy(_path, other._path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
|
||||
ptr = _path + (other.ptr - other._path);
|
||||
if(--(ref->count) == 0)
|
||||
{
|
||||
@ -536,7 +523,7 @@ void file_iterator::next()
|
||||
ptr = _path;
|
||||
}
|
||||
else
|
||||
std::strcpy(ptr, ref->_data.cFileName);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, MAX_PATH - (ptr - _path), ref->_data.cFileName));
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,34 +570,26 @@ directory_iterator::directory_iterator(const char* wild)
|
||||
BOOST_REGEX_NOEH_ASSERT(_root)
|
||||
_path = new char[MAX_PATH];
|
||||
BOOST_REGEX_NOEH_ASSERT(_path)
|
||||
std::strcpy(_root, wild);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild));
|
||||
ptr = _root;
|
||||
while(*ptr)++ptr;
|
||||
while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr;
|
||||
#if 0
|
||||
*ptr = 0;
|
||||
std::strcpy(_path, _root);
|
||||
if(*_path == 0)
|
||||
std::strcpy(_path, ".");
|
||||
std::strcat(_path, _fi_sep);
|
||||
ptr = _path + std::strlen(_path);
|
||||
#else
|
||||
|
||||
if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) )
|
||||
{
|
||||
_root[1]='\0';
|
||||
std::strcpy(_path, _root);
|
||||
ptr = _path + std::strlen(_path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr = 0;
|
||||
std::strcpy(_path, _root);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root));
|
||||
if(*_path == 0)
|
||||
std::strcpy(_path, ".");
|
||||
std::strcat(_path, _fi_sep);
|
||||
ptr = _path + std::strlen(_path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, "."));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcat_s(_path, MAX_PATH, _fi_sep));
|
||||
}
|
||||
#endif
|
||||
ptr = _path + std::strlen(_path);
|
||||
|
||||
ref = new file_iterator_ref();
|
||||
BOOST_REGEX_NOEH_ASSERT(ref)
|
||||
ref->count = 1;
|
||||
@ -622,7 +601,7 @@ directory_iterator::directory_iterator(const char* wild)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::strcpy(ptr, ref->_data.cFileName);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, MAX_PATH - (ptr - _path), ref->_data.cFileName));
|
||||
if(((ref->_data.dwFileAttributes & _fi_dir) == 0) || (std::strcmp(ref->_data.cFileName, ".") == 0) || (std::strcmp(ref->_data.cFileName, "..") == 0))
|
||||
next();
|
||||
}
|
||||
@ -661,8 +640,8 @@ directory_iterator::directory_iterator(const directory_iterator& other)
|
||||
BOOST_REGEX_NOEH_ASSERT(_root)
|
||||
_path = new char[MAX_PATH];
|
||||
BOOST_REGEX_NOEH_ASSERT(_path)
|
||||
std::strcpy(_root, other._root);
|
||||
std::strcpy(_path, other._path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
|
||||
ptr = _path + (other.ptr - other._path);
|
||||
ref = other.ref;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
@ -679,8 +658,8 @@ directory_iterator::directory_iterator(const directory_iterator& other)
|
||||
|
||||
directory_iterator& directory_iterator::operator=(const directory_iterator& other)
|
||||
{
|
||||
std::strcpy(_root, other._root);
|
||||
std::strcpy(_path, other._path);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root));
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path));
|
||||
ptr = _path + (other.ptr - other._path);
|
||||
if(--(ref->count) == 0)
|
||||
{
|
||||
@ -723,7 +702,7 @@ void directory_iterator::next()
|
||||
ptr = _path;
|
||||
}
|
||||
else
|
||||
std::strcpy(ptr, ref->_data.cFileName);
|
||||
re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, MAX_PATH - (ptr - _path), ref->_data.cFileName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA*
|
||||
{
|
||||
result = std::strlen(names[code]) + 1;
|
||||
if(buf_size >= result)
|
||||
std::strcpy(buf, names[code]);
|
||||
re_detail::strcpy_s(buf, buf_size, names[code]);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
@ -145,15 +145,23 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA*
|
||||
{
|
||||
if(std::strcmp(e->re_endp, names[i]) == 0)
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
(::sprintf_s)(localbuf, 5, "%d", i);
|
||||
#else
|
||||
(std::sprintf)(localbuf, "%d", i);
|
||||
#endif
|
||||
if(std::strlen(localbuf) < buf_size)
|
||||
std::strcpy(buf, localbuf);
|
||||
re_detail::strcpy_s(buf, buf_size, localbuf);
|
||||
return std::strlen(localbuf) + 1;
|
||||
}
|
||||
}
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
(::sprintf_s)(localbuf, 5, "%d", 0);
|
||||
#else
|
||||
(std::sprintf)(localbuf, "%d", 0);
|
||||
#endif
|
||||
if(std::strlen(localbuf) < buf_size)
|
||||
std::strcpy(buf, localbuf);
|
||||
re_detail::strcpy_s(buf, buf_size, localbuf);
|
||||
return std::strlen(localbuf) + 1;
|
||||
}
|
||||
if(code <= (int)REG_E_UNKNOWN)
|
||||
@ -168,7 +176,7 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA*
|
||||
std::size_t len = p.size();
|
||||
if(len < buf_size)
|
||||
{
|
||||
std::strcpy(buf, p.c_str());
|
||||
re_detail::strcpy_s(buf, buf_size, p.c_str());
|
||||
}
|
||||
return len + 1;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const
|
||||
id, // locale identifier
|
||||
LCMAP_SORTKEY, // mapping transformation type
|
||||
p1, // source string
|
||||
p2 - p1, // number of characters in source string
|
||||
static_cast<int>(p2 - p1), // number of characters in source string
|
||||
0, // destination buffer
|
||||
0 // size of destination buffer
|
||||
);
|
||||
@ -242,7 +242,7 @@ BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const
|
||||
id, // locale identifier
|
||||
LCMAP_SORTKEY, // mapping transformation type
|
||||
p1, // source string
|
||||
p2 - p1, // number of characters in source string
|
||||
static_cast<int>(p2 - p1), // number of characters in source string
|
||||
&*result.begin(), // destination buffer
|
||||
bytes // size of destination buffer
|
||||
);
|
||||
@ -262,7 +262,7 @@ BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const
|
||||
id, // locale identifier
|
||||
LCMAP_SORTKEY, // mapping transformation type
|
||||
p1, // source string
|
||||
p2 - p1, // number of characters in source string
|
||||
static_cast<int>(p2 - p1), // number of characters in source string
|
||||
0, // destination buffer
|
||||
0 // size of destination buffer
|
||||
);
|
||||
@ -273,7 +273,7 @@ BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const
|
||||
id, // locale identifier
|
||||
LCMAP_SORTKEY, // mapping transformation type
|
||||
p1, // source string
|
||||
p2 - p1, // number of characters in source string
|
||||
static_cast<int>(p2 - p1), // number of characters in source string
|
||||
reinterpret_cast<wchar_t*>(&*result.begin()), // destination buffer *of bytes*
|
||||
bytes // size of destination buffer
|
||||
);
|
||||
@ -295,7 +295,7 @@ BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transfor
|
||||
id, // locale identifier
|
||||
LCMAP_SORTKEY, // mapping transformation type
|
||||
(LPCWSTR)p1, // source string
|
||||
p2 - p1, // number of characters in source string
|
||||
static_cast<int>(p2 - p1), // number of characters in source string
|
||||
0, // destination buffer
|
||||
0 // size of destination buffer
|
||||
);
|
||||
@ -306,7 +306,7 @@ BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transfor
|
||||
id, // locale identifier
|
||||
LCMAP_SORTKEY, // mapping transformation type
|
||||
(LPCWSTR)p1, // source string
|
||||
p2 - p1, // number of characters in source string
|
||||
static_cast<int>(p2 - p1), // number of characters in source string
|
||||
reinterpret_cast<wchar_t*>(&*result.begin()), // destination buffer *of bytes*
|
||||
bytes // size of destination buffer
|
||||
);
|
||||
|
@ -139,7 +139,11 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW*
|
||||
{
|
||||
result = std::wcslen(wnames[code]) + 1;
|
||||
if(buf_size >= result)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
::wcscpy_s(buf, buf_size, wnames[code]);
|
||||
#else
|
||||
std::wcscpy(buf, wnames[code]);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
@ -156,13 +160,21 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW*
|
||||
{
|
||||
(std::swprintf)(localbuf, 5, L"%d", i);
|
||||
if(std::wcslen(localbuf) < buf_size)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
::wcscpy_s(buf, buf_size, localbuf);
|
||||
#else
|
||||
std::wcscpy(buf, localbuf);
|
||||
#endif
|
||||
return std::wcslen(localbuf) + 1;
|
||||
}
|
||||
}
|
||||
(std::swprintf)(localbuf, 5, L"%d", 0);
|
||||
if(std::wcslen(localbuf) < buf_size)
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
::wcscpy_s(buf, buf_size, localbuf);
|
||||
#else
|
||||
std::wcscpy(buf, localbuf);
|
||||
#endif
|
||||
return std::wcslen(localbuf) + 1;
|
||||
}
|
||||
#endif
|
||||
@ -178,7 +190,7 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW*
|
||||
std::size_t len = p.size();
|
||||
if(len < buf_size)
|
||||
{
|
||||
std::copy(p.c_str(), p.c_str() + p.size() + 1, buf);
|
||||
re_detail::copy(p.c_str(), p.c_str() + p.size() + 1, buf);
|
||||
}
|
||||
return len + 1;
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ int cpp_main(int /*argc*/, char * /*argv*/[])
|
||||
test_character_escapes();
|
||||
test_assertion_escapes();
|
||||
test_tricky_cases();
|
||||
test_tricky_cases2();
|
||||
test_grep();
|
||||
test_replace();
|
||||
test_non_greedy_repeats();
|
||||
|
@ -38,6 +38,22 @@ void test_backrefs()
|
||||
TEST_REGEX_SEARCH("(a)\\1bc*d", perl, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a)\\1bc*[ce]d", perl, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("^(a)\\1b(c)*cd$", perl, "aabcccd", match_default, make_array(0, 7, 0, 1, 4, 5, -2, -2));
|
||||
TEST_REGEX_SEARCH("(ab*)[ab]*\\1", extended, "ababaaa", match_default, make_array(0, 7, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a\\(b*\\)c\\1d", basic, "abbcbbd", match_default, make_array(0, 7, 1, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a\\(b*\\)c\\1d", basic, "abbcbd", match_default, make_array(-2, -2));
|
||||
TEST_REGEX_SEARCH("a\\(b*\\)c\\1d", basic, "abbcbbbd", match_default, make_array(-2, -2));
|
||||
TEST_REGEX_SEARCH("^\\(.\\)\\1", basic, "abc", match_default, make_array(-2, -2));
|
||||
TEST_REGEX_SEARCH("a\\([bc]\\)\\1d", basic, "abcdabbd", match_default, make_array(4, 8, 5, 6, -2, -2));
|
||||
// strictly speaking this is at best ambiguous, at worst wrong, this is what most
|
||||
// re implimentations will match though.
|
||||
TEST_REGEX_SEARCH("a\\(\\([bc]\\)\\2\\)*d", basic, "abbccd", match_default, make_array(0, 6, 3, 5, 3, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("a\\(\\([bc]\\)\\2\\)*d", basic, "abbcbd", match_default, make_array(-2, -2));
|
||||
TEST_REGEX_SEARCH("a\\(\\(b\\)*\\2\\)*d", basic, "abbbd", match_default, make_array(0, 5, 1, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\(a\\)\\1bcd", basic, "aabcd", match_default, make_array(0, 5, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\(a\\)\\1bc*d", basic, "aabcd", match_default, make_array(0, 5, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\(a\\)\\1bc*d", basic, "aabd", match_default, make_array(0, 4, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\(a\\)\\1bc*d", basic, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\(a\\)\\1bc*[ce]d", basic, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("^\\(a\\)\\1b\\(c\\)*cd$", basic, "aabcccd", match_default, make_array(0, 7, 0, 1, 4, 5, -2, -2));
|
||||
TEST_REGEX_SEARCH("\\(ab*\\)[ab]*\\1", basic, "ababaaa", match_default, make_array(0, 7, 0, 1, -2, -2));
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "test.hpp"
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)\
|
||||
&& !BOOST_WORKAROUND(BOOST_MSVC, == 1400)\
|
||||
&& !BOOST_WORKAROUND(__HP_aCC, BOOST_TESTED_AT(55500))\
|
||||
&& !(defined(__GNUC__) && (__GNUC__ < 3) && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)))
|
||||
|
||||
|
@ -15,6 +15,9 @@
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
|
||||
void test_tricky_cases2();
|
||||
void test_tricky_cases3();
|
||||
|
||||
void test_tricky_cases()
|
||||
{
|
||||
using namespace boost::regex_constants;
|
||||
@ -98,6 +101,92 @@ void test_tricky_cases()
|
||||
TEST_REGEX_SEARCH("a(b|c){2,4}d", perl, "abcbcd", match_default, make_array(0, 6, 4, 5, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,}d", perl, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,}d", perl, "abcbd", match_default, make_array(0, 5, 3, 4, -2, -2));
|
||||
|
||||
test_tricky_cases2();
|
||||
test_tricky_cases3();
|
||||
}
|
||||
|
||||
void test_tricky_cases2()
|
||||
{
|
||||
using namespace boost::regex_constants;
|
||||
|
||||
TEST_REGEX_SEARCH("a(((b)))c", extended, "abc", match_default, make_array(0, 3, 1, 2, 1, 2, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|(c))d", extended, "abd", match_default, make_array(0, 3, 1, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|(c))d", extended, "acd", match_default, make_array(0, 3, 1, 2, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b*|c)d", extended, "abbd", match_default, make_array(0, 4, 1, 3, -2, -2));
|
||||
// just gotta have one DFA-buster, of course
|
||||
TEST_REGEX_SEARCH("a[ab]{20}", extended, "aaaaabaaaabaaaabaaaab", match_default, make_array(0, 21, -2, -2));
|
||||
// and an inline expansion in case somebody gets tricky
|
||||
TEST_REGEX_SEARCH("a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab]", extended, "aaaaabaaaabaaaabaaaab", match_default, make_array(0, 21, -2, -2));
|
||||
// and in case somebody just slips in an NFA...
|
||||
TEST_REGEX_SEARCH("a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night)", extended, "aaaaabaaaabaaaabaaaabweeknights", match_default, make_array(0, 31, 21, 24, 24, 31, -2, -2));
|
||||
// one really big one
|
||||
TEST_REGEX_SEARCH("1234567890123456789012345678901234567890123456789012345678901234567890", extended, "a1234567890123456789012345678901234567890123456789012345678901234567890b", match_default, make_array(1, 71, -2, -2));
|
||||
// fish for problems as brackets go past 8
|
||||
TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn]", extended, "xacegikmoq", match_default, make_array(1, 8, -2, -2));
|
||||
TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn][op]", extended, "xacegikmoq", match_default, make_array(1, 9, -2, -2));
|
||||
TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn][op][qr]", extended, "xacegikmoqy", match_default, make_array(1, 10, -2, -2));
|
||||
TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn][op][q]", extended, "xacegikmoqy", match_default, make_array(1, 10, -2, -2));
|
||||
// and as parenthesis go past 9:
|
||||
TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)", extended, "zabcdefghi", match_default, make_array(1, 9, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)(i)", extended, "zabcdefghij", match_default, make_array(1, 10, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)", extended, "zabcdefghijk", match_default, make_array(1, 11, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)", extended, "zabcdefghijkl", match_default, make_array(1, 12, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a)d|(b)c", extended, "abc", match_default, make_array(1, 3, -1, -1, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("_+((www)|(ftp)|(mailto)):_*", extended, "_wwwnocolon _mailto:", match_default, make_array(12, 20, 13, 19, -1, -1, -1, -1, 13, 19, -2, -2));
|
||||
// subtleties of matching
|
||||
TEST_REGEX_SEARCH("a\\(b\\)\\?c\\1d", basic|bk_plus_qm, "acd", match_default, make_array(0, 3, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b?c)+d", extended, "accd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("(wee|week)(knights|night)", extended, "weeknights", match_default, make_array(0, 10, 0, 3, 3, 10, -2, -2));
|
||||
TEST_REGEX_SEARCH(".*", extended, "abc", match_default, make_array(0, 3, -2, 3, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|(c))d", extended, "abd", match_default, make_array(0, 3, 1, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|(c))d", extended, "acd", match_default, make_array(0, 3, 1, 2, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b*|c|e)d", extended, "abbd", match_default, make_array(0, 4, 1, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b*|c|e)d", extended, "acd", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b*|c|e)d", extended, "ad", match_default, make_array(0, 2, 1, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b?)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b?)c", extended, "ac", match_default, make_array(0, 2, 1, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b+)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b+)c", extended, "abbbc", match_default, make_array(0, 5, 1, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b*)c", extended, "ac", match_default, make_array(0, 2, 1, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a|ab)(bc([de]+)f|cde)", extended, "abcdef", match_default, make_array(0, 6, 0, 1, 1, 6, 3, 5, -2, -2));
|
||||
TEST_REGEX_SEARCH("a([bc]?)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a([bc]?)c", extended, "ac", match_default, make_array(0, 2, 1, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a([bc]+)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a([bc]+)c", extended, "abcc", match_default, make_array(0, 4, 1, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a([bc]+)bc", extended, "abcbc", match_default, make_array(0, 5, 1, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(bb+|b)b", extended, "abb", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(bbb+|bb+|b)b", extended, "abb", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(bbb+|bb+|b)b", extended, "abbb", match_default, make_array(0, 4, 1, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(bbb+|bb+|b)bb", extended, "abbb", match_default, make_array(0, 4, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("(.*).*", extended, "abcdef", match_default, make_array(0, 6, 0, 6, -2, 6, 6, 6, 6, -2, -2));
|
||||
TEST_REGEX_SEARCH("(a*)*", extended, "bc", match_default, make_array(0, 0, 0, 0, -2, 1, 1, 1, 1, -2, 2, 2, 2, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("xyx*xz", extended, "xyxxxxyxxxz", match_default, make_array(5, 11, -2, -2));
|
||||
// do we get the right subexpression when it is used more than once?
|
||||
TEST_REGEX_SEARCH("a(b|c)*d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c)*d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c)+d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c)+d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c?)+d", extended, "ad", match_default, make_array(0, 2, 1, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,0}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,1}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,1}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,2}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,2}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){0,}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){1,1}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){1,2}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){1,2}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){1,}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){1,}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,2}d", extended, "acbd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,2}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,4}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,4}d", extended, "abcbd", match_default, make_array(0, 5, 3, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,4}d", extended, "abcbcd", match_default, make_array(0, 6, 4, 5, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b|c){2,}d", extended, "abcbd", match_default, make_array(0, 5, 3, 4, -2, -2));
|
||||
// perl only:
|
||||
TEST_REGEX_SEARCH("a(b|c?)+d", perl, "abcd", match_default, make_array(0, 4, 3, 3, -2, -2));
|
||||
TEST_REGEX_SEARCH("a(b+|((c)*))+d", perl, "abd", match_default, make_array(0, 3, 2, 2, 2, 2, -1, -1, -2, -2));
|
||||
@ -123,12 +212,32 @@ void test_tricky_cases()
|
||||
// preprossor directives:
|
||||
TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", perl, "#define some_symbol", match_default, make_array(0, 19, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", perl, "#define some_symbol(x) #x", match_default, make_array(0, 25, -1, -1, -2, -2));
|
||||
// try to match C++ syntax elements:
|
||||
// line comment:
|
||||
TEST_REGEX_SEARCH("//[^\\n]*", extended&~no_escape_in_lists, "++i //here is a line comment\n", match_default, make_array(4, 28, -2, -2));
|
||||
// block comment:
|
||||
TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/* here is a block comment */", match_default, make_array(0, 29, 26, 27, -2, -2));
|
||||
TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/**/", match_default, make_array(0, 4, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/***/", match_default, make_array(0, 5, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/****/", match_default, make_array(0, 6, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/*****/", match_default, make_array(0, 7, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/*****/*/", match_default, make_array(0, 7, -1, -1, -2, -2));
|
||||
// preprossor directives:
|
||||
TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", extended&~no_escape_in_lists, "#define some_symbol", match_default, make_array(0, 19, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", extended&~no_escape_in_lists, "#define some_symbol(x) #x", match_default, make_array(0, 25, -1, -1, -2, -2));
|
||||
// perl only:
|
||||
TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", perl, "#define some_symbol(x) \\ \r\n foo();\\\r\n printf(#x);", match_default, make_array(0, 53, 30, 42, -2, -2));
|
||||
// literals:
|
||||
// POSIX leftmost longest checks:
|
||||
TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "a", match_default, make_array(0, 1, -1, -1, 0, 1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "aa", match_default, make_array(0, 2, -1, -1, 0, 2, -2, -2));
|
||||
TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "aaa", match_default, make_array(0, 3, 0, 3, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "aaaa", match_default, make_array(0, 4, -1, -1, 0, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("($)|(\\>)", extended&~no_escape_in_lists, "aaaa", match_default, make_array(4, 4, 4, 4, -1, -1, -2, -2));
|
||||
TEST_REGEX_SEARCH("($)|(\\>)", extended&~no_escape_in_lists, "aaaa", match_default|match_not_eol, make_array(4, 4, -1, -1, 4, 4, -2, -2));
|
||||
TEST_REGEX_SEARCH("(aaa)(ab)*", extended, "aaaabab", match_default, make_array(0, 7, 0, 3, 5, 7, -2, -2));
|
||||
}
|
||||
|
||||
void test_tricky_cases2()
|
||||
void test_tricky_cases3()
|
||||
{
|
||||
using namespace boost::regex_constants;
|
||||
TEST_REGEX_SEARCH("((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)?", perl, "0xFF", match_default, make_array(0, 4, 0, 4, 0, 4, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2));
|
||||
|
Reference in New Issue
Block a user