|
|
@@ -6,28 +6,25 @@
|
|
|
*/
|
|
|
package net.ranides.assira.nio;
|
|
|
|
|
|
-import java.io.BufferedWriter;
|
|
|
+import java.io.EOFException;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.ObjectInputStream;
|
|
|
import java.io.ObjectOutputStream;
|
|
|
import java.io.OutputStream;
|
|
|
import java.io.Reader;
|
|
|
-import java.io.StringWriter;
|
|
|
import java.io.Writer;
|
|
|
import java.nio.BufferOverflowException;
|
|
|
import java.nio.BufferUnderflowException;
|
|
|
import java.nio.ByteBuffer;
|
|
|
import java.nio.CharBuffer;
|
|
|
import java.nio.ReadOnlyBufferException;
|
|
|
+import java.nio.channels.ClosedChannelException;
|
|
|
import java.nio.channels.SeekableByteChannel;
|
|
|
import java.nio.charset.Charset;
|
|
|
-import java.nio.charset.CharsetDecoder;
|
|
|
-import java.nio.charset.CoderResult;
|
|
|
import net.ranides.assira.generic.ValueUtils;
|
|
|
import net.ranides.assira.io.FileHelper;
|
|
|
import net.ranides.assira.io.RIOException;
|
|
|
-import net.ranides.assira.text.TextEncoding;
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
@@ -92,12 +89,6 @@ public final class BufferAdapter {
|
|
|
return new CWriter(buffer);
|
|
|
}
|
|
|
|
|
|
- private static void nullcheck(Object object) throws IOException {
|
|
|
- if(null == object) {
|
|
|
- throw new IOException("Buffer is closed");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private static class BChannel implements SeekableByteChannel {
|
|
|
|
|
|
private ByteBuffer buffer;
|
|
|
@@ -113,14 +104,14 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
FileHelper.close(buffer);
|
|
|
buffer = null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public int read(ByteBuffer dst) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
if(buffer.remaining() == 0) {
|
|
|
return -1;
|
|
|
}
|
|
|
@@ -128,11 +119,11 @@ public final class BufferAdapter {
|
|
|
int prv = buffer.limit();
|
|
|
int max = buffer.position() + count;
|
|
|
if( max != buffer.limit(max).limit() ) {
|
|
|
- throw new IOException("ByteBufferChannel can't set Buffer limits.");
|
|
|
+ throw new IOException("ByteBufferChannel can't set internal Buffer limits.");
|
|
|
}
|
|
|
dst.put(buffer);
|
|
|
if(prv != buffer.limit(prv).limit()) {
|
|
|
- throw new IOException("ByteBufferChannel can't restore Buffer limits.");
|
|
|
+ throw new IOException("ByteBufferChannel can't restore internal Buffer limits.");
|
|
|
}
|
|
|
return count;
|
|
|
}
|
|
|
@@ -140,10 +131,27 @@ public final class BufferAdapter {
|
|
|
@Override
|
|
|
public int write(ByteBuffer src) throws IOException {
|
|
|
try {
|
|
|
- nullcheck(buffer);
|
|
|
- int ret = src.remaining();
|
|
|
- buffer.put(src);
|
|
|
- return ret;
|
|
|
+ nullcheck();
|
|
|
+ int brem = buffer.remaining();
|
|
|
+ if(brem == 0) {
|
|
|
+ throw new EOFException();
|
|
|
+ }
|
|
|
+ int srem = src.remaining();
|
|
|
+ if( srem > brem) {
|
|
|
+ int prv = src.limit();
|
|
|
+ int max = src.position() + brem;
|
|
|
+ if(max != src.limit(max).limit()) {
|
|
|
+ throw new IOException("ByteBufferChannel can't set source Buffer limits.");
|
|
|
+ }
|
|
|
+ buffer.put(src);
|
|
|
+ if(prv != src.limit(prv).limit()) {
|
|
|
+ throw new IOException("ByteBufferChannel can't restore source Buffer limits.");
|
|
|
+ }
|
|
|
+ return brem;
|
|
|
+ } else {
|
|
|
+ buffer.put(src);
|
|
|
+ return srem;
|
|
|
+ }
|
|
|
} catch(BufferOverflowException | ReadOnlyBufferException cause) {
|
|
|
throw new IOException(cause);
|
|
|
}
|
|
|
@@ -151,32 +159,44 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public long position() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
return buffer.position();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public SeekableByteChannel position(long newPosition) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
assert newPosition == (int)newPosition;
|
|
|
- buffer.position((int)newPosition);
|
|
|
+ if( newPosition < buffer.limit() ) {
|
|
|
+ buffer.position((int)newPosition);
|
|
|
+ } else {
|
|
|
+ buffer.position(buffer.limit());
|
|
|
+ }
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public long size() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
return buffer.limit();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public SeekableByteChannel truncate(long size) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
assert size == (int)size;
|
|
|
- buffer.limit((int)size);
|
|
|
+ if( size < buffer.limit()) {
|
|
|
+ buffer.limit((int)size);
|
|
|
+ }
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ private void nullcheck() throws IOException {
|
|
|
+ if(null == buffer) {
|
|
|
+ throw new ClosedChannelException();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private static class BIStream extends InputStream {
|
|
|
@@ -189,14 +209,14 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
FileHelper.close(buffer);
|
|
|
buffer = null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public int read() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
try {
|
|
|
return buffer.get();
|
|
|
} catch(BufferUnderflowException cause) {
|
|
|
@@ -206,7 +226,7 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public int read(byte[] target, int offset, int len) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
try {
|
|
|
buffer.get(target, offset, len);
|
|
|
return len;
|
|
|
@@ -217,16 +237,22 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public int available() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
return buffer.remaining();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public long skip(long n) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
int np = buffer.position()+(int)n;
|
|
|
return np == buffer.position(np).position() ? n : 0;
|
|
|
}
|
|
|
+
|
|
|
+ private void nullcheck() throws IOException {
|
|
|
+ if(null == buffer) {
|
|
|
+ throw new IOException("InputStream is closed");
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -240,19 +266,19 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
FileHelper.close(buffer);
|
|
|
buffer = null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void flush() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void write(int b) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
try {
|
|
|
buffer.put( (byte)b );
|
|
|
} catch(BufferUnderflowException | ReadOnlyBufferException cause) {
|
|
|
@@ -262,7 +288,7 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void write(byte[] bytes, int offset, int len) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
try {
|
|
|
buffer.put(bytes, offset, len);
|
|
|
} catch(BufferUnderflowException | ReadOnlyBufferException cause) {
|
|
|
@@ -270,6 +296,12 @@ public final class BufferAdapter {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void nullcheck() throws IOException {
|
|
|
+ if(null == buffer) {
|
|
|
+ throw new IOException("OutputStream is closed");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private static class CReader extends Reader {
|
|
|
@@ -282,14 +314,14 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
FileHelper.close(buffer);
|
|
|
buffer = null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public int read() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
try {
|
|
|
return buffer.get();
|
|
|
} catch(BufferUnderflowException cause) {
|
|
|
@@ -299,7 +331,7 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public int read(char[] target, int offset, int len) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
try {
|
|
|
buffer.get(target, offset, len);
|
|
|
return len;
|
|
|
@@ -310,11 +342,17 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public long skip(long count) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
int np = buffer.position()+(int)count;
|
|
|
return np == buffer.position(np).position() ? count : 0;
|
|
|
}
|
|
|
|
|
|
+ private void nullcheck() throws IOException {
|
|
|
+ if(null == buffer) {
|
|
|
+ throw new IOException("Reader is closed");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private static class CWriter extends Writer {
|
|
|
@@ -332,7 +370,7 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
flush();
|
|
|
FileHelper.close(buffer);
|
|
|
buffer = null;
|
|
|
@@ -341,7 +379,7 @@ public final class BufferAdapter {
|
|
|
@Override
|
|
|
public Writer append(char c) throws IOException {
|
|
|
try {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
buffer.put(c);
|
|
|
return this;
|
|
|
} catch(BufferUnderflowException | ReadOnlyBufferException cause) {
|
|
|
@@ -357,7 +395,7 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public Writer append(CharSequence value, int start, int end) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
CharSequence svalue = ValueUtils.or(value, "null");
|
|
|
try {
|
|
|
for(int i=start; i<end; i++) {
|
|
|
@@ -376,14 +414,14 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void write(char[] target) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
write(target, 0, target.length);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void write(char[] target, int offset, int len) throws IOException {
|
|
|
try {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
buffer.put(target, offset, len);
|
|
|
} catch(BufferUnderflowException | ReadOnlyBufferException cause) {
|
|
|
throw new IOException(cause);
|
|
|
@@ -393,7 +431,7 @@ public final class BufferAdapter {
|
|
|
@Override
|
|
|
public void write(String value) throws IOException {
|
|
|
try {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
buffer.put(value);
|
|
|
} catch(BufferUnderflowException | ReadOnlyBufferException cause) {
|
|
|
throw new IOException(cause);
|
|
|
@@ -403,13 +441,19 @@ public final class BufferAdapter {
|
|
|
@Override
|
|
|
public void write(String value, int offset, int len) throws IOException {
|
|
|
try {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
buffer.put(value, offset, offset+len);
|
|
|
} catch(BufferUnderflowException | ReadOnlyBufferException cause) {
|
|
|
throw new IOException(cause);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void nullcheck() throws IOException {
|
|
|
+ if(null == buffer) {
|
|
|
+ throw new IOException("Writer is closed");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private static class BWriter extends Writer {
|
|
|
@@ -424,7 +468,7 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
flush();
|
|
|
FileHelper.close(buffer);
|
|
|
buffer = null;
|
|
|
@@ -437,9 +481,15 @@ public final class BufferAdapter {
|
|
|
|
|
|
@Override
|
|
|
public void write(char[] cbuf, int off, int len) throws IOException {
|
|
|
- nullcheck(buffer);
|
|
|
+ nullcheck();
|
|
|
buffer.put( charset.encode(CharBuffer.wrap(cbuf, off, len)) );
|
|
|
}
|
|
|
+
|
|
|
+ private void nullcheck() throws IOException {
|
|
|
+ if(null == buffer) {
|
|
|
+ throw new IOException("Writer is closed");
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
}
|