Repeats now work, Jamfiles and portability issues also addressed.

[SVN r22512]
This commit is contained in:
John Maddock
2004-03-17 13:18:27 +00:00
parent 4d2d3a1450
commit 23d7352b19
19 changed files with 565 additions and 129 deletions

View File

@ -64,6 +64,7 @@ protected:
re_syntax_base* m_last_state;// the last state we added
bool m_icase; // true for case insensitive matches
typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character
typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character
private:
basic_regex_creator& operator=(const basic_regex_creator&);
basic_regex_creator(const basic_regex_creator&);
@ -80,8 +81,11 @@ basic_regex_creator<charT, traits>::basic_regex_creator(regex_data<charT, traits
{
m_pdata->m_data.clear();
static const charT w = 'w';
static const charT s = 's';
m_word_mask = m_traits.lookup_classname(&w, &w +1);
//BOOST_ASSERT(m_word_mask); // TODO!!
m_mask_space = m_traits.lookup_classname(&s, &s +1);
BOOST_ASSERT(m_word_mask);
BOOST_ASSERT(m_mask_space);
}
template <class charT, class traits>
@ -308,7 +312,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
{
if(!m_traits.is_class(static_cast<charT>(i), m_word_mask))
map[i] &= ~mask;
map[i] &= static_cast<unsigned char>(~mask);
}
}
return;
@ -323,7 +327,7 @@ void basic_regex_creator<charT, traits>::create_startmap(re_syntax_base* state,
for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i)
{
if(m_traits.is_class(static_cast<charT>(i), m_word_mask))
map[i] &= ~mask;
map[i] &= static_cast<unsigned char>(~mask);
}
}
return;

View File

@ -43,6 +43,7 @@ public:
bool parse_extended_escape();
bool parse_match_any();
bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits<std::size_t>::max)());
bool parse_repeat_range(bool isbasic);
private:
typedef bool (basic_regex_parser::*parser_proc_type)();
@ -157,6 +158,7 @@ bool basic_regex_parser<charT, traits>::parse_basic()
template <class charT, class traits>
bool basic_regex_parser<charT, traits>::parse_extended()
{
bool result;
switch(this->m_traits.syntax_type(*m_position))
{
case regex_constants::syntax_open_mark:
@ -190,10 +192,20 @@ bool basic_regex_parser<charT, traits>::parse_extended()
fail(REG_BADRPT, 0);
++m_position;
return parse_repeat(1);
case regex_constants::syntax_open_brace:
++m_position;
return parse_repeat_range(false);
case regex_constants::syntax_close_brace:
fail(REG_EBRACE, this->m_position - this->m_end);
// we don't ever get here, because we will have thrown:
BOOST_ASSERT(0);
result = false;
break;
default:
return parse_literal();
result = parse_literal();
break;
}
return true;
return result;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
@ -244,16 +256,41 @@ template <class charT, class traits>
bool basic_regex_parser<charT, traits>::parse_basic_escape()
{
++m_position;
bool result;
switch(this->m_traits.escape_syntax_type(*m_position))
{
case regex_constants::syntax_open_mark:
return parse_open_paren();
case regex_constants::syntax_close_mark:
return false;
case regex_constants::syntax_plus:
if(this->m_pdata->m_flags & regex_constants::bk_plus_qm)
{
++m_position;
return parse_repeat(1);
}
else
return parse_literal();
case regex_constants::syntax_question:
if(this->m_pdata->m_flags & regex_constants::bk_plus_qm)
{
++m_position;
return parse_repeat(0, 1);
}
else
return parse_literal();
case regex_constants::syntax_open_brace:
++m_position;
return parse_repeat_range(true);
case regex_constants::syntax_close_brace:
fail(REG_EBRACE, this->m_position - this->m_base);
result = false;
break;
default:
return parse_literal();
result = parse_literal();
break;
}
return true;
return result;
}
template <class charT, class traits>
@ -305,6 +342,10 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
++m_position;
}
}
if(0 == this->m_last_state)
{
fail(REG_BADRPT, std::distance(m_base, m_position));
}
if(this->m_last_state->type == syntax_element_endmark)
{
// insert a repeat before the '(' matching the last ')':
@ -367,6 +408,80 @@ bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_
return true;
}
template <class charT, class traits>
bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
{
//
// parse a repeat-range:
//
std::size_t min, max;
int v;
// skip whitespace:
while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space))
++m_position;
// fail if at end:
if(this->m_position == this->m_end)
fail(REG_EBRACE, this->m_position - this->m_base);
// get min:
v = this->m_traits.toi(m_position, m_end, 10);
// skip whitespace:
while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space))
++m_position;
if(v < 0)
fail(REG_BADBR, this->m_position - this->m_base);
else if(this->m_position == this->m_end)
fail(REG_EBRACE, this->m_position - this->m_base);
min = v;
// see if we have a comma:
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma)
{
// move on and error check:
++m_position;
// skip whitespace:
while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space))
++m_position;
if(this->m_position == this->m_end)
fail(REG_EBRACE, this->m_position - this->m_base);
// get the value if any:
v = this->m_traits.toi(m_position, m_end, 10);
max = (v >= 0) ? v : (std::numeric_limits<std::size_t>::max)();
}
else
{
// no comma, max = min:
max = min;
}
// skip whitespace:
while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space))
++m_position;
// OK now check trailing }:
if(this->m_position == this->m_end)
fail(REG_EBRACE, this->m_position - this->m_base);
if(isbasic)
{
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_escape)
{
++m_position;
if(this->m_position == this->m_end)
fail(REG_EBRACE, this->m_position - this->m_base);
}
else
{
fail(REG_BADBR, this->m_position - this->m_base);
}
}
if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_brace)
++m_position;
else
fail(REG_BADBR, this->m_position - this->m_base);
//
// finally go and add the repeat, unless error:
//
if(min > max)
fail(REG_ERANGE, this->m_position - this->m_base);
return parse_repeat(min, max);
}
} // namespace re_detail
} // namespace boost

