|
5 | 5 | import dan200.computercraft.api.lua.LuaException; |
6 | 6 |
|
7 | 7 | import javax.annotation.Nonnull; |
| 8 | +import java.io.ByteArrayOutputStream; |
8 | 9 | import java.io.IOException; |
9 | 10 | import java.io.InputStream; |
10 | 11 | import java.util.Arrays; |
|
13 | 14 |
|
14 | 15 | public class BinaryInputHandle extends HandleGeneric |
15 | 16 | { |
| 17 | + private static final int BUFFER_SIZE = 8192; |
| 18 | + |
16 | 19 | private final InputStream m_stream; |
17 | 20 |
|
18 | 21 | public BinaryInputHandle( InputStream reader ) |
@@ -45,16 +48,46 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O |
45 | 48 | if( args.length > 0 && args[ 0 ] != null ) |
46 | 49 | { |
47 | 50 | int count = getInt( args, 0 ); |
48 | | - if( count <= 0 || count >= 1024 * 16 ) |
| 51 | + if( count < 0 ) |
49 | 52 | { |
50 | | - throw new LuaException( "Count out of range" ); |
| 53 | + // Whilst this may seem absurd to allow reading 0 bytes, PUC Lua it so |
| 54 | + // it seems best to remain somewhat consistent. |
| 55 | + throw new LuaException( "Cannot read a negative number of bytes" ); |
51 | 56 | } |
| 57 | + else if( count <= BUFFER_SIZE ) |
| 58 | + { |
| 59 | + // If we've got a small count, then allocate that and read it. |
| 60 | + byte[] bytes = new byte[ count ]; |
| 61 | + int read = m_stream.read( bytes ); |
| 62 | + |
| 63 | + if( read < 0 ) return null; |
| 64 | + if( read < count ) bytes = Arrays.copyOf( bytes, read ); |
| 65 | + return new Object[] { bytes }; |
| 66 | + } |
| 67 | + else |
| 68 | + { |
| 69 | + byte[] buffer = new byte[ BUFFER_SIZE ]; |
52 | 70 |
|
53 | | - byte[] bytes = new byte[ count ]; |
54 | | - count = m_stream.read( bytes ); |
55 | | - if( count < 0 ) return null; |
56 | | - if( count < bytes.length ) bytes = Arrays.copyOf( bytes, count ); |
57 | | - return new Object[] { bytes }; |
| 71 | + // Read the initial set of bytes, failing if none are read. |
| 72 | + int read = m_stream.read( buffer, 0, Math.min( buffer.length, count ) ); |
| 73 | + if( read == -1 ) return null; |
| 74 | + |
| 75 | + ByteArrayOutputStream out = new ByteArrayOutputStream( read ); |
| 76 | + count -= read; |
| 77 | + out.write( buffer, 0, read ); |
| 78 | + |
| 79 | + // Otherwise read until we either reach the limit or we no longer consume |
| 80 | + // the full buffer. |
| 81 | + while( read >= buffer.length && count > 0 ) |
| 82 | + { |
| 83 | + read = m_stream.read( buffer, 0, Math.min( BUFFER_SIZE, count ) ); |
| 84 | + if( read == -1 ) break; |
| 85 | + count -= read; |
| 86 | + out.write( buffer, 0, read ); |
| 87 | + } |
| 88 | + |
| 89 | + return new Object[] { out.toByteArray() }; |
| 90 | + } |
58 | 91 | } |
59 | 92 | else |
60 | 93 | { |
|
0 commit comments