#ifndef PERL_INVLIST_INLINE_H_
#define PERL_INVLIST_INLINE_H_
#if defined(PERL_IN_UTF8_C) \
|| defined(PERL_IN_REGCOMP_C) \
|| defined(PERL_IN_REGEXEC_C) \
|| defined(PERL_IN_TOKE_C) \
|| defined(PERL_IN_PP_C) \
|| defined(PERL_IN_OP_C) \
|| defined(PERL_IN_DOOP_C)
#define ELEMENT_RANGE_MATCHES_INVLIST(i) (! ((i) & 1))
#define PREV_RANGE_MATCHES_INVLIST(i) (! ELEMENT_RANGE_MATCHES_INVLIST(i))
#define TO_INTERNAL_SIZE(x) ((x) * sizeof(UV))
#define FROM_INTERNAL_SIZE(x) ((x)/ sizeof(UV))
PERL_STATIC_INLINE
bool
S_is_invlist(
const
SV*
const
invlist)
{
return
invlist != NULL && SvTYPE(invlist) == SVt_INVLIST;
}
PERL_STATIC_INLINE
bool
*
S_get_invlist_offset_addr(SV* invlist)
{
PERL_ARGS_ASSERT_GET_INVLIST_OFFSET_ADDR;
assert
(is_invlist(invlist));
return
&(((XINVLIST*) SvANY(invlist))->is_offset);
}
PERL_STATIC_INLINE UV
S__invlist_len(SV*
const
invlist)
{
PERL_ARGS_ASSERT__INVLIST_LEN;
assert
(is_invlist(invlist));
return
(SvCUR(invlist) == 0)
? 0
: FROM_INTERNAL_SIZE(SvCUR(invlist)) - *get_invlist_offset_addr(invlist);
}
PERL_STATIC_INLINE
bool
S__invlist_contains_cp(SV*
const
invlist,
const
UV cp)
{
IV index = _invlist_search(invlist, cp);
PERL_ARGS_ASSERT__INVLIST_CONTAINS_CP;
return
index >= 0 && ELEMENT_RANGE_MATCHES_INVLIST(index);
}
PERL_STATIC_INLINE UV*
S_invlist_array(SV*
const
invlist)
{
PERL_ARGS_ASSERT_INVLIST_ARRAY;
assert
(_invlist_len(invlist));
assert
(0 == *(SvPVX(invlist)));
return
((UV *) SvPVX(invlist) + *get_invlist_offset_addr(invlist));
}
#endif
#if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_OP_C) || defined(PERL_IN_DOOP_C)
PERL_STATIC_INLINE
void
S_invlist_extend(pTHX_ SV*
const
invlist,
const
UV new_max)
{
PERL_ARGS_ASSERT_INVLIST_EXTEND;
assert
(SvTYPE(invlist) == SVt_INVLIST);
SvGROW((SV *)invlist, TO_INTERNAL_SIZE(new_max + 1));
}
PERL_STATIC_INLINE
void
S_invlist_set_len(pTHX_ SV*
const
invlist,
const
UV len,
const
bool
offset)
{
PERL_UNUSED_CONTEXT;
PERL_ARGS_ASSERT_INVLIST_SET_LEN;
assert
(SvTYPE(invlist) == SVt_INVLIST);
SvCUR_set(invlist,
(len == 0)
? 0
: TO_INTERNAL_SIZE(len + offset));
assert
(SvLEN(invlist) == 0 || SvCUR(invlist) <= SvLEN(invlist));
}
PERL_STATIC_INLINE SV*
S_add_cp_to_invlist(pTHX_ SV* invlist,
const
UV cp) {
return
_add_range_to_invlist(invlist, cp, cp);
}
PERL_STATIC_INLINE UV
S_invlist_highest(SV*
const
invlist)
{
UV len = _invlist_len(invlist);
UV *array;
PERL_ARGS_ASSERT_INVLIST_HIGHEST;
if
(len == 0) {
return
0;
}
array = invlist_array(invlist);
return
(ELEMENT_RANGE_MATCHES_INVLIST(len - 1))
? UV_MAX
: array[len - 1] - 1;
}
#endif
#if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_OP_C)
PERL_STATIC_INLINE STRLEN*
S_get_invlist_iter_addr(SV* invlist)
{
PERL_ARGS_ASSERT_GET_INVLIST_ITER_ADDR;
assert
(is_invlist(invlist));
return
&(((XINVLIST*) SvANY(invlist))->iterator);
}
PERL_STATIC_INLINE
void
S_invlist_iterinit(SV* invlist)
{
PERL_ARGS_ASSERT_INVLIST_ITERINIT;
*get_invlist_iter_addr(invlist) = 0;
}
PERL_STATIC_INLINE
void
S_invlist_iterfinish(SV* invlist)
{
PERL_ARGS_ASSERT_INVLIST_ITERFINISH;
*get_invlist_iter_addr(invlist) = (STRLEN) UV_MAX;
}
STATIC
bool
S_invlist_iternext(SV* invlist, UV* start, UV* end)
{
STRLEN* pos = get_invlist_iter_addr(invlist);
UV len = _invlist_len(invlist);
UV *array;
PERL_ARGS_ASSERT_INVLIST_ITERNEXT;
if
(*pos >= len) {
*pos = (STRLEN) UV_MAX;
return
FALSE;
}
array = invlist_array(invlist);
*start = array[(*pos)++];
if
(*pos >= len) {
*end = UV_MAX;
}
else
{
*end = array[(*pos)++] - 1;
}
return
TRUE;
}
#endif
#ifndef PERL_IN_REGCOMP_C
# undef TO_INTERNAL_SIZE
# undef FROM_INTERNAL_SIZE
#endif
#endif /* PERL_INVLIST_INLINE_H_ */