summaryrefslogtreecommitdiff
path: root/regcomp.c
diff options
context:
space:
mode:
authorKarl Williamson <public@khwilliamson.com>2011-05-28 18:38:45 -0600
committerKarl Williamson <public@khwilliamson.com>2011-07-03 14:05:46 -0600
commitf3dc70d12790e82ff4a6e947fbd697a2152d0040 (patch)
treec08ad9d92c4bf11a7e61e15c20fb25f13fc50586 /regcomp.c
parent97b14ce75a908d3b10dc3ba9714c4514d32a0b43 (diff)
downloadperl-f3dc70d12790e82ff4a6e947fbd697a2152d0040.tar.gz
Add iterator for inversion lists
Diffstat (limited to 'regcomp.c')
-rw-r--r--regcomp.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/regcomp.c b/regcomp.c
index 02062a6fbb..1f9c33d1c0 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -5835,7 +5835,8 @@ S_reg_scan_name(pTHX_ RExC_state_t *pRExC_state, U32 flags)
* Some of the methods should always be private to the implementation, and some
* should eventually be made public */
-#define HEADER_LENGTH 0
+#define INVLIST_ITER_OFFSET 0
+#define HEADER_LENGTH (INVLIST_ITER_OFFSET + 1)
/* Internally things are UVs */
#define TO_INTERNAL_SIZE(x) ((x + HEADER_LENGTH) * sizeof(UV))
@@ -5905,6 +5906,9 @@ Perl__new_invlist(pTHX_ IV initial_size)
new_list = newSV(TO_INTERNAL_SIZE(initial_size));
invlist_set_len(new_list, 0);
+ /* Force iterinit() to be used to get iteration to work */
+ *get_invlist_iter_addr(new_list) = UV_MAX;
+
return new_list;
}
#endif
@@ -6362,10 +6366,58 @@ S_add_cp_to_invlist(pTHX_ SV* invlist, const UV cp) {
return add_range_to_invlist(invlist, cp, cp);
}
+PERL_STATIC_INLINE UV*
+S_get_invlist_iter_addr(pTHX_ SV* invlist)
+{
+ /* Return the address of the UV that contains the current iteration
+ * position */
+
+ PERL_ARGS_ASSERT_GET_INVLIST_ITER_ADDR;
+
+ return (UV *) (SvPVX(invlist) + (INVLIST_ITER_OFFSET * sizeof (UV)));
+}
+
+PERL_STATIC_INLINE void
+S_invlist_iterinit(pTHX_ SV* invlist) /* Initialize iterator for invlist */
+{
+ PERL_ARGS_ASSERT_INVLIST_ITERINIT;
+
+ *get_invlist_iter_addr(invlist) = 0;
+}
+
+STATIC bool
+S_invlist_iternext(pTHX_ SV* invlist, UV* start, UV* end)
+{
+ UV* pos = get_invlist_iter_addr(invlist);
+ UV len = invlist_len(invlist);
+ UV *array;
+
+ PERL_ARGS_ASSERT_INVLIST_ITERNEXT;
+
+ if (*pos >= len) {
+ *pos = UV_MAX; /* Force iternit() to be required next time */
+ return FALSE;
+ }
+
+ array = invlist_array(invlist);
+
+ *start = array[(*pos)++];
+
+ if (*pos >= len) {
+ *end = UV_MAX;
+ }
+ else {
+ *end = array[(*pos)++] - 1;
+ }
+
+ return TRUE;
+}
+
#undef HEADER_LENGTH
#undef INVLIST_INITIAL_LENGTH
#undef TO_INTERNAL_SIZE
#undef FROM_INTERNAL_SIZE
+#undef INVLIST_ITER_OFFSET
/* End of inversion list object */