View File

@ -36,6 +36,100 @@ class cpp_regex_traits;
namespace re_detail{
//
// class parser_buf:
// acts as a stream buffer which wraps around a pair of pointers:
//
template <class charT,
class traits = ::std::char_traits<charT> >
class parser_buf : public ::std::basic_streambuf<charT, traits>
{
typedef ::std::basic_streambuf<charT, traits> base_type;
typedef typename base_type::int_type int_type;
typedef typename base_type::char_type char_type;
typedef typename base_type::pos_type pos_type;
typedef ::std::streamsize streamsize;
typedef typename base_type::off_type off_type;
public:
parser_buf() : base_type() { setbuf(0, 0); }
const charT* getnext() { return this->gptr(); }
protected:
std::basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n);
typename parser_buf<charT, traits>::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which);
typename parser_buf<charT, traits>::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which);
private:
parser_buf& operator=(const parser_buf&);
parser_buf(const parser_buf&);
};
template<class charT, class traits>
std::basic_streambuf<charT, traits>*
parser_buf<charT, traits>::setbuf(char_type* s, streamsize n)
{
this->setg(s, s, s + n);
return this;
}
template<class charT, class traits>
typename parser_buf<charT, traits>::pos_type
parser_buf<charT, traits>::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which)
{
if(which & ::std::ios_base::out)
return pos_type(off_type(-1));
std::ptrdiff_t size = this->egptr() - this->eback();
std::ptrdiff_t pos = this->gptr() - this->eback();
charT* g = this->eback();
switch(way)
{
case ::std::ios_base::beg:
if((off < 0) || (off > size))
return pos_type(off_type(-1));
else
this->setg(g, g + off, g + size);
break;
case ::std::ios_base::end:
if((off < 0) || (off > size))
return pos_type(off_type(-1));
else
this->setg(g, g + size - off, g + size);
break;
case ::std::ios_base::cur:
{
std::ptrdiff_t newpos = pos + off;
if((newpos < 0) || (newpos > size))
return pos_type(off_type(-1));
else
this->setg(g, g + newpos, g + size);
break;
}
default: ;
}
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4244)
#endif
return static_cast<pos_type>(this->gptr() - this->eback());
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template<class charT, class traits>
typename parser_buf<charT, traits>::pos_type
parser_buf<charT, traits>::seekpos(pos_type sp, ::std::ios_base::openmode which)
{
if(which & ::std::ios_base::out)
return pos_type(off_type(-1));
off_type size = static_cast<off_type>(this->egptr() - this->eback());
charT* g = this->eback();
if(off_type(sp) <= size)
{
this->setg(g, g + off_type(sp), g + size);
}
return pos_type(off_type(-1));
}
//
// class cpp_regex_traits_base:
// acts as a container for locale and the facets we are using.
@ -210,8 +304,9 @@ template <class charT>
class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer<charT>
{
public:
cpp_regex_traits_implementation();
cpp_regex_traits_implementation(const std::locale& l) : cpp_regex_traits_char_layer<charT>(l){}
typedef std::basic_string<charT> string_type;
//cpp_regex_traits_implementation();
cpp_regex_traits_implementation(const std::locale& l);
std::string error_string(regex_constants::error_type n) const
{
if(!m_error_strings.empty())
@ -221,12 +316,15 @@ public:
}
return get_default_error_string(n);
}
re_detail::parser_buf<charT> m_sbuf; // buffer for parsing numbers.
std::basic_istream<charT> m_is; // stream for parsing numbers.
private:
std::map<int, std::string> m_error_strings;
std::map<int, std::string> m_error_strings; // error messages indexed by numberic ID
};
template <class charT>
cpp_regex_traits_implementation<charT>::cpp_regex_traits_implementation()
cpp_regex_traits_implementation<charT>::cpp_regex_traits_implementation(const std::locale& l)
: cpp_regex_traits_char_layer<charT>(l), m_is(&m_sbuf)
{
#ifndef __IBMCPP__
typename std::messages<charT>::catalog cat = static_cast<std::messages<char>::catalog>(-1);
@ -253,14 +351,26 @@ cpp_regex_traits_implementation<charT>::cpp_regex_traits_implementation()
{
for(int i = 0; i <= boost::regex_constants::error_unknown; ++i)
{
std::string s = this->m_pmessages->get(cat, 0, i+200, get_default_error_string(i));
m_error_strings[i] = s;
const char* p = get_default_error_string(i);
string_type default_message;
while(*p)
{
default_message.append(1, this->m_pctype->widen(*p));
++p;
}
string_type s = this->m_pmessages->get(cat, 0, i+200, default_message);
std::string result;
for(std::string::size_type j = 0; j < s.size(); ++j)
{
result.append(1, this->m_pctype->narrow(s[j], 0));
}
m_error_strings[i] = result;
}
}
}
template <class charT>
boost::shared_ptr<cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l)
boost::shared_ptr<cpp_regex_traits_implementation<charT> > create_cpp_regex_traits(const std::locale& l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT))
{
// TODO: create a cache for previously constructed objects.
return boost::shared_ptr<cpp_regex_traits_implementation<charT> >(new cpp_regex_traits_implementation<charT>(l));
@ -278,7 +388,26 @@ public:
typedef std::size_t size_type;
typedef std::basic_string<char_type> string_type;
typedef std::locale locale_type;
typedef typename ctype_type::mask char_class_type;
typedef boost::uint_least32_t char_class_type;
BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 16);
BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 17);
BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 18);
BOOST_STATIC_CONSTANT(char_class_type,
mask_base =
std::ctype<char>::alnum
| std::ctype<char>::alpha
| std::ctype<char>::cntrl
| std::ctype<char>::digit
| std::ctype<char>::graph
| std::ctype<char>::lower
| std::ctype<char>::print
| std::ctype<char>::punct
| std::ctype<char>::space
| std::ctype<char>::upper
| std::ctype<char>::xdigit);
//BOOST_STATIC_ASSERT(0 == (mask_base & (mask_word | mask_unicode)));
cpp_regex_traits()
: m_pimpl(re_detail::create_cpp_regex_traits<charT>(std::locale()))
@ -309,7 +438,33 @@ public:
}
char_class_type lookup_classname(const charT* p1, const charT* p2) const
{
return 0;
static const char_class_type masks[] =
{
0,
std::ctype<char>::alnum,
std::ctype<char>::alpha,
cpp_regex_traits<charT>::mask_blank,
std::ctype<char>::cntrl,
std::ctype<char>::digit,
std::ctype<char>::digit,
std::ctype<char>::graph,
std::ctype<char>::lower,
std::ctype<char>::lower,
std::ctype<char>::print,
std::ctype<char>::punct,
std::ctype<char>::space,
std::ctype<char>::space,
cpp_regex_traits<charT>::mask_unicode,
std::ctype<char>::upper,
std::ctype<char>::upper,
std::ctype<char>::alnum | cpp_regex_traits<charT>::mask_word,
std::ctype<char>::alnum | cpp_regex_traits<charT>::mask_word,
std::ctype<char>::xdigit,
};
int id = re_detail::get_default_class_id(p1, p2);
assert(id >= -1);
assert(id < sizeof(masks) / sizeof(masks[0]));
return masks[1 + id];
}
string_type lookup_collatename(const charT* p1, const charT* p2) const
{
@ -317,12 +472,21 @@ public:
}
bool is_class(charT c, char_class_type f) const
{
if((f & cpp_regex_traits<charT>::mask_base)
&& (m_pimpl->m_pctype->is(
static_cast<std::ctype<charT>::mask>(f & cpp_regex_traits<charT>::mask_base), c)))
return true;
else if((f & cpp_regex_traits<charT>::mask_unicode) && (c >= 256))
return true;
else if((f & cpp_regex_traits<charT>::mask_word) && (c == '_'))
return true;
else if((f & cpp_regex_traits<charT>::mask_blank)
&& m_pimpl->m_pctype->is(static_cast<std::ctype<charT>::mask>(f & cpp_regex_traits<charT>::mask_base), c)
&& !re_detail::is_separator(c))
return true;
return false;
}
int value(charT) const
{
return -1;
}
int toi(const charT*& p1, const charT* p2, int radix)const;
locale_type imbue(locale_type l)
{
std::locale result(getloc());
@ -356,6 +520,25 @@ private:
#endif
};
template <class charT>
int cpp_regex_traits<charT>::toi(const charT*& first, const charT* last, int radix)const
{
m_pimpl->m_sbuf.pubsetbuf(const_cast<charT*>(first), static_cast<std::streamsize>(last-first));
m_pimpl->m_is.clear();
if(std::abs(radix) == 16) m_pimpl->m_is >> std::hex;
else if(std::abs(radix) == 8) m_pimpl->m_is >> std::oct;
else m_pimpl->m_is >> std::dec;
int val;
if(m_pimpl->m_is >> val)
{
first = first + ((last - first) - m_pimpl->m_sbuf.in_avail());
return val;
}
else
return -1;
}
template <class charT>
std::string cpp_regex_traits<charT>::catalog_name(const std::string& name)
{

View File

@ -87,10 +87,10 @@ inline const charT* re_skip_past_null(const charT* p)
return ++p;
}
template <class iterator, class charT, class traits_type>
template <class iterator, class charT, class traits_type, class char_classT>
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
iterator last,
const re_set_long<typename traits_type::char_class_type>* set_,
const re_set_long<char_classT>* set_,
const basic_regex<charT, traits_type>& e)
{
const charT* p = reinterpret_cast<const charT*>(set_+1);
@ -233,7 +233,7 @@ public:
}
std::size_t get_count() { return count; }
int get_id() { return id; }
int operator++() { return ++count; }
std::size_t operator++() { return ++count; }
bool check_null_repeat(const BidiIterator& pos, std::size_t max)
{
// this is called when we are about to start a new repeat,

View File

@ -586,10 +586,11 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_backref()
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
{
typedef typename traits::char_class_type char_class_type;
// let the traits class do the work:
if(position == last)
return false;
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<typename traits::char_class_type>*>(pstate), re);
BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re);
if(t != position)
{
pstate = pstate->next.p;

View File

@ -624,8 +624,9 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
#ifdef __BORLANDC__
#pragma option push -w-8008 -w-8066 -w-8004
#endif
typedef typename traits::char_class_type char_class_type;
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
const re_set_long<typename traits::char_class_type>* set = static_cast<const re_set_long<typename traits::char_class_type>*>(pstate->next.p);
const re_set_long<char_class_type>* set = static_cast<const re_set_long<char_class_type>*>(pstate->next.p);
unsigned count = 0;
//
// start by working out how much we can skip:

View File

@ -119,6 +119,7 @@ namespace regex_constants{
collate = ::boost::regbase::collate,
nosubs = ::boost::regbase::nosubs,
optimize = ::boost::regbase::optimize,
bk_plus_qm = ::boost::regbase::bk_plus_qm,
basic = ::boost::regbase::basic,
extended = ::boost::regbase::extended,

View File

@ -179,7 +179,7 @@ OutputIterator BOOST_REGEX_CALL _reg_format_aux(OutputIterator out,
case regex_constants::syntax_digit:
{
expand_sub:
unsigned int index = parse_value(fmt, fmt_end, traits_inst, 10);
unsigned int index = traits_inst.toi(fmt, fmt_end, 10);
if(index < m.size())
oi_assign(&out, re_copy_out(out, Iterator(m[index].first), Iterator(m[index].second)));
continue;
@ -259,7 +259,7 @@ expand_sub:
++fmt;
continue;
}
int val = parse_value(fmt, fmt_end, traits_inst, 16);
int val = traits_inst.toi(fmt, fmt_end, 16);
if(val < 0)
{
fmt -= 2;
@ -284,7 +284,7 @@ expand_sub:
}
else
{
int val = parse_value(fmt, fmt_end, traits_inst, 16);
int val = traits_inst.toi(fmt, fmt_end, 16);
if(val < 0)
{
--fmt;
@ -324,7 +324,7 @@ expand_sub:
if(flags & format_sed)
goto expand_sub;
else
c = static_cast<charT>(parse_value(fmt, fmt_end, traits_inst, 8));
c = static_cast<charT>(traits_inst.toi(fmt, fmt_end, 8));
break;
default:
//c = *fmt;
@ -391,7 +391,7 @@ expand_sub:
++fmt;
return out;
}
unsigned int id = parse_value(fmt, fmt_end, traits_inst, 10);
unsigned int id = traits_inst.toi(fmt, fmt_end, 10);
if(m[id].matched)
{
oi_assign(&out, _reg_format_aux(out, m, fmt, flags | regex_constants::format_is_if, traits_inst));

View File

@ -139,7 +139,7 @@ inline bool regex_match(const std::string& s,
}
#if !defined(BOOST_NO_WREGEX)
inline bool regex_match(const std::basic_string<wchar_t>& s,
match_results<std::basic_string<wchar_t>::const_iterator, wregex::allocator_type>& m,
match_results<std::basic_string<wchar_t>::const_iterator>& m,
const wregex& e,
match_flag_type flags = match_default)
{

View File

@ -131,6 +131,7 @@ inline bool regex_search(const std::basic_string<charT, ST, SA>& s,
return regex_search(s.begin(), s.end(), e, flags);
}
#else // non-template function overloads
#if 0
inline bool regex_search(const char* first, const char* last,
const regex& e,
match_flag_type flags = match_default)
@ -142,12 +143,13 @@ inline bool regex_search(const char* first, const char* last,
#ifndef BOOST_NO_WREGEX
inline bool regex_search(const wchar_t* first, const wchar_t* last,
const wregex& e,
match_flag_type flags = match_default)
match_flag_type flags/* = match_default*/)
{
wcmatch m;
return regex_search(first, last, m, e, flags);
}
#endif
#endif
inline bool regex_search(const char* str,
const regex& e,
match_flag_type flags = match_default)

View File

@ -47,7 +47,13 @@ inline bool is_combining<unsigned char>(unsigned char)
{
return false;
}
#if defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
#ifdef _MSC_VER
template<>
inline bool is_combining<wchar_t>(wchar_t c)
{
return is_combining_implementation(static_cast<unsigned short>(c));
}
#elif defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
#if defined(WCHAR_MAX) && (WCHAR_MAX <= USHRT_MAX)
template<>
inline bool is_combining<wchar_t>(wchar_t c)
@ -58,7 +64,7 @@ inline bool is_combining<wchar_t>(wchar_t c)
template<>
inline bool is_combining<wchar_t>(wchar_t c)
{
return (c > std::numeric_limits<uint_least16_t>::max()) ? false : is_combining_implementation(static_cast<unsigned short>(c));
return (c > (std::numeric_limits<uint_least16_t>::max)()) ? false : is_combining_implementation(static_cast<unsigned short>(c));
}
#endif
#endif
@ -72,13 +78,85 @@ inline bool is_separator(charT c)
return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r'));
}
//
// get the id of a character clasification, the individual
// traits classes then transform that id into a bitmask:
//
template <class charT>
struct character_pointer_range
{
const charT* p1;
const charT* p2;
bool operator < (const character_pointer_range& r)const
{
return std::lexicographical_compare(p1, p2, r.p1, r.p2);
}
bool operator == (const character_pointer_range& r)const
{
return (std::distance(p1, p2) == std::distance(r.p1, r.p2)) && std::equal(p1, p2, r.p1);
}
};
template <class charT>
int get_default_class_id(const charT* p1, const charT* p2)
{
static const charT data[] = {
'a', 'l', 'n', 'u', 'm',
'a', 'l', 'p', 'h', 'a',
'b', 'l', 'a', 'n', 'k',
'c', 'n', 't', 'r', 'l',
'd', 'i', 'g', 'i', 't',
'g', 'r', 'a', 'p', 'h',
'l', 'o', 'w', 'e', 'r',
'p', 'r', 'i', 'n', 't',
'p', 'u', 'n', 'c', 't',
's', 'p', 'a', 'c', 'e',
'u', 'n', 'i', 'c', 'o', 'd', 'e',
'u', 'p', 'p', 'e', 'r',
'w', 'o', 'r', 'd',
'x', 'd', 'i', 'g', 'i', 't',
};
static const character_pointer_range<charT> ranges[] =
{
{data+0, data+5,}, // alnum
{data+5, data+10,}, // alpha
{data+10, data+15,}, // blank
{data+15, data+20,}, // cntrl
{data+20, data+21,}, // d
{data+20, data+25,}, // digit
{data+25, data+30,}, // graph
{data+30, data+31,}, // l
{data+30, data+35,}, // lower
{data+35, data+40,}, // print
{data+40, data+45,}, // punct
{data+45, data+46,}, // s
{data+45, data+50,}, // space
{data+50, data+57,}, // unicode
{data+57, data+58,}, // u
{data+57, data+62,}, // upper
{data+62, data+63,}, // w
{data+62, data+66,}, // word
{data+66, data+72,}, // xdigit
};
character_pointer_range<charT> t = { p1, p2, };
const character_pointer_range<charT>* p = std::lower_bound(ranges, ranges + (sizeof(ranges)/sizeof(ranges[0])), t);
if(t == *p)
return static_cast<int>(p - ranges);
return -1;
}
#if 0
//
// parse_value:
// covert a character sequence into a value, return -1 if no digits found:
//
template <class ForwardIterator, class traits>
int parse_value(ForwardIterator& p1, ForwardIterator p2, const traits& traits_inst, int radix = 10)
template <class charT, class traits>
int parse_value(const charT*& p1, const charT* p2, const traits& traits_inst, int radix = 10)
{
return traits_inst.toi(p1, p2, radix);
#if 0
int value = 0;
if(traits_inst.value(*p1) < 0)
return -1;
@ -91,8 +169,9 @@ int parse_value(ForwardIterator& p1, ForwardIterator p2, const traits& traits_in
++p1;
}
return value;
#endif
}
#endif
} // re_detail
} // boost

View File

@ -221,10 +221,10 @@ enum re_jump_size_type
/*** proc re_is_set_member *********************************************
Forward declaration: we'll need this one later...
***********************************************************************/
template <class iterator, class charT, class traits_type>
template <class iterator, class charT, class traits_type, class char_classT>
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
iterator last,
const re_set_long<typename traits_type::char_class_type>* set_,
const re_set_long<char_classT>* set_,
const basic_regex<charT, traits_type>& e);
} // namespace re_detail

View File

@ -162,6 +162,10 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA*
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA* expression, const char* buf, regsize_t n, regmatch_t* array, int eflags)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4267)
#endif
bool result = false;
match_flag_type flags = match_default | expression->eflags;
const char* end;
@ -217,6 +221,9 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA* expression, cons
return 0;
}
return REG_NOMATCH;
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA* expression)

