diff options
Diffstat (limited to 'invlist_inline.h')
-rw-r--r-- | invlist_inline.h | 100 |
1 files changed, 95 insertions, 5 deletions
diff --git a/invlist_inline.h b/invlist_inline.h index ebb37b6543..8b28c21885 100644 --- a/invlist_inline.h +++ b/invlist_inline.h @@ -10,7 +10,7 @@ #define PERL_INVLIST_INLINE_H_ #if defined(PERL_IN_UTF8_C) \ - || defined(PERL_IN_REGCOMP_C) \ + || defined(PERL_IN_REGCOMP_ANY) \ || defined(PERL_IN_REGEXEC_C) \ || defined(PERL_IN_TOKE_C) \ || defined(PERL_IN_PP_C) \ @@ -93,7 +93,7 @@ S_invlist_array(SV* const invlist) } #endif -#if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_OP_C) || defined(PERL_IN_DOOP_C) +#if defined(PERL_IN_REGCOMP_ANY) || 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) @@ -161,7 +161,7 @@ S_invlist_highest(SV* const invlist) : array[len - 1] - 1; } -# if defined(PERL_IN_REGCOMP_C) +# if defined(PERL_IN_REGCOMP_ANY) PERL_STATIC_INLINE UV S_invlist_highest_range_start(SV* const invlist) @@ -199,7 +199,7 @@ S_invlist_highest_range_start(SV* const invlist) # endif #endif -#if defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_OP_C) +#if defined(PERL_IN_REGCOMP_ANY) || defined(PERL_IN_OP_C) PERL_STATIC_INLINE STRLEN* S_get_invlist_iter_addr(SV* invlist) @@ -275,11 +275,101 @@ S_invlist_iternext(SV* invlist, UV* start, UV* end) #endif -#ifndef PERL_IN_REGCOMP_C +#ifndef PERL_IN_REGCOMP_ANY /* These symbols are only needed later in regcomp.c */ # undef TO_INTERNAL_SIZE # undef FROM_INTERNAL_SIZE #endif +#ifdef PERL_IN_REGCOMP_ANY +PERL_STATIC_INLINE +bool +S_invlist_is_iterating(const SV* const invlist) +{ + PERL_ARGS_ASSERT_INVLIST_IS_ITERATING; + + /* get_invlist_iter_addr()'s sv is non-const only because it returns a + * value that can be used to modify the invlist, it doesn't modify the + * invlist itself */ + return *(get_invlist_iter_addr((SV*)invlist)) < (STRLEN) UV_MAX; +} + +PERL_STATIC_INLINE +SV * +S_invlist_contents(pTHX_ SV* const invlist, const bool traditional_style) +{ + /* Get the contents of an inversion list into a string SV so that they can + * be printed out. If 'traditional_style' is TRUE, it uses the format + * traditionally done for debug tracing; otherwise it uses a format + * suitable for just copying to the output, with blanks between ranges and + * a dash between range components */ + + UV start, end; + SV* output; + const char intra_range_delimiter = (traditional_style ? '\t' : '-'); + const char inter_range_delimiter = (traditional_style ? '\n' : ' '); + + if (traditional_style) { + output = newSVpvs("\n"); + } + else { + output = newSVpvs(""); + } + + PERL_ARGS_ASSERT_INVLIST_CONTENTS; + + assert(! invlist_is_iterating(invlist)); + + invlist_iterinit(invlist); + while (invlist_iternext(invlist, &start, &end)) { + if (end == UV_MAX) { + Perl_sv_catpvf(aTHX_ output, "%04" UVXf "%cINFTY%c", + start, intra_range_delimiter, + inter_range_delimiter); + } + else if (end != start) { + Perl_sv_catpvf(aTHX_ output, "%04" UVXf "%c%04" UVXf "%c", + start, + intra_range_delimiter, + end, inter_range_delimiter); + } + else { + Perl_sv_catpvf(aTHX_ output, "%04" UVXf "%c", + start, inter_range_delimiter); + } + } + + if (SvCUR(output) && ! traditional_style) {/* Get rid of trailing blank */ + SvCUR_set(output, SvCUR(output) - 1); + } + + return output; +} + +PERL_STATIC_INLINE +UV +S_invlist_lowest(SV* const invlist) +{ + /* Returns the lowest code point that matches an inversion list. This API + * has an ambiguity, as it returns 0 under either the lowest is actually + * 0, or if the list is empty. If this distinction matters to you, check + * for emptiness before calling this function */ + + UV len = _invlist_len(invlist); + UV *array; + + PERL_ARGS_ASSERT_INVLIST_LOWEST; + + if (len == 0) { + return 0; + } + + array = invlist_array(invlist); + + return array[0]; +} + +#endif + #endif /* PERL_INVLIST_INLINE_H_ */ |