Skip to content

Commit

Permalink
[pmc] add missing StringHandle methods
Browse files Browse the repository at this point in the history
Similar to the FileHandle PMC: tell, seek, peek.
Add more error handling to StringHandle->seek (out of bounds)
Add testcase t/pmc/stringhandle_26

Fixes GH #1011
  • Loading branch information
Reini Urban committed Feb 16, 2016
1 parent 5976fa2 commit d8ae34f
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 5 deletions.
8 changes: 7 additions & 1 deletion src/io/stringhandle.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,10 @@ io_stringhandle_seek(PARROT_INTERP, ARGMOD(PMC *handle), const PIOOFF_T offset,
INTVAL old_offs;
STRING *stringhandle;
INTVAL read_offs = 0;
/* TODO: Need more error checking */
INTVAL buffer_size;
GETATTR_StringHandle_stringhandle(interp, handle, stringhandle);
buffer_size = stringhandle->_buflen;

switch (whence) {
case SEEK_SET:
/* Absolute seek, start from the beginning of the string */
Expand All @@ -420,6 +423,9 @@ io_stringhandle_seek(PARROT_INTERP, ARGMOD(PMC *handle), const PIOOFF_T offset,
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
"Cannot seek with mode %d", whence);
}
if (read_offs < 0 || read_offs >= buffer_size)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
"seek to %ld out of bounds", read_offs);
SETATTR_StringHandle_read_offset(interp, handle, read_offs);
return (PIOOFF_T)read_offs;
}
Expand Down
59 changes: 57 additions & 2 deletions src/pmc/stringhandle.pmc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (C) 2008-2014, Parrot Foundation.
Copyright (C) 2008-2016, Parrot Foundation.

=head1 NAME

Expand Down Expand Up @@ -152,7 +152,7 @@ Mark active stringhandle data as live.

=item C<INTVAL get_bool()>

Returns whether the StringHandle has reached the end of the file.
Returns whether the StringHandle has reached the end of the buffer.

=cut

Expand Down Expand Up @@ -390,6 +390,61 @@ string data).
RETURN(INTVAL 0);
}

/*

=item C<METHOD tell()>

Get the current position in the stream. 2 C<INTVAL>s are returned. The first is
the position. The second is the position shifted down by 32 bits to handle
overflows on 32-bit systems.

=cut

*/

METHOD tell() :no_wb {
PIOOFF_T pos;
GET_ATTR_read_offset(INTERP, SELF, pos);
RETURN(INTVAL pos, INTVAL pos>>32);
}

/*

=item C<METHOD seek(INTVAL whence, INTVAL offs, INTVAL offs_overflow)>

Set the position to an offset specified by C<offs> (and optionally
C<offs_overflow>). C<whence> determines from where in the buffer the
offset is taken.

Whence Value Meaning
0 Seek from the beginning of the buffer
1 Seek from the current position
2 Seek from the end of the buffer

=cut

*/

METHOD seek(INTVAL whence, INTVAL offs) {
IO_VTABLE * vtable;
GETATTR_StringHandle_io_vtable(INTERP, SELF, vtable);
vtable->seek(INTERP, SELF, offs, whence);
}

/*

=item C<METHOD peek()>

Returns the next byte from the stream, but does not remove it.

=cut

*/

METHOD peek() :no_wb {
STRING * const s = Parrot_io_peek(INTERP, SELF);
RETURN(STRING* s);
}

/*

Expand Down
51 changes: 49 additions & 2 deletions t/pmc/stringhandle.t
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!perl
# Copyright (C) 2006-2010, Parrot Foundation.
# Copyright (C) 2006-2016, Parrot Foundation.

use strict;
use warnings;
use lib qw( . lib ../lib ../../lib );

use Test::More;
use Parrot::Test tests => 25;
use Parrot::Test tests => 26;

=head1 NAME
Expand Down Expand Up @@ -720,6 +720,53 @@ CODE
ok
OUTPUT

# GH 1011 FileHandle analog methods
pir_output_is( <<'CODE', <<"OUTPUT", "seek/tell/peek stringhandle" );
.sub 'main' :main
.local pmc ifh
ifh = new ['StringHandle']
ifh.'encoding'('utf8')
ifh.'open'('README.pod', 'rw')
ifh.'puts'('# Copyright (C) 2001-2014, Parrot Foundation.')
ifh.'seek'(0, 27)
$S0 = ifh.'read'(17)
if $S0 == 'Parrot Foundation' goto ok_1
print 'not '
print $S0
ok_1:
say 'ok 1 - seek 0,28'
$I0 = ifh.'tell'()
if $I0 == 45 goto ok_2
print 'not '
print $I0
ok_2:
say 'ok 2 - tell'
$S0 = ifh.'peek'() # one byte
if $S0 == '.' goto ok_3
print 'not '
print $S0
ok_3:
say 'ok 3 - peek value'
$I0 = ifh.'tell'()
if $I0 == 45 goto ok_4
print 'not '
print $I0
ok_4:
say 'ok 4 - peek does not advance'
ifh.'close'()
.end
CODE
ok 1 - seek 0,28
ok 2 - tell
ok 3 - peek value
ok 4 - peek does not advance
OUTPUT


# GH #465
# L<PDD22/I\/O PMC API/=item get_fd>
# NOTES: this is going to be platform dependent
Expand Down

0 comments on commit d8ae34f

Please sign in to comment.