summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c35
1 files changed, 11 insertions, 24 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 799baa456b..0b759035ad 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -482,7 +482,6 @@ PP(pp_formline)
NV value;
bool gotsome = FALSE; /* seen at least one non-blank item on this line */
STRLEN len; /* length of current sv */
- STRLEN linemax; /* estimate of output size in bytes */
bool item_is_utf8 = FALSE;
bool targ_is_utf8 = FALSE;
const char *fmt;
@@ -505,10 +504,11 @@ PP(pp_formline)
SvTAINTED_on(PL_formtarget);
if (DO_UTF8(PL_formtarget))
targ_is_utf8 = TRUE;
- /* this is an initial estimate of how much output buffer space
- * to allocate. It may be exceeded later */
- linemax = (SvCUR(formsv) * (IN_BYTES ? 1 : 3) + 1);
- t = SvGROW(PL_formtarget, len + linemax + 1);
+ /* Usually the output data will be the same size as the format,
+ * so this is a good first guess. Later on, @* or utf8 upgrades
+ * may trigger further growing.
+ */
+ t = SvGROW(PL_formtarget, len + SvCUR(formsv) + 1);
/* XXX from now onwards, SvCUR(PL_formtarget) is invalid */
t += len;
f = SvPV_const(formsv, len);
@@ -761,14 +761,12 @@ PP(pp_formline)
* if trans, translate certain characters during the copy */
{
U8 *tmp = NULL;
- STRLEN grow = 0;
+ STRLEN cur = t - SvPVX_const(PL_formtarget);
- SvCUR_set(PL_formtarget,
- t - SvPVX_const(PL_formtarget));
+ SvCUR_set(PL_formtarget, cur);
if (targ_is_utf8 && !item_is_utf8) {
source = tmp = bytes_to_utf8(source, &to_copy);
- grow = to_copy;
} else {
if (item_is_utf8 && !targ_is_utf8) {
U8 *s;
@@ -776,14 +774,10 @@ PP(pp_formline)
a problem we have a simple solution for.
Don't need get magic. */
sv_utf8_upgrade_nomg(PL_formtarget);
+ cur = SvCUR(PL_formtarget); /* may have changed */
targ_is_utf8 = TRUE;
/* re-calculate linemark */
s = (U8*)SvPVX(PL_formtarget);
- /* the bytes we initially allocated to append the
- * whole line may have been gobbled up during the
- * upgrade, so allocate a whole new line's worth
- * for safety */
- grow = linemax;
while (linemark--)
s += UTF8SKIP(s);
linemark = s - (U8*)SvPVX(PL_formtarget);
@@ -791,17 +785,10 @@ PP(pp_formline)
/* Easy. They agree. */
assert (item_is_utf8 == targ_is_utf8);
}
- if (!trans)
- /* @* and ^* are the only things that can exceed
- * the linemax, so grow by the output size, plus
- * a whole new form's worth in case of any further
- * output */
- grow = linemax + to_copy;
- if (grow)
- SvGROW(PL_formtarget, SvCUR(PL_formtarget) + grow + 1);
- t = SvPVX(PL_formtarget) + SvCUR(PL_formtarget);
+ t = SvGROW(PL_formtarget, cur + to_copy + 1) + cur;
Copy(source, t, to_copy, char);
+
if (trans) {
/* blank out ~ or control chars, depending on trans.
* works on bytes not chars, so relies on not
@@ -817,7 +804,7 @@ PP(pp_formline)
}
t += to_copy;
- SvCUR_set(PL_formtarget, SvCUR(PL_formtarget) + to_copy);
+ SvCUR_set(PL_formtarget, cur + to_copy);
if (tmp)
Safefree(tmp);
break;