+ if (*xlen < xAlloc - COLLXFRM_HDR_LEN) {
+
+ /* Some systems include a trailing NUL in the returned length.
+ * Ignore it, using a loop in case multiple trailing NULs are
+ * returned. */
+ while ( (*xlen) > 0
+ && *(xbuf + COLLXFRM_HDR_LEN + (*xlen) - 1) == '\0')
+ {
+ (*xlen)--;
+ }
+
+ /* If the first try didn't get it, it means our prediction was low.
+ * Modify the coefficients so that we predict a larger value in any
+ * future transformations */
+ if (! first_time) {
+ STRLEN needed = *xlen + 1; /* +1 For trailing NUL */
+ STRLEN computed_guess = PL_collxfrm_base
+ + (PL_collxfrm_mult * length_in_chars);
+
+ /* On zero-length input, just keep current slope instead of
+ * dividing by 0 */
+ const STRLEN new_m = (length_in_chars != 0)
+ ? needed / length_in_chars
+ : PL_collxfrm_mult;
+
+ DEBUG_Lv(PerlIO_printf(Perl_debug_log,
+ "%s: %d: initial size of %zu bytes for a length "
+ "%zu string was insufficient, %zu needed\n",
+ __FILE__, __LINE__,
+ computed_guess, length_in_chars, needed));
+
+ /* If slope increased, use it, but discard this result for
+ * length 1 strings, as we can't be sure that it's a real slope
+ * change */
+ if (length_in_chars > 1 && new_m > PL_collxfrm_mult) {
+#ifdef DEBUGGING
+ STRLEN old_m = PL_collxfrm_mult;
+ STRLEN old_b = PL_collxfrm_base;
+#endif
+ PL_collxfrm_mult = new_m;
+ PL_collxfrm_base = 1; /* +1 For trailing NUL */
+ computed_guess = PL_collxfrm_base
+ + (PL_collxfrm_mult * length_in_chars);
+ if (computed_guess < needed) {
+ PL_collxfrm_base += needed - computed_guess;
+ }
+
+ DEBUG_Lv(PerlIO_printf(Perl_debug_log,
+ "%s: %d: slope is now %zu; was %zu, base "
+ "is now %zu; was %zu\n",
+ __FILE__, __LINE__,
+ PL_collxfrm_mult, old_m,
+ PL_collxfrm_base, old_b));
+ }
+ else { /* Slope didn't change, but 'b' did */
+ const STRLEN new_b = needed
+ - computed_guess
+ + PL_collxfrm_base;
+ DEBUG_Lv(PerlIO_printf(Perl_debug_log,
+ "%s: %d: base is now %zu; was %zu\n",
+ __FILE__, __LINE__,
+ new_b, PL_collxfrm_base));
+ PL_collxfrm_base = new_b;
+ }
+ }
+