EiMR |UV* |invlist_array |NN SV* const invlist
EiM |void |invlist_destroy |NN SV* const invlist
EsM |void |invlist_extend |NN SV* const invlist|const UV len
-EsMR |SV* |invlist_intersection |NN SV* const a|NN SV* const b
+EsM |void |invlist_intersection |NN SV* const a|NN SV* const b|NN SV** i
EiMR |UV |invlist_len |NN SV* const invlist
EiMR |UV |invlist_max |NN SV* const invlist
EiM |void |invlist_set_len |NN SV* const invlist|const UV len
EiM |void |invlist_set_max |NN SV* const invlist|const UV max
EiM |void |invlist_trim |NN SV* const invlist
-EsMR |SV* |invlist_union |NN SV* const a|NN SV* const b
+EsM |void |invlist_union |NN SV* const a|NN SV* const b|NN SV** output
#endif
Ap |void |taint_env
Ap |void |taint_proper |NULLOK const char* f|NN const char *const s
#define invlist_array(a) S_invlist_array(aTHX_ a)
#define invlist_destroy(a) S_invlist_destroy(aTHX_ a)
#define invlist_extend(a,b) S_invlist_extend(aTHX_ a,b)
-#define invlist_intersection(a,b) S_invlist_intersection(aTHX_ a,b)
+#define invlist_intersection(a,b,c) S_invlist_intersection(aTHX_ a,b,c)
#define invlist_len(a) S_invlist_len(aTHX_ a)
#define invlist_max(a) S_invlist_max(aTHX_ a)
#define invlist_set_len(a,b) S_invlist_set_len(aTHX_ a,b)
#define invlist_set_max(a,b) S_invlist_set_max(aTHX_ a,b)
#define invlist_trim(a) S_invlist_trim(aTHX_ a)
-#define invlist_union(a,b) S_invlist_union(aTHX_ a,b)
+#define invlist_union(a,b,c) S_invlist_union(aTHX_ a,b,c)
#define join_exact(a,b,c,d,e,f) S_join_exact(aTHX_ a,b,c,d,e,f)
#define make_trie(a,b,c,d,e,f,g,h) S_make_trie(aTHX_ a,b,c,d,e,f,g,h)
#define make_trie_failtable(a,b,c,d) S_make_trie_failtable(aTHX_ a,b,c,d)
#define PERL_ARGS_ASSERT_INVLIST_EXTEND \
assert(invlist)
-STATIC SV* S_invlist_intersection(pTHX_ SV* const a, SV* const b)
- __attribute__warn_unused_result__
+STATIC void S_invlist_intersection(pTHX_ SV* const a, SV* const b, SV** i)
__attribute__nonnull__(pTHX_1)
- __attribute__nonnull__(pTHX_2);
+ __attribute__nonnull__(pTHX_2)
+ __attribute__nonnull__(pTHX_3);
#define PERL_ARGS_ASSERT_INVLIST_INTERSECTION \
- assert(a); assert(b)
+ assert(a); assert(b); assert(i)
PERL_STATIC_INLINE UV S_invlist_len(pTHX_ SV* const invlist)
__attribute__warn_unused_result__
#define PERL_ARGS_ASSERT_INVLIST_TRIM \
assert(invlist)
-STATIC SV* S_invlist_union(pTHX_ SV* const a, SV* const b)
- __attribute__warn_unused_result__
+STATIC void S_invlist_union(pTHX_ SV* const a, SV* const b, SV** output)
__attribute__nonnull__(pTHX_1)
- __attribute__nonnull__(pTHX_2);
+ __attribute__nonnull__(pTHX_2)
+ __attribute__nonnull__(pTHX_3);
#define PERL_ARGS_ASSERT_INVLIST_UNION \
- assert(a); assert(b)
+ assert(a); assert(b); assert(output)
STATIC U32 S_join_exact(pTHX_ struct RExC_state_t *pRExC_state, regnode *scan, I32 *min, U32 flags, regnode *val, U32 depth)
__attribute__nonnull__(pTHX_1)
}
#endif
-STATIC SV*
-S_invlist_union(pTHX_ SV* const a, SV* const b)
+STATIC void
+S_invlist_union(pTHX_ SV* const a, SV* const b, SV** output)
{
- /* Return a new inversion list which is the union of two inversion lists.
+ /* Take the union of two inversion lists and point 'result' to it. If
+ * 'result' on input points to one of the two lists, the reference count to
+ * that list will be decremented.
* The basis for this comes from "Unicode Demystified" Chapter 13 by
* Richard Gillam, published by Addison-Wesley, and explained at some
* length there. The preface says to incorporate its examples into your
* XXX A potential performance improvement is to keep track as we go along
* if only one of the inputs contributes to the result, meaning the other
* is a subset of that one. In that case, we can skip the final copy and
- * return the larger of the input lists */
+ * return the larger of the input lists, but then outside code might need
+ * to keep track of whether to free the input list or not */
UV* array_a = invlist_array(a); /* a's array */
UV* array_b = invlist_array(b);
}
}
- return u;
+ /* We may be removing a reference to one of the inputs */
+ if (&a == output || &b == output) {
+ SvREFCNT_dec(*output);
+ }
+
+ *output = u;
+ return;
}
-STATIC SV*
-S_invlist_intersection(pTHX_ SV* const a, SV* const b)
+STATIC void
+S_invlist_intersection(pTHX_ SV* const a, SV* const b, SV** i)
{
- /* Return the intersection of two inversion lists. The basis for this
- * comes from "Unicode Demystified" Chapter 13 by Richard Gillam, published
- * by Addison-Wesley, and explained at some length there. The preface says
- * to incorporate its examples into your code at your own risk. In fact,
- * it had bugs
+ /* Take the intersection of two inversion lists and point 'i' to it. If
+ * 'i' on input points to one of the two lists, the reference count to that
+ * list will be decremented.
+ * The basis for this comes from "Unicode Demystified" Chapter 13 by
+ * Richard Gillam, published by Addison-Wesley, and explained at some
+ * length there. The preface says to incorporate its examples into your
+ * code at your own risk. In fact, it had bugs
*
* The algorithm is like a merge sort, and is essentially the same as the
* union above
}
}
- return r;
+ /* We may be removing a reference to one of the inputs */
+ if (&a == i || &b == i) {
+ SvREFCNT_dec(*i);
+ }
+
+ *i = r;
+ return;
}
STATIC SV*
range_invlist = _new_invlist(2);
_append_range_to_invlist(range_invlist, start, end);
- added_invlist = invlist_union(invlist, range_invlist);
+ invlist_union(invlist, range_invlist, &added_invlist);
/* The passed in list can be freed, as well as our temporary */
invlist_destroy(range_invlist);
* be checked. Get the intersection of this class and all the
* possible characters that are foldable. This can quickly narrow
* down a large class */
- fold_intersection = invlist_intersection(PL_utf8_foldable, nonbitmap);
+ invlist_intersection(PL_utf8_foldable, nonbitmap, &fold_intersection);
/* Now look at the foldable characters in this class individually */
fold_list = invlist_array(fold_intersection);
/* Combine the two lists into one. */
if (l1_fold_invlist) {
if (nonbitmap) {
- SV* temp = invlist_union(nonbitmap, l1_fold_invlist);
- invlist_destroy(nonbitmap);
- nonbitmap = temp;
+ invlist_union(nonbitmap, l1_fold_invlist, &nonbitmap);
invlist_destroy(l1_fold_invlist);
}
else {