more or less completed non-recursive implementation.

[SVN r18185]
This commit is contained in:
John Maddock
2003-04-05 10:20:40 +00:00
parent 498fcb125b
commit 6746fd87cc
6 changed files with 102 additions and 20 deletions

View File

@ -468,10 +468,9 @@ void raise_error(const traits& t, unsigned code)
# ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
# undef BOOST_REGEX_HAS_MS_STACK_GUARD
# endif
namespace boost{ namespace re_detail{
BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block();
BOOST_REGEX_DECL void BOOST_REGEX_CALL release_mem_block(void*);
} }
# ifndef BOOST_REGEX_MAX_CACHE_BLOCKS
# define BOOST_REGEX_MAX_CACHE_BLOCKS BOOST_REGEX_MAX_BLOCKS
# endif
#endif

View File

@ -77,3 +77,9 @@
// used by the non-recursive algorithm.
// #define BOOST_REGEX_MAX_BLOCKS 1024
// define this if you want to set the maximum number of memory blocks
// cached by the non-recursive algorithm: Normally this is the same as
// BOOST_REGEX_MAX_BLOCKS, but can be higher if you have multiple threads
// all using boost.regex, or lower if you don't want boost.regex to cache
// memory.
// #define BOOST_REGEX_MAX_CACHE_BLOCKS 1024

View File

@ -16,14 +16,14 @@
* LOCATION: see http://www.boost.org for most recent version.
* FILE mem_block_cache.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Definitions of perl_matcher member functions that are
* specific to the non-recursive implementation.
* DESCRIPTION: memory block cache used by the non-recursive matcher.
*/
#ifndef BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP
#define BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP
#include <new>
#include <boost/regex/v4/regex_synch.hpp>
#ifdef __BORLANDC__
# pragma option push -a8 -b -Vx -Ve -pc -w-8027
@ -39,7 +39,9 @@ struct mem_block_node
struct mem_block_cache
{
// this member has to be statically initialsed:
mem_block_node* next;
unsigned cached_blocks;
~mem_block_cache()
{
@ -52,19 +54,33 @@ struct mem_block_cache
}
void* get()
{
if(next)
#ifdef BOOST_HAS_THREADS
re_detail::cs_guard g(*re_detail::p_re_lock);
#endif
if(next)
{
mem_block_node* result = next;
next = next->next;
--cached_blocks;
return result;
}
return ::operator new(BOOST_REGEX_BLOCKSIZE);
}
void put(void* p)
{
mem_block_node* old = static_cast<mem_block_node*>(p);
old->next = next;
next = old;
#ifdef BOOST_HAS_THREADS
re_detail::cs_guard g(*re_detail::p_re_lock);
#endif
if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS)
{
::operator delete(p);
}
else
{
mem_block_node* old = static_cast<mem_block_node*>(p);
old->next = next;
next = old;
}
}
};

View File

@ -384,6 +384,7 @@ private:
bool unwind_char_repeat(bool);
bool unwind_short_set_repeat(bool);
bool unwind_long_set_repeat(bool);
bool unwind_non_greedy_repeat(bool);
void destroy_single_repeat();
void push_matched_paren(int index, const sub_match<BidiIterator>& sub);
void push_recursion_stopper();
@ -391,6 +392,7 @@ private:
void push_alt(const re_syntax_base* ps);
void push_repeater_count(int i, repeater_count<BidiIterator>** s);
void push_single_repeat(unsigned c, const re_repeat* r, BidiIterator last_position, int id);
void push_non_greedy_repeat(const re_syntax_base* ps);
// pointer to base of stack:

View File

