📄 regex_compile.hpp
字号:
/*
*
* Copyright (c) 1998-2002
* Dr John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE regex_compile.hpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: Declares reg_expression<> member functions. This is
* an internal header file, do not include directly.
*/
#ifndef BOOST_REGEX_COMPILE_HPP
#define BOOST_REGEX_COMPILE_HPP
namespace boost{
#ifdef __BORLANDC__
#pragma option push -a8 -b -Vx -Ve -pc -w-8004
#endif
namespace re_detail{
template <class traits>
struct kmp_translator
{
typedef typename traits::char_type char_type;
bool icase;
const traits* pt;
kmp_translator(bool c, traits* p) : icase(c), pt(p) {}
char_type operator()(char_type c)
{
return pt->translate(c, icase);
}
};
template <class charT, class traits_type, class Allocator>
bool BOOST_REGEX_CALL re_maybe_set_member(charT c,
const re_set_long* set_,
const reg_expression<charT, traits_type, Allocator>& e)
{
const charT* p = reinterpret_cast<const charT*>(set_+1);
bool icase = e.flags() & regbase::icase;
charT col = e.get_traits().translate(c, icase);
for(unsigned int i = 0; i < set_->csingles; ++i)
{
if(col == *p)
return set_->isnot ? false : true;
while(*p)++p;
++p; // skip null
}
return set_->isnot ? true : false;
}
} // namespace re_detail
template <class charT, class traits, class Allocator>
inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* _map, unsigned char mask, const re_detail::_wide_type&)
{
if((traits_size_type)(traits_uchar_type)c >= 256)
return true;
return BOOST_REGEX_MAKE_BOOL(_map[(traits_uchar_type)c] & mask);
}
template <class charT, class traits, class Allocator>
inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::can_start(charT c, const unsigned char* _map, unsigned char mask, const re_detail::_narrow_type&)
{
return BOOST_REGEX_MAKE_BOOL(_map[(traits_uchar_type)c] & mask);
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>::reg_expression(const Allocator& a)
: regbase(), data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
{
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, flag_type f, const Allocator& a)
: data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
{
set_expression(p, f | regbase::use_except);
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>::reg_expression(const charT* p1, const charT* p2, flag_type f, const Allocator& a)
: data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
{
set_expression(p1, p2, f | regbase::use_except);
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>::reg_expression(const charT* p, size_type len, flag_type f, const Allocator& a)
: data(a), pkmp(0), error_code_(REG_EMPTY), _expression(0)
{
set_expression(p, p + len, f | regbase::use_except);
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>::reg_expression(const reg_expression<charT, traits, Allocator>& e)
: regbase(e), data(e.allocator()), pkmp(0), error_code_(REG_EMPTY), _expression(0)
{
//
// we do a deep copy only if e is a valid expression, otherwise fail.
//
if(e.error_code() == 0)
{
const charT* pe = e.expression();
set_expression(pe, pe + e._expression_len, e.flags() | regbase::use_except);
}
else
{
_flags = e.flags() & ~(regbase::use_except);
fail(e.error_code());
}
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>::~reg_expression()
{
if(pkmp)
re_detail::kmp_free(pkmp, data.allocator());
}
template <class charT, class traits, class Allocator>
reg_expression<charT, traits, Allocator>& BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator=(const reg_expression<charT, traits, Allocator>& e)
{
//
// we do a deep copy only if e is a valid expression, otherwise fail.
//
if(this == &e) return *this;
_flags = use_except;
fail(e.error_code());
if(error_code() == 0)
set_expression(e._expression, e._expression + e._expression_len, e.flags() | regbase::use_except);
return *this;
}
template <class charT, class traits, class Allocator>
inline bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator==(const reg_expression<charT, traits, Allocator>& e)const
{
return (_flags == e.flags())
&& (_expression_len == e._expression_len)
&& (std::memcmp(_expression, e._expression, _expression_len * sizeof(charT)) == 0);
}
template <class charT, class traits, class Allocator>
bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::operator<(const reg_expression<charT, traits, Allocator>& e)const
{
//
// we can't offer a diffinitive ordering, but we can be consistant:
if(_flags != e.flags()) return _flags < e.flags();
if(_expression_len != e._expression_len) return _expression_len < e._expression_len;
return std::memcmp(expression(), e.expression(), _expression_len);
}
template <class charT, class traits, class Allocator>
Allocator BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::allocator()const
{
return data.allocator();
}
template <class charT, class traits, class Allocator>
Allocator BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::get_allocator()const
{
return data.allocator();
}
template <class charT, class traits, class Allocator>
unsigned int BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_inner_set(const charT*& first, const charT* last)
{
//
// we have an inner [...] construct
//
jm_assert(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) == traits_type::syntax_open_set);
const charT* base = first;
while( (first != last)
&& (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*first) != traits_type::syntax_close_set) )
++first;
if(first == last)
return 0;
++first;
if((first-base) < 5)
return 0;
if(*(base+1) != *(first-2))
return 0;
unsigned int result = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+1));
if((result == traits_type::syntax_colon) && ((first-base) == 5))
{
unsigned type = traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*(base+2));
if((type == traits_type::syntax_left_word) || (type == traits_type::syntax_right_word))
return type;
}
return ((result == traits_type::syntax_colon) || (result == traits_type::syntax_dot) || (result == traits_type::syntax_equal)) ? result : 0;
}
template <class charT, class traits, class Allocator>
bool BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::skip_space(const charT*& first, const charT* last)
{
//
// returns true if we get to last:
//
while((first != last) && (traits_inst.is_class(*first, traits_type::char_class_space) == true))
{
++first;
}
return first == last;
}
template <class charT, class traits, class Allocator>
void BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_range(const charT*& ptr, const charT* end, unsigned& min, unsigned& max)
{
//
// we have {x} or {x,} or {x,y} NB no spaces inside braces
// anything else is illegal
// On input ptr points to "{"
//
++ptr;
if(skip_space(ptr, end))
{
fail(REG_EBRACE);
return;
}
if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_digit)
{
fail(REG_BADBR);
return;
}
min = traits_inst.toi(ptr, end, 10);
if(skip_space(ptr, end))
{
fail(REG_EBRACE);
return;
}
if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_comma)
{
//we have a second interval:
++ptr;
if(skip_space(ptr, end))
{
fail(REG_EBRACE);
return;
}
if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) == traits_type::syntax_digit)
max = traits_inst.toi(ptr, end, 10);
else
max = (unsigned)-1;
}
else
max = min;
// validate input:
if(skip_space(ptr, end))
{
fail(REG_EBRACE);
return;
}
if(max < min)
{
fail(REG_ERANGE);
return;
}
if(_flags & bk_braces)
{
if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_slash)
{
fail(REG_BADBR);
return;
}
else
{
// back\ is OK now check the }
++ptr;
if((ptr == end) || (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_close_brace))
{
fail(REG_BADBR);
return;
}
}
}
else if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)*ptr) != traits_type::syntax_close_brace)
{
fail(REG_BADBR);
return;
}
}
template <class charT, class traits, class Allocator>
charT BOOST_REGEX_CALL reg_expression<charT, traits, Allocator>::parse_escape(const charT*& first, const charT* last)
{
charT c(*first);
traits_size_type c_unsigned = (traits_size_type)(traits_uchar_type)*first;
// this is only used for the switch(), but cannot be folded in
// due to a bug in Comeau 4.2.44beta3
traits_size_type syntax = traits_inst.syntax_type(c_unsigned);
switch(syntax)
{
case traits_type::syntax_a:
c = '\a';
++first;
break;
case traits_type::syntax_f:
c = '\f';
++first;
break;
case traits_type::syntax_n:
c = '\n';
++first;
break;
case traits_type::syntax_r:
c = '\r';
++first;
break;
case traits_type::syntax_t:
c = '\t';
++first;
break;
case traits_type::syntax_v:
c = '\v';
++first;
break;
case traits_type::syntax_x:
++first;
if(first == last)
{
fail(REG_EESCAPE);
break;
}
// maybe have \x{ddd}
if(traits_inst.syntax_type((traits_size_type)(traits_uchar_type)(*first)) == traits_type::syntax_open_brace)
{
++first;
if(first == last)
{
fail(REG_EESCAPE);
break;
}
if(traits_inst.is_class(*first, traits_type::char_class_xdigit) == false)
{
fail(REG_BADBR);
break;
}
c = (charT)traits_inst.toi(first, last, -16);
if((first == last) || (traits_inst.syntax_type((traits_size_type)(traits_uchar_type)(*first)) != traits_type::syntax_close_brace))
{
fail(REG_BADBR);
}
++first;
break;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -