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 # ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
# undef BOOST_REGEX_HAS_MS_STACK_GUARD # undef BOOST_REGEX_HAS_MS_STACK_GUARD
# endif # endif
namespace boost{ namespace re_detail{ # ifndef BOOST_REGEX_MAX_CACHE_BLOCKS
BOOST_REGEX_DECL void* BOOST_REGEX_CALL get_mem_block(); # define BOOST_REGEX_MAX_CACHE_BLOCKS BOOST_REGEX_MAX_BLOCKS
BOOST_REGEX_DECL void BOOST_REGEX_CALL release_mem_block(void*); # endif
} }
#endif #endif

View File

@ -77,3 +77,9 @@
// used by the non-recursive algorithm. // used by the non-recursive algorithm.
// #define BOOST_REGEX_MAX_BLOCKS 1024 // #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. * LOCATION: see http://www.boost.org for most recent version.
* FILE mem_block_cache.hpp * FILE mem_block_cache.hpp
* VERSION see <boost/version.hpp> * VERSION see <boost/version.hpp>
* DESCRIPTION: Definitions of perl_matcher member functions that are * DESCRIPTION: memory block cache used by the non-recursive matcher.
* specific to the non-recursive implementation.
*/ */
#ifndef BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP #ifndef BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP
#define BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP #define BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP
#include <new> #include <new>
#include <boost/regex/v4/regex_synch.hpp>
#ifdef __BORLANDC__ #ifdef __BORLANDC__
# pragma option push -a8 -b -Vx -Ve -pc -w-8027 # pragma option push -a8 -b -Vx -Ve -pc -w-8027
@ -39,7 +39,9 @@ struct mem_block_node
struct mem_block_cache struct mem_block_cache
{ {
// this member has to be statically initialsed:
mem_block_node* next; mem_block_node* next;
unsigned cached_blocks;
~mem_block_cache() ~mem_block_cache()
{ {
@ -52,19 +54,33 @@ struct mem_block_cache
} }
void* get() 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; mem_block_node* result = next;
next = next->next; next = next->next;
--cached_blocks;
return result; return result;
} }
return ::operator new(BOOST_REGEX_BLOCKSIZE); return ::operator new(BOOST_REGEX_BLOCKSIZE);
} }
void put(void* p) void put(void* p)
{ {
mem_block_node* old = static_cast<mem_block_node*>(p); #ifdef BOOST_HAS_THREADS
old->next = next; re_detail::cs_guard g(*re_detail::p_re_lock);
next = old; #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_char_repeat(bool);
bool unwind_short_set_repeat(bool); bool unwind_short_set_repeat(bool);
bool unwind_long_set_repeat(bool); bool unwind_long_set_repeat(bool);
bool unwind_non_greedy_repeat(bool);
void destroy_single_repeat(); void destroy_single_repeat();
void push_matched_paren(int index, const sub_match<BidiIterator>& sub); void push_matched_paren(int index, const sub_match<BidiIterator>& sub);
void push_recursion_stopper(); void push_recursion_stopper();
@ -391,6 +392,7 @@ private:
void push_alt(const re_syntax_base* ps); void push_alt(const re_syntax_base* ps);
void push_repeater_count(int i, repeater_count<BidiIterator>** s); 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_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: // pointer to base of stack:

View File

@ -97,6 +97,7 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match()
#ifdef BOOST_REGEX_NON_RECURSIVE #ifdef BOOST_REGEX_NON_RECURSIVE
save_state_init init(&m_stack_base, &m_backup_state); save_state_init init(&m_stack_base, &m_backup_state);
used_block_count = BOOST_REGEX_MAX_BLOCKS; used_block_count = BOOST_REGEX_MAX_BLOCKS;
try{
#endif #endif
// reset our state machine: // reset our state machine:
@ -111,6 +112,17 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match()
return false; return false;
return m_result[0].second == last; 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 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
}__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) }__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode())
{ {
@ -134,6 +146,7 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::find()
#ifdef BOOST_REGEX_NON_RECURSIVE #ifdef BOOST_REGEX_NON_RECURSIVE
save_state_init init(&m_stack_base, &m_backup_state); save_state_init init(&m_stack_base, &m_backup_state);
used_block_count = BOOST_REGEX_MAX_BLOCKS; used_block_count = BOOST_REGEX_MAX_BLOCKS;
try{
#endif #endif
state_count = 0; state_count = 0;
@ -180,6 +193,17 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::find()
matcher_proc_type proc = s_find_vtable[type]; matcher_proc_type proc = s_find_vtable[type];
return (this->*proc)(); 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 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
}__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) }__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_combining,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_soft_buffer_end, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_soft_buffer_end,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_restart_continue, &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) #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_dot_repeat_fast, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_dot_repeat_fast,
#else #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_char_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_set_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_long_set_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_long_set_repeat,
#endif
}; };
template <class BidiIterator, class Allocator, class traits, class Allocator2> 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_fast_dot = 9,
saved_state_rep_char = 10, saved_state_rep_char = 10,
saved_state_rep_short_set = 11, 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 struct saved_state
@ -134,8 +135,6 @@ struct saved_single_repeat : public saved_state
template <class BidiIterator, class Allocator, class traits, class Allocator2> template <class BidiIterator, class Allocator, class traits, class Allocator2>
bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_all_states() 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(); push_recursion_stopper();
do{ do{
while(pstate) while(pstate)
@ -144,6 +143,8 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_all_states
++state_count; ++state_count;
if(!(this->*proc)()) if(!(this->*proc)())
{ {
if(state_count > max_state_count)
raise_error(traits_inst, REG_ESPACE);
if((m_match_flags & match_partial) && (position == last)) if((m_match_flags & match_partial) && (position == last))
m_has_partial_match = true; m_has_partial_match = true;
if(false == unwind(false)) if(false == unwind(false))
@ -235,6 +236,21 @@ inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::push_alt(
m_backup_state = pmp; 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> 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) 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) if(take_second)
{ {
// store position in case we fail: // store position in case we fail:
BidiIterator pos = position; push_non_greedy_repeat(rep->next.p);
pstate = rep->alt.p; pstate = rep->alt.p;
if(match_all_states()) return true;
return true;
// failed alternative, reset posistion and fall through for repeat:
position = pos;
} }
if((next_count->get_count() < rep->max) && take_first) if((next_count->get_count() < rep->max) && take_first)
{ {
// increase the counter: // increase the counter:
++(*next_count); ++(*next_count);
pstate = rep->next.p; pstate = rep->next.p;
return match_all_states(); return true;
} }
} }
return false; return false;
@ -1114,6 +1127,21 @@ bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_long_set_
return false; 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> template <class BidiIterator, class Allocator, class traits, class Allocator2>
typename perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_proc_type const typename perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_proc_type const
perl_matcher<BidiIterator, Allocator, traits, Allocator2>::s_unwind_table[] = 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_char_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_short_set_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_long_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_non_greedy_repeat,
}; };
} }