Skip to content

Commit ee3f55a

Browse files
committed
First tests for file ops, plus fixes on JVM.
1 parent d3cfdd6 commit ee3f55a

File tree

7 files changed

+88
-11
lines changed

7 files changed

+88
-11
lines changed

src/vm/jvm/QAST/Compiler.nqp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,7 @@ QAST::OperationsJAST.map_classlib_core_op('getstdout', $TYPE_OPS, 'getstdout', [
18901890
QAST::OperationsJAST.map_classlib_core_op('getstderr', $TYPE_OPS, 'getstderr', [], $RT_OBJ, :tc);
18911891
QAST::OperationsJAST.map_classlib_core_op('setencoding', $TYPE_OPS, 'setencoding', [$RT_OBJ, $RT_STR], $RT_OBJ, :tc);
18921892
QAST::OperationsJAST.map_classlib_core_op('tellfh', $TYPE_OPS, 'tellfh', [$RT_OBJ], $RT_INT, :tc);
1893+
QAST::OperationsJAST.map_classlib_core_op('writefh', $TYPE_OPS, 'writefh', [$RT_OBJ, $RT_OBJ], $RT_OBJ, :tc);
18931894
QAST::OperationsJAST.map_classlib_core_op('printfh', $TYPE_OPS, 'printfh', [$RT_OBJ, $RT_STR], $RT_STR, :tc);
18941895
QAST::OperationsJAST.map_classlib_core_op('sayfh', $TYPE_OPS, 'sayfh', [$RT_OBJ, $RT_STR], $RT_STR, :tc);
18951896
QAST::OperationsJAST.map_classlib_core_op('readlinefh', $TYPE_OPS, 'readlinefh', [$RT_OBJ], $RT_STR, :tc);

src/vm/jvm/runtime/org/perl6/nqp/io/FileHandle.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ public void seek(ThreadContext tc, long offset, long whence) {
7676

7777
public long tell(ThreadContext tc) {
7878
try {
79-
return chan.position();
79+
long position = chan.position();
80+
return readBuffer != null ? position - readBuffer.remaining() : position;
8081
} catch (IOException e) {
8182
throw ExceptionHandling.dieInternal(tc, e);
8283
}
@@ -95,8 +96,8 @@ public synchronized String slurp(ThreadContext tc) {
9596
int total = 0;
9697
int read;
9798
if (readBuffer != null) {
98-
buffers.add(ByteBuffer.wrap(readBuffer.array(), readBuffer.position(),
99-
readBuffer.limit() - readBuffer.position()));
99+
total = readBuffer.limit() - readBuffer.position();
100+
buffers.add(ByteBuffer.wrap(readBuffer.array(), readBuffer.position(), total));
100101
readBuffer = null;
101102
}
102103
while ((read = chan.read(curBuffer)) != -1) {
@@ -127,6 +128,7 @@ public synchronized String readline(ThreadContext tc) {
127128
/* End of file, so what we have is fine. */
128129
eof = true;
129130
foundLine = true;
131+
readBuffer.flip();
130132
break;
131133
}
132134
readBuffer.flip();
@@ -165,8 +167,11 @@ private String decodeBuffers(ArrayList<ByteBuffer> buffers, int total) throws IO
165167
// Copy to a single buffer and decode (could be smarter, but need
166168
// to be wary as UTF-8 chars may span a buffer boundary).
167169
ByteBuffer allBytes = ByteBuffer.allocate(total);
168-
for (ByteBuffer bb : buffers)
169-
allBytes.put(bb.array(), 0, bb.limit());
170+
for (ByteBuffer bb : buffers) {
171+
int amount = total < bb.limit() ? total : bb.limit();
172+
allBytes.put(bb.array(), 0, amount);
173+
total -= amount;
174+
}
170175
allBytes.rewind();
171176
return dec.decode(allBytes).toString();
172177
}
@@ -175,9 +180,8 @@ public boolean eof(ThreadContext tc) {
175180
return eof;
176181
}
177182

178-
public void print(ThreadContext tc, String s) {
183+
public void write(ThreadContext tc, ByteBuffer buffer) {
179184
try {
180-
ByteBuffer buffer = enc.encode(CharBuffer.wrap(s));
181185
int toWrite = buffer.limit();
182186
int written = 0;
183187
while (written < toWrite) {
@@ -186,7 +190,16 @@ public void print(ThreadContext tc, String s) {
186190
}
187191
} catch (IOException e) {
188192
throw ExceptionHandling.dieInternal(tc, e);
189-
}
193+
}
194+
}
195+
196+
public void print(ThreadContext tc, String s) {
197+
try {
198+
ByteBuffer buffer = enc.encode(CharBuffer.wrap(s));
199+
write(tc, buffer);
200+
} catch (IOException e) {
201+
throw ExceptionHandling.dieInternal(tc, e);
202+
}
190203
}
191204

192205
public void say(ThreadContext tc, String s) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package org.perl6.nqp.io;
22

3+
import java.nio.ByteBuffer;
4+
35
import org.perl6.nqp.runtime.ThreadContext;
46

57
public interface IIOSyncWritable {
68
public void print(ThreadContext tc, String s);
79
public void say(ThreadContext tc, String s);
10+
public void write(ThreadContext tc, ByteBuffer bb);
811
}

src/vm/jvm/runtime/org/perl6/nqp/io/StandardWriteHandle.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public void setEncoding(ThreadContext tc, Charset cs) {
4040
dec = cs.newDecoder();
4141
}
4242

43+
public void write(ThreadContext tc, ByteBuffer buffer) {
44+
byte[] bytes = buffer.array();
45+
ps.write(bytes, 0, buffer.limit());
46+
}
47+
4348
public void print(ThreadContext tc, String s) {
4449
try {
4550
ByteBuffer buffer = enc.encode(CharBuffer.wrap(s));

src/vm/jvm/runtime/org/perl6/nqp/runtime/Ops.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,23 @@ public static long tellfh(SixModelObject obj, ThreadContext tc) {
403403
}
404404
}
405405

406+
public static SixModelObject writefh(SixModelObject obj, SixModelObject buf, ThreadContext tc) {
407+
ByteBuffer bb = decode8(buf, tc);
408+
if (obj instanceof IOHandleInstance) {
409+
IOHandleInstance h = (IOHandleInstance)obj;
410+
if (h.handle instanceof IIOSyncWritable)
411+
((IIOSyncWritable)h.handle).write(tc, bb);
412+
else
413+
throw ExceptionHandling.dieInternal(tc,
414+
"This handle does not support print");
415+
}
416+
else {
417+
throw ExceptionHandling.dieInternal(tc,
418+
"printfh requires an object with the IOHandle REPR");
419+
}
420+
return buf;
421+
}
422+
406423
public static String printfh(SixModelObject obj, String data, ThreadContext tc) {
407424
if (obj instanceof IOHandleInstance) {
408425
IOHandleInstance h = (IOHandleInstance)obj;
@@ -3005,7 +3022,7 @@ else if (encoding.equals("utf32")) {
30053022
}
30063023
}
30073024

3008-
public static String decode8(SixModelObject buf, String csName, ThreadContext tc) {
3025+
protected static ByteBuffer decode8(SixModelObject buf, ThreadContext tc) {
30093026
ByteBuffer bb;
30103027
if (buf instanceof VMArrayInstance_i8) {
30113028
VMArrayInstance_i8 bufi8 = (VMArrayInstance_i8)buf;
@@ -3021,8 +3038,14 @@ public static String decode8(SixModelObject buf, String csName, ThreadContext tc
30213038
bb.put((byte)tc.native_i);
30223039
}
30233040
}
3041+
return bb;
3042+
}
3043+
3044+
public static String decode8(SixModelObject buf, String csName, ThreadContext tc) {
3045+
ByteBuffer bb = decode8(buf, tc);
30243046
return Charset.forName(csName).decode(bb).toString();
30253047
}
3048+
30263049
public static String decode(SixModelObject buf, String encoding, ThreadContext tc) {
30273050
if (encoding.equals("utf8")) {
30283051
return decode8(buf, "UTF-8", tc);

t/nqp/19-file-ops.t

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#! nqp
2+
3+
# Test nqp::op file operations.
4+
5+
plan(20);
6+
7+
ok( nqp::stat('CREDITS', nqp::const::STAT_EXISTS) == 1, 'nqp::stat exists');
8+
ok( nqp::stat('AARDVARKS', nqp::const::STAT_EXISTS) == 0, 'nqp::stat not exists');
9+
10+
ok( nqp::stat('t', nqp::const::STAT_ISDIR) == 1, 'nqp::stat is directory');
11+
ok( nqp::stat('CREDITS', nqp::const::STAT_ISDIR) == 0, 'nqp::stat not directory');
12+
13+
ok( nqp::stat('CREDITS', nqp::const::STAT_ISREG) == 1, 'nqp::stat is regular file');
14+
ok( nqp::stat('t', nqp::const::STAT_ISREG) == 0, 'nqp::stat not regular file');
15+
16+
my $credits := nqp::open('CREDITS', 'r');
17+
ok( $credits, 'nqp::open for read');
18+
ok( nqp::tellfh($credits) == 0, 'nqp::tellfh start of file');
19+
my $line := nqp::readlinefh($credits);
20+
ok( nqp::chars($line) == nqp::chars($line), 'nqp::readlinefh line to read');
21+
ok( nqp::tellfh($credits) == 5, 'nqp::tellfh line two');
22+
my $rest := nqp::readallfh($credits);
23+
ok( nqp::chars($rest) > 100, 'nqp::readallfh lines to read');
24+
ok( nqp::tellfh($credits) == nqp::chars($line) + nqp::chars($rest), 'nqp::tellfh end of file');
25+
ok( nqp::chars(nqp::readlinefh($credits)) == 0, 'nqp::readlinefh end of file');
26+
ok( nqp::chars(nqp::readlinefh($credits)) == 0, 'nqp::readlinefh end of file repeat');
27+
ok( nqp::chars(nqp::readallfh($credits)) == 0, 'nqp::readallfh end of file');
28+
ok( nqp::chars(nqp::readlinefh($credits)) == 0, 'nqp::readlinefh end of file repeat');
29+
ok( nqp::defined(nqp::closefh($credits)), 'nqp::closefh');
30+
31+
ok( nqp::defined(nqp::getstdin()), 'nqp::getstdin');
32+
ok( nqp::defined(nqp::getstdout()), 'nqp::getstdout');
33+
ok( nqp::defined(nqp::getstderr()), 'nqp::getstderr');

t/nqp/59-nqpop.t

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Test nqp::op pseudo-functions.
44

5-
plan(112);
5+
plan(111);
66

77

88
ok( nqp::add_i(5,2) == 7, 'nqp::add_i');
@@ -108,7 +108,6 @@ ok( nqp::istrue(0.0) == 0, 'nqp::istrue');
108108
ok( nqp::istrue(0.1) == 1, 'nqp::istrue');
109109
ok( nqp::istrue(nqp::list()) == 0, 'nqp::istrue on empty list');
110110
ok( nqp::istrue(nqp::list(1,2,3)) == 1, 'nqp::istrue on nonempty list');
111-
ok( nqp::istrue(nqp::null()) == 0, 'nqp::istrue on null');
112111

113112
my $list := nqp::list(0, 'a', 'b', 3.0);
114113
ok( nqp::elems($list) == 4, 'nqp::elems');

0 commit comments

Comments
 (0)