View File

@ -95,7 +95,7 @@ const char* get_default_error_string(regex_constants::error_type n)
"Invalid back reference", /* REG_ESUBREG */
"Unmatched [ or [^", /* REG_EBRACK */
"Unmatched ( or \\(", /* REG_EPAREN */
"Unmatched \\{", /* REG_EBRACE */
"Unmatched { or \\{", /* REG_EBRACE */
"Invalid content of \\{\\}", /* REG_BADBR */
"Invalid range end", /* REG_ERANGE */
"Memory exhausted", /* REG_ESPACE */
@ -112,7 +112,7 @@ const char* get_default_error_string(regex_constants::error_type n)
"",
};
return (n <= REG_E_UNKNOWN) ? s_default_error_messages[REG_E_UNKNOWN] : s_default_error_messages[n];
return (n > REG_E_UNKNOWN) ? s_default_error_messages[REG_E_UNKNOWN] : s_default_error_messages[n];
}
bool is_combining_implementation(boost::uint_least16_t c)

View File

@ -23,7 +23,10 @@
#include <boost/regex/static_mutex.hpp>
#if defined(BOOST_HAS_WINTHREADS)
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <boost/static_assert.hpp>
#endif
@ -64,6 +67,8 @@ void scoped_static_mutex_lock::unlock()
#elif defined(BOOST_HAS_WINTHREADS)
BOOST_STATIC_ASSERT(sizeof(LONG) == sizeof(boost::int32_t));
scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& m, bool lk)
: m_mutex(m), m_have_lock(false)
{
@ -81,7 +86,11 @@ void scoped_static_mutex_lock::lock()
{
if(0 == m_have_lock)
{
while(0 != InterlockedCompareExchange((LONG*)&(m_mutex.m_mutex), 1, 0))
#if defined(BOOST_MSVC) && (BOOST_MSVC <=1200)
while(0 != InterlockedCompareExchange(reinterpret_cast<void**>((boost::uint_least16_t*)&(m_mutex.m_mutex)), (void*)1, 0))
#else
while(0 != InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(&(m_mutex.m_mutex)), 1, 0))
#endif
{
Sleep(0);
}
@ -93,7 +102,11 @@ void scoped_static_mutex_lock::unlock()
{
if(m_have_lock)
{
#if defined(BOOST_MSVC) && (BOOST_MSVC <=1200)
InterlockedExchange((LONG*)&(m_mutex.m_mutex), 0);
#else
InterlockedExchange(reinterpret_cast<volatile LONG*>(&(m_mutex.m_mutex)), 0);
#endif
m_have_lock = false;
}
}

View File

@ -170,6 +170,10 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW*
BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW* expression, const wchar_t* buf, regsize_t n, regmatch_t* array, int eflags)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4267)
#endif
bool result = false;
match_flag_type flags = match_default | expression->eflags;
const wchar_t* end;
@ -224,6 +228,9 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW* expression, cons
return 0;
}
return REG_NOMATCH;
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW* expression)