@ -97,6 +97,7 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match()
#ifdef BOOST_REGEX_NON_RECURSIVE
save_state_init init(&m_stack_base, &m_backup_state);
used_block_count = BOOST_REGEX_MAX_BLOCKS;
try{
#endif
// reset our state machine:
@ -111,6 +112,17 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match()
return false;
return m_result[0].second == last;
#ifdef BOOST_REGEX_NON_RECURSIVE
}
catch(...)
{
// unwind all pushed states, apart from anything else this
// ensures that all the states are correctly destructed
// not just the memory freed.
while(unwind(true)){}
throw;
}
#endif
#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
}__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode())
{
@ -134,6 +146,7 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::find()
#ifdef BOOST_REGEX_NON_RECURSIVE
save_state_init init(&m_stack_base, &m_backup_state);
used_block_count = BOOST_REGEX_MAX_BLOCKS;
try{
#endif
state_count = 0;
@ -180,6 +193,17 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::find()
matcher_proc_type proc = s_find_vtable[type];
return (this->*proc)();
#ifdef BOOST_REGEX_NON_RECURSIVE
}
catch(...)
{
// unwind all pushed states, apart from anything else this
// ensures that all the states are correctly destructed
// not just the memory freed.
while(unwind(true)){}
throw;
}
#endif
#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
}__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode())
{
@ -755,6 +779,12 @@ perl_matcher<BidiIterator, Allocator, traits, Allocator2>::s_match_vtable[] =
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_combining,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_soft_buffer_end,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_restart_continue,
#if 0
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_rep,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_rep,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_rep,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_rep,
#else
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_dot_repeat_fast,
#else
@ -763,7 +793,7 @@ perl_matcher<BidiIterator, Allocator, traits, Allocator2>::s_match_vtable[] =
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_char_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_long_set_repeat,
#endif
};
template <class BidiIterator, class Allocator, class traits, class Allocator2>

View File

@ -54,7 +54,8 @@ enum saved_state_type
saved_state_rep_fast_dot = 9,
saved_state_rep_char = 10,
saved_state_rep_short_set = 11,
saved_state_rep_long_set = 12
saved_state_rep_long_set = 12,
saved_state_non_greedy_long_repeat = 13
};
struct saved_state
@ -134,8 +135,6 @@ struct saved_single_repeat : public saved_state
template <class BidiIterator, class Allocator, class traits, class Allocator2>
bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_all_states()
{
if(state_count > max_state_count)
raise_error(traits_inst, REG_ESPACE);
push_recursion_stopper();
do{
while(pstate)
@ -144,6 +143,8 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_all_states
++state_count;
if(!(this->*proc)())
{
if(state_count > max_state_count)
raise_error(traits_inst, REG_ESPACE);
if((m_match_flags & match_partial) && (position == last))
m_has_partial_match = true;
if(false == unwind(false))
@ -235,6 +236,21 @@ inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::push_alt(
m_backup_state = pmp;
}
template <class BidiIterator, class Allocator, class traits, class Allocator2>
inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::push_non_greedy_repeat(const re_syntax_base* ps)
{
saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
--pmp;
if(pmp < m_stack_base)
{
extend_stack();
pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
--pmp;
}
new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
m_backup_state = pmp;
}
template <class BidiIterator, class Allocator, class traits, class Allocator2>
inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
{
@ -408,19 +424,16 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_rep()
if(take_second)
{
// store position in case we fail:
BidiIterator pos = position;
push_non_greedy_repeat(rep->next.p);
pstate = rep->alt.p;
if(match_all_states())
return true;
// failed alternative, reset posistion and fall through for repeat:
position = pos;
return true;
}
if((next_count->get_count() < rep->max) && take_first)
{
// increase the counter:
++(*next_count);
pstate = rep->next.p;
return match_all_states();
return true;
}
}
return false;
@ -1114,6 +1127,21 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_long_set_
return false;
}
template <class BidiIterator, class Allocator, class traits, class Allocator2>
bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_non_greedy_repeat(bool r)
{
saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
if(!r)
{
position = pmp->position;
pstate = pmp->pstate;
++(*next_count);
}
destroy(pmp++);
m_backup_state = pmp;
return r;
}
template <class BidiIterator, class Allocator, class traits, class Allocator2>
typename perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_proc_type const
perl_matcher<BidiIterator, Allocator, traits, Allocator2>::s_unwind_table[] =
@ -1131,6 +1159,7 @@ perl_matcher<BidiIterator, Allocator, traits, Allocator2>::s_unwind_table[] =
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_char_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_short_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_long_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_non_greedy_repeat,
};
}