#if defined(PERL_IN_UTF8_C) || defined(PERL_IN_REGCOMP_C) || defined(PERL_IN_REGEXEC_C)
+#define INVLIST_LEN_OFFSET 0 /* Number of elements in the inversion list */
+
+/* This is a combination of a version and data structure type, so that one
+ * being passed in can be validated to be an inversion list of the correct
+ * vintage. When the structure of the header is changed, a new random number
+ * in the range 2**31-1 should be generated. Then, if an auxiliary program
+ * doesn't change correspondingly, it will be discovered immediately */
+#define INVLIST_VERSION_ID_OFFSET 1
+#define INVLIST_VERSION_ID 1826693541
+
+#define INVLIST_OFFSET_OFFSET 2 /* 0 or 1 */
+/* The UV at this position contains either 0 or 1. If 0, the inversion list
+ * contains the code point U+00000, and begins at element [0] in the array,
+ * which always contains 0. If 1, the inversion list doesn't contain U+0000,
+ * and it begins at element [1]. Inverting an inversion list consists of
+ * adding or removing the 0 at the beginning of it. By reserving a space for
+ * that 0, inversion can be made very fast: we just flip this UV */
+
+/* For safety, when adding new elements, remember to #undef them at the end of
+ * the inversion list code section */
+
+#define HEADER_LENGTH (INVLIST_OFFSET_OFFSET + 1) /* includes 1 for the constant
+ 0 element */
+
/* An element is in an inversion list iff its index is even numbered: 0, 2, 4,
* etc */
#define ELEMENT_RANGE_MATCHES_INVLIST(i) (! ((i) & 1))
#define TO_INTERNAL_SIZE(x) (((x) + 1) * sizeof(UV))
#define FROM_INTERNAL_SIZE(x) (((x)/ sizeof(UV)) - 1)
+#define INVLIST_INITIAL_LEN 10
PERL_STATIC_INLINE UV*
S__invlist_array_init(pTHX_ SV* const invlist, const bool will_have_0)
U8* offset_addr;
if (initial_size < 0) {
- initial_size = 10;
+ initial_size = INVLIST_INITIAL_LEN;
}
/* Allocate the initial space */
*offset_addr = (U8) UV_MAX;
*get_invlist_previous_index_addr(new_list) = 0;
+#if HEADER_LENGTH != 3
+# error Need to regenerate INVLIST_VERSION_ID by running perl -E 'say int(rand 2**31-1)', and then changing the #if to the new length
+#endif
return new_list;
}
/* Return a pointer to a newly constructed inversion list, initialized to
* point to <list>, which has to be in the exact correct inversion list
* form, including internal fields. Thus this is a dangerous routine that
- * should not be used in the wrong hands. The passed in 'list' contains
- * several header fields at the beginning that are not part of the
- * inversion list body proper */
-
- const STRLEN length = (STRLEN) list[0];
- const UV version_id = list[1];
- const U8 offset = (U8) list[2];
-#define HEADER_LENGTH 3
- /* If any of the above changes in any way, you must change HEADER_LENGTH
- * (if appropriate) and regenerate INVLIST_VERSION_ID by running
- * perl -E 'say int(rand 2**31-1)'
- */
-#define INVLIST_VERSION_ID 1826693541/* This is a combination of a version and
- data structure type, so that one being
- passed in can be validated to be an
- inversion list of the correct vintage.
- */
+ * should not be used in the wrong hands */
SV* invlist = newSV_type(SVt_PVLV);
+ STRLEN length = (STRLEN) list[INVLIST_LEN_OFFSET];
+ U8 offset = (U8) list[INVLIST_OFFSET_OFFSET];
PERL_ARGS_ASSERT__NEW_INVLIST_C_ARRAY;
- if (version_id != INVLIST_VERSION_ID) {
+ if (list[INVLIST_VERSION_ID_OFFSET] != INVLIST_VERSION_ID) {
Perl_croak(aTHX_ "panic: Incorrect version for previously generated inversion list");
}
#endif
#undef HEADER_LENGTH
+#undef INVLIST_INITIAL_LENGTH
#undef TO_INTERNAL_SIZE
#undef FROM_INTERNAL_SIZE
+#undef INVLIST_LEN_OFFSET
+#undef INVLIST_OFFSET_OFFSET
#undef INVLIST_VERSION_ID
/* End of inversion list object */