View File

@ -80,93 +80,108 @@ void basic_tests()
TEST_REGEX_SEARCH("\\*", perl, "*", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("(ab)*", perl, "abab", match_default, make_array(0, 4, 2, 4, -2, -2));
// now try operator + :
TEST_REGEX_SEARCH("ab+", perl, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("ab+", perl, "ab", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("ab+", perl, "sssabbbbbbsss", match_default, make_array(3, 10, -2, -2));
TEST_REGEX_SEARCH("ab+c+", perl, "abbb", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("ab+c+", perl, "accc", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("ab+c+", perl, "abbcc", match_default, make_array(0, 5, -2, -2));
TEST_INVALID_REGEX("+a", perl);
TEST_INVALID_REGEX("\\<+", perl);
TEST_INVALID_REGEX("\\>+", perl);
TEST_REGEX_SEARCH("\n+", perl, "\n\n", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("\\+", perl, "+", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("\\+", perl, "++", match_default, make_array(0, 1, -2, 1, 2, -2, -2));
TEST_REGEX_SEARCH("\\++", perl, "++", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("+", basic|bk_plus_qm, "+", match_default, make_array(0, 1, -2, -2));
TEST_INVALID_REGEX("\\+", basic|bk_plus_qm);
TEST_REGEX_SEARCH("a\\+", basic|bk_plus_qm, "aa", match_default, make_array(0, 2, -2, -2));
// now try operator ?
TEST_REGEX_SEARCH("a?", perl, "b", match_default, make_array(0, 0, -2, -2));
TEST_REGEX_SEARCH("ab?", perl, "a", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("ab?", perl, "ab", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("ab?", perl, "sssabbbbbbsss", match_default, make_array(3, 5, -2, -2));
TEST_REGEX_SEARCH("ab?c?", perl, "a", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("ab?c?", perl, "abbb", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("ab?c?", perl, "accc", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("ab?c?", perl, "abcc", match_default, make_array(0, 3, -2, -2));
TEST_INVALID_REGEX("?a", perl);
TEST_INVALID_REGEX("\\<?", perl);
TEST_INVALID_REGEX("\\>?", perl);
TEST_REGEX_SEARCH("\n?", perl, "\n\n", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("\\?", perl, "?", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("\\?", perl, "?", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("\\??", perl, "??", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("?", basic|bk_plus_qm, "?", match_default, make_array(0, 1, -2, -2));
TEST_INVALID_REGEX("\\?", basic|bk_plus_qm);
TEST_REGEX_SEARCH("a\\?", basic|bk_plus_qm, "aa", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("a\\?", basic|bk_plus_qm, "b", match_default, make_array(0, 0, -2, -2));
TEST_REGEX_SEARCH("a?", basic, "a?", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a+", basic, "a+", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\?", basic, "a?", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\+", basic, "a+", match_default, make_array(0, 2, -2, -2));
// now try operator {}
TEST_REGEX_SEARCH("a{2}", perl, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("a{2}", perl, "aa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a{2}", perl, "aaa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a{2,}", perl, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("a{2,}", perl, "aa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a{2,}", perl, "aaaaa", match_default, make_array(0, 5, -2, -2));
TEST_REGEX_SEARCH("a{2,4}", perl, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("a{2,4}", perl, "aa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a{2,4}", perl, "aaa", match_default, make_array(0, 3, -2, -2));
TEST_REGEX_SEARCH("a{2,4}", perl, "aaaa", match_default, make_array(0, 4, -2, -2));
TEST_REGEX_SEARCH("a{2,4}", perl, "aaaaa", match_default, make_array(0, 4, -2, -2));
TEST_REGEX_SEARCH("a{ 2 , 4 }", perl, "aaaaa", match_default, make_array(0, 4, -2, -2));
TEST_REGEX_SEARCH("a{ 2 , }", perl, "aaaaa", match_default, make_array(0, 5, -2, -2));
TEST_REGEX_SEARCH("a{ 2 }", perl, "aaa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\{\\}", perl, "a{}", match_default, make_array(0, 3, -2, -2));
TEST_INVALID_REGEX("a{}", perl);
TEST_INVALID_REGEX("a{", perl);
TEST_INVALID_REGEX("a{1", perl);
TEST_INVALID_REGEX("a{1,", perl);
TEST_INVALID_REGEX("a{ }", perl);
TEST_INVALID_REGEX("a}", perl);
TEST_INVALID_REGEX("{1}", perl);
TEST_INVALID_REGEX("a{b}", perl);
TEST_INVALID_REGEX("a{1b}", perl);
TEST_INVALID_REGEX("a{1,b}", perl);
TEST_INVALID_REGEX("a{1,2v}", perl);
// now try operator \\{\\} for POSIX basic regexes
TEST_REGEX_SEARCH("a\\{2\\}", basic, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("a\\{2\\}", basic, "aa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\{2\\}", basic, "aaa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\{2,\\}", basic, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("a\\{2,\\}", basic, "aa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\{2,\\}", basic, "aaaaa", match_default, make_array(0, 5, -2, -2));
TEST_REGEX_SEARCH("a\\{2,4\\}", basic, "a", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("a\\{2,4\\}", basic, "aa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a\\{2,4\\}", basic, "aaa", match_default, make_array(0, 3, -2, -2));
TEST_REGEX_SEARCH("a\\{2,4\\}", basic, "aaaa", match_default, make_array(0, 4, -2, -2));
TEST_REGEX_SEARCH("a\\{2,4\\}", basic, "aaaaa", match_default, make_array(0, 4, -2, -2));
TEST_REGEX_SEARCH("a\\{ 2 , 4 \\}", basic, "aaaaa", match_default, make_array(0, 4, -2, -2));
TEST_REGEX_SEARCH("a\\{ 2 , \\}", basic, "aaaaa", match_default, make_array(0, 5, -2, -2));
TEST_REGEX_SEARCH("a\\{ 2 \\}", basic, "aaa", match_default, make_array(0, 2, -2, -2));
TEST_REGEX_SEARCH("a{}", basic, "a{}", match_default, make_array(0, 3, -2, -2));
TEST_INVALID_REGEX("a\\{\\}", basic);
TEST_INVALID_REGEX("a\\{", basic);
TEST_INVALID_REGEX("a\\{1", basic);
TEST_INVALID_REGEX("a\\{1,", basic);
TEST_INVALID_REGEX("a\\{ \\}", basic);
TEST_INVALID_REGEX("a\\}", basic);
TEST_INVALID_REGEX("\\{1\\}", basic);
TEST_INVALID_REGEX("a\\{b\\}", basic);
TEST_INVALID_REGEX("a\\{1b\\}", basic);
TEST_INVALID_REGEX("a\\{1,b\\}", basic);
TEST_INVALID_REGEX("a\\{1,2v\\}", basic);
#if 0
; now try operator +
ab+ a -1 -1
ab+ ab 0 2
ab+ sssabbbbbbsss 3 10
ab+c+ a -1 -1
ab+c+ abbb -1 -1
ab+c+ accc -1 -1
ab+c+ abbcc 0 5
+a !
\<+ !
\>+ !
\n+ \n\n 0 2
\+ + 0 1
\+ ++ 0 1
\++ ++ 0 2
- match_default normal bk_plus_qm REG_EXTENDED REG_NO_POSIX_TEST
+ + 0 1
\+ !
a\+ aa 0 2
; now try operator ?
- match_default normal REG_EXTENDED
a? b 0 0
ab? a 0 1
ab? ab 0 2
ab? sssabbbbbbsss 3 5
ab?c? a 0 1
ab?c? abbb 0 2
ab?c? accc 0 2
ab?c? abcc 0 3
?a !
\<? !
\>? !
\n? \n\n 0 1
\? ? 0 1
\? ?? 0 1
\?? ?? 0 1
- match_default normal bk_plus_qm REG_EXTENDED REG_NO_POSIX_TEST
? ? 0 1
\? !
a\? aa 0 1
a\? b 0 0
- match_default normal limited_ops
a? a? 0 2
a+ a+ 0 2
a\? a? 0 2
a\+ a+ 0 2
; now try operator {}
- match_default normal REG_EXTENDED
a{2} a -1 -1
a{2} aa 0 2
a{2} aaa 0 2
a{2,} a -1 -1
a{2,} aa 0 2
a{2,} aaaaa 0 5
a{2,4} a -1 -1
a{2,4} aa 0 2
a{2,4} aaa 0 3
a{2,4} aaaa 0 4
a{2,4} aaaaa 0 4
; spaces are now allowed inside {}
"a{ 2 , 4 }" aaaaa 0 4
a{} !
"a{ }" !
a{2 !
a} !
\{\} {} 0 2
- match_default normal bk_braces
a\{2\} a -1 -1
a\{2\} aa 0 2
a\{2\} aaa 0 2
a\{2,\} a -1 -1
a\{2,\} aa 0 2
a\{2,\} aaaaa 0 5
a\{2,4\} a -1 -1
a\{2,4\} aa 0 2
a\{2,4\} aaa 0 3
a\{2,4\} aaaa 0 4
a\{2,4\} aaaaa 0 4
"a\{ 2 , 4 \}" aaaaa 0 4
{} {} 0 2
; now test the alternation operator |
- match_default normal REG_EXTENDED
a|b a 0 1

View File

@ -11,7 +11,7 @@
// real test:
//
template <class charT, class tagT>
void test(charT, const tagT& tag)
void test(const charT&, const tagT& tag)
{
boost::basic_regex<charT> e;
test(e, tag);

View File

@ -11,6 +11,10 @@ struct test_regex_search_tag{};
template <class BidirectionalIterator>
void test_sub_match(const boost::sub_match<BidirectionalIterator>& sub, BidirectionalIterator base, const int* answer_table, int i)
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4244)
#endif
typedef typename boost::sub_match<BidirectionalIterator>::value_type charT;
if(sub.matched == 0)
{
@ -38,6 +42,9 @@ void test_sub_match(const boost::sub_match<BidirectionalIterator>& sub, Bidirect
<< ", expected " << answer_table[1 + 2*i] << ".", charT);
}
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class BidirectionalIterator, class Allocator>
@ -52,10 +59,11 @@ void test_result(const boost::match_results<BidirectionalIterator, Allocator>& w
template<class charT, class traits>
void test_simple_search(boost::basic_regex<charT, traits>& r)
{
typedef typename std::basic_string<charT>::const_iterator const_iterator;
const std::basic_string<charT>& search_text = test_info<charT>::search_text();
boost::regex_constants::match_flag_type opts = test_info<charT>::match_options();
const int* answer_table = test_info<charT>::answer_table();
boost::match_results<typename std::basic_string<charT>::const_iterator> what;
boost::match_results<const_iterator> what;
if(boost::regex_search(
search_text.begin(),
search_text.end(),