Skip to content

Commit a427930

Browse files
committed
Merge pull request dan200#541 from SquidDev-CC/ComputerCraft/feature/unlimited-reads
Remove upper bound on how many bytes/characters can be read
2 parents a0d71cb + 7dbc4e6 commit a427930

File tree

2 files changed

+80
-15
lines changed

2 files changed

+80
-15
lines changed

src/main/java/dan200/computercraft/core/apis/handles/BinaryInputHandle.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import dan200.computercraft.api.lua.LuaException;
66

77
import javax.annotation.Nonnull;
8+
import java.io.ByteArrayOutputStream;
89
import java.io.IOException;
910
import java.io.InputStream;
1011
import java.util.Arrays;
@@ -13,6 +14,8 @@
1314

1415
public class BinaryInputHandle extends HandleGeneric
1516
{
17+
private static final int BUFFER_SIZE = 8192;
18+
1619
private final InputStream m_stream;
1720

1821
public BinaryInputHandle( InputStream reader )
@@ -45,16 +48,46 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O
4548
if( args.length > 0 && args[ 0 ] != null )
4649
{
4750
int count = getInt( args, 0 );
48-
if( count <= 0 || count >= 1024 * 16 )
51+
if( count < 0 )
4952
{
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" );
5156
}
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 ];
5270

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+
}
5891
}
5992
else
6093
{

src/main/java/dan200/computercraft/core/apis/handles/EncodedInputHandle.java

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
import javax.annotation.Nonnull;
77
import java.io.*;
88

9-
import static dan200.computercraft.core.apis.ArgumentHelper.*;
9+
import static dan200.computercraft.core.apis.ArgumentHelper.optInt;
1010

1111
public class EncodedInputHandle extends HandleGeneric
1212
{
13+
private static final int BUFFER_SIZE = 8192;
14+
1315
private final BufferedReader m_reader;
1416

1517
public EncodedInputHandle( BufferedReader reader )
@@ -111,15 +113,45 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O
111113
try
112114
{
113115
int count = optInt( args, 0, 1 );
114-
if( count <= 0 || count >= 1024 * 16 )
116+
if( count < 0 )
117+
{
118+
// Whilst this may seem absurd to allow reading 0 characters, PUC Lua it so
119+
// it seems best to remain somewhat consistent.
120+
throw new LuaException( "Cannot read a negative number of characters" );
121+
}
122+
else if( count <= BUFFER_SIZE )
123+
{
124+
// If we've got a small count, then allocate that and read it.
125+
char[] chars = new char[ count ];
126+
int read = m_reader.read( chars );
127+
128+
return read < 0 ? null : new Object[] { new String( chars, 0, read ) };
129+
}
130+
else
115131
{
116-
throw new LuaException( "Count out of range" );
132+
// If we've got a large count, read in bunches of 8192.
133+
char[] buffer = new char[ BUFFER_SIZE ];
134+
135+
// Read the initial set of characters, failing if none are read.
136+
int read = m_reader.read( buffer, 0, Math.min( buffer.length, count ) );
137+
if( read == -1 ) return null;
138+
139+
StringBuilder out = new StringBuilder( read );
140+
count -= read;
141+
out.append( buffer, 0, read );
142+
143+
// Otherwise read until we either reach the limit or we no longer consume
144+
// the full buffer.
145+
while( read >= BUFFER_SIZE && count > 0 )
146+
{
147+
read = m_reader.read( buffer, 0, Math.min( BUFFER_SIZE, count ) );
148+
if( read == -1 ) break;
149+
count -= read;
150+
out.append( buffer, 0, read );
151+
}
152+
153+
return new Object[] { out.toString() };
117154
}
118-
char[] bytes = new char[ count ];
119-
count = m_reader.read( bytes );
120-
if( count < 0 ) return null;
121-
String str = new String( bytes, 0, count );
122-
return new Object[] { str };
123155
}
124156
catch( IOException e )
125157
{

0 commit comments

Comments
 (0)