s->posn = SvCUR(s->var);
else
s->posn = 0;
+ SvSETMAGIC(s->var);
return code;
}
PerlIOScalar_seek(pTHX_ PerlIO * f, Off_t offset, int whence)
{
PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
+ SvGETMAGIC(s->var);
STRLEN oldcur = SvCUR(s->var);
STRLEN newlen;
switch (whence) {
return s->posn;
}
+
+SSize_t
+PerlIOScalar_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
+{
+ if (!f)
+ return 0;
+ if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) {
+ PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+ SETERRNO(EBADF, SS_IVCHAN);
+ return 0;
+ }
+ {
+ PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
+ SV *sv = s->var;
+ char *p;
+ STRLEN len, got;
+ p = SvPV(sv, len);
+ got = len - (STRLEN)(s->posn);
+ if (got <= 0)
+ return 0;
+ if (got > (STRLEN)count)
+ got = (STRLEN)count;
+ Copy(p + (STRLEN)(s->posn), vbuf, got, STDCHAR);
+ s->posn += (Off_t)got;
+ return (SSize_t)got;
+ }
+}
+
SSize_t
PerlIOScalar_write(pTHX_ PerlIO * f, const void *vbuf, Size_t count)
{
PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
SV *sv = s->var;
char *dst;
+ SvGETMAGIC(sv);
if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND) {
dst = SvGROW(sv, SvCUR(sv) + count);
offset = SvCUR(sv);
if ((s->posn + count) > SvCUR(sv))
dst = SvGROW(sv, (STRLEN)s->posn + count);
else
- dst = SvPV_nolen(sv);
+ dst = SvPVX(sv);
offset = s->posn;
s->posn += count;
}
Move(vbuf, dst + offset, count, char);
if ((STRLEN) s->posn > SvCUR(sv))
SvCUR_set(sv, (STRLEN)s->posn);
- SvPOK_on(s->var);
+ SvPOK_on(sv);
+ SvSETMAGIC(sv);
return count;
}
else
{
PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
+ SvGETMAGIC(s->var);
return (STDCHAR *) SvPV_nolen(s->var);
}
return (STDCHAR *) NULL;
{
if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
+ SvGETMAGIC(s->var);
if (SvCUR(s->var) > (STRLEN) s->posn)
return SvCUR(s->var) - (STRLEN)s->posn;
else
{
if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
+ SvGETMAGIC(s->var);
return SvCUR(s->var);
}
return 0;
PerlIOScalar_set_ptrcnt(pTHX_ PerlIO * f, STDCHAR * ptr, SSize_t cnt)
{
PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
+ SvGETMAGIC(s->var);
s->posn = SvCUR(s->var) - cnt;
}
PerlIOScalar_arg,
PerlIOScalar_fileno,
PerlIOScalar_dup,
- PerlIOBase_read,
+ PerlIOScalar_read,
NULL, /* unread */
PerlIOScalar_write,
PerlIOScalar_seek,
$| = 1;
-use Test::More tests => 55;
+use Test::More tests => 69;
my $fh;
my $var = "aaa\n";
is(<$fh>, "42", "reading from non-string scalars");
close $fh;
-{ package P; sub TIESCALAR {bless{}} sub FETCH { "shazam" } }
+{ package P; sub TIESCALAR {bless{}} sub FETCH { "shazam" } sub STORE {} }
tie $p, P; open $fh, '<', \$p;
is(<$fh>, "shazam", "reading from magic scalars");
package MgUndef;
sub TIESCALAR { bless [] }
sub FETCH { $fetch++; return undef }
+ sub STORE {}
}
tie my $scalar, MgUndef;
ok(!seek(F, -150, SEEK_END), $!);
}
+# RT #43789: should respect tied scalar
+
+{
+ package TS;
+ my $s;
+ sub TIESCALAR { bless \my $x }
+ sub FETCH { $s .= ':F'; ${$_[0]} }
+ sub STORE { $s .= ":S($_[1])"; ${$_[0]} = $_[1] }
+
+ package main;
+
+ my $x;
+ $s = '';
+ tie $x, 'TS';
+ my $fh;
+
+ ok(open($fh, '>', \$x), 'open-write tied scalar');
+ $s .= ':O';
+ print($fh 'ABC');
+ $s .= ':P';
+ ok(seek($fh, 0, SEEK_SET));
+ $s .= ':SK';
+ print($fh 'DEF');
+ $s .= ':P';
+ ok(close($fh), 'close tied scalar - write');
+ is($s, ':F:S():O:F:S(ABC):P:F:SK:F:S(DEF):P', 'tied actions - write');
+ is($x, 'DEF', 'new value preserved');
+
+ $x = 'GHI';
+ $s = '';
+ ok(open($fh, '+<', \$x), 'open-read tied scalar');
+ $s .= ':O';
+ my $buf;
+ is(read($fh,$buf,2), 2, 'read1');
+ $s .= ':R';
+ is($buf, 'GH', 'buf1');
+ is(read($fh,$buf,2), 1, 'read2');
+ $s .= ':R';
+ is($buf, 'I', 'buf2');
+ is(read($fh,$buf,2), 0, 'read3');
+ $s .= ':R';
+ is($buf, '', 'buf3');
+ ok(close($fh), 'close tied scalar - read');
+ is($s, ':F:S(GHI):O:F:R:F:R:F:R', 'tied actions - read');
+}
+
+