(Vibhu Mohindra) Fix RandomAccessCharacterFile.java

parent a4969d10
...@@ -59,11 +59,12 @@ ...@@ -59,11 +59,12 @@
rdf:_3 _:ville ; rdf:_3 _:ville ;
rdf:_4 _:astalla ; rdf:_4 _:astalla ;
rdf:_5 _:rudi ; rdf:_5 _:rudi ;
rdf:_5 _:ferada ; rdf:_6 _:ferada ;
rdf:_5 _:cyrus ; rdf:_7 _:cyrus ;
rdf:_5 _:dmiles ; rdf:_8 _:dmiles ;
rdf:_5 _:alanr ; rdf:_9 _:alanr ;
rdf:_5 _:pipping ; rdf:_10 _:pipping ;
rdf:_11 _:olof ;
] . ] .
<abcl:doap> <abcl:doap>
......
...@@ -51,8 +51,11 @@ import java.nio.charset.CharsetEncoder; ...@@ -51,8 +51,11 @@ import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult; import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction; import java.nio.charset.CodingErrorAction;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import org.armedbear.lisp.Debug; import org.armedbear.lisp.Debug;
import static org.armedbear.lisp.Lisp.error; import static org.armedbear.lisp.Lisp.error;
import org.armedbear.lisp.SimpleError; import org.armedbear.lisp.SimpleError;
import org.armedbear.lisp.SimpleString; import org.armedbear.lisp.SimpleString;
...@@ -298,7 +301,7 @@ public class RandomAccessCharacterFile { ...@@ -298,7 +301,7 @@ public class RandomAccessCharacterFile {
// there is no write pending data in the buffers. // there is no write pending data in the buffers.
bbufIsDirty = false; bbufIsDirty = false;
bbufIsReadable = false; bbufIsReadable = true;
bbufpos = fcn.position(); bbufpos = fcn.position();
...@@ -356,16 +359,18 @@ public class RandomAccessCharacterFile { ...@@ -356,16 +359,18 @@ public class RandomAccessCharacterFile {
// need to read from the file. // need to read from the file.
if (bbufIsDirty) { if (bbufIsDirty) {
bbuf.flip(); flushBbuf(false);
fcn.position(bbufpos);
fcn.write(bbuf);
bbufpos += bbuf.position();
bbuf.clear(); bbuf.clear();
bbufIsReadable = false;
} else { } else {
int bbufEnd = bbufIsReadable ? bbuf.limit() : bbuf.position(); int bbufEnd = bbufIsReadable ? bbuf.limit() : bbuf.position();
fcn.position(bbufpos + bbufEnd); fcn.position(bbufpos + bbufEnd);
bbufpos += bbuf.position(); bbufpos += bbuf.position();
bbuf.compact(); if (bbufIsReadable) {
bbuf.compact();
bbufIsReadable = false;
} else //must discard the junk bytes after bbuf.position()
bbuf.clear();
} }
bufReady = (fcn.read(bbuf) != -1); bufReady = (fcn.read(bbuf) != -1);
...@@ -376,6 +381,7 @@ public class RandomAccessCharacterFile { ...@@ -376,6 +381,7 @@ public class RandomAccessCharacterFile {
return bufReady; return bufReady;
} }
final int read(char[] cb, int off, int len) throws IOException { final int read(char[] cb, int off, int len) throws IOException {
CharBuffer cbuf = CharBuffer.wrap(cb, off, len); CharBuffer cbuf = CharBuffer.wrap(cb, off, len);
boolean decodeWasUnderflow = false; boolean decodeWasUnderflow = false;
...@@ -428,6 +434,7 @@ public class RandomAccessCharacterFile { ...@@ -428,6 +434,7 @@ public class RandomAccessCharacterFile {
if (CoderResult.OVERFLOW == r || bbuf.remaining() == 0) { if (CoderResult.OVERFLOW == r || bbuf.remaining() == 0) {
flushBbuf(false); flushBbuf(false);
bbuf.clear(); bbuf.clear();
bbufIsReadable = false;
} }
if (r.isUnmappable()) { if (r.isUnmappable()) {
throw new RACFUnmappableCharacterException(cbuf.position(), throw new RACFUnmappableCharacterException(cbuf.position(),
...@@ -455,12 +462,17 @@ public class RandomAccessCharacterFile { ...@@ -455,12 +462,17 @@ public class RandomAccessCharacterFile {
+ (bbufIsReadable ? bbuf.limit() : bbuf.position()); // beyond position() + (bbufIsReadable ? bbuf.limit() : bbuf.position()); // beyond position()
if (newPosition >= bbufpos && newPosition < bbufend) { if (newPosition >= bbufpos && newPosition < bbufend) {
// near seek. within existing data of bbuf. // near seek. within existing data of bbuf.
if (!bbufIsReadable) { //rewinding. keep tail buffered.
bbuf.limit(bbuf.position());
bbufIsReadable = true;
}
bbuf.position((int)(newPosition - bbufpos)); bbuf.position((int)(newPosition - bbufpos));
} else { } else {
fcn.position(newPosition); fcn.position(newPosition);
// far seek; discard the buffer (it's already cleared) // far seek; discard the buffer (it's already cleared)
bbuf.clear(); bbuf.clear();
bbuf.flip(); // "there is no useful data on this buffer yet." bbuf.flip(); // "there is no useful data on this buffer yet."
bbufIsReadable = true;
bbufpos = newPosition; bbufpos = newPosition;
} }
} }
...@@ -470,33 +482,40 @@ public class RandomAccessCharacterFile { ...@@ -470,33 +482,40 @@ public class RandomAccessCharacterFile {
} }
public final long length() throws IOException { public final long length() throws IOException {
flushBbuf(false); flushBbuf(true);
return fcn.size(); return fcn.size();
} }
private final void flushBbuf(boolean commitOnly) throws IOException { final void flushBbuf(boolean commitOnly) throws IOException {
if (! bbufIsDirty) if (commitOnly && !bbufIsDirty)
return; return;
//otherwise, we do at least need to increase bbufpos
fcn.position(bbufpos); fcn.position(bbufpos);
// if the buffer is dirty, the modifications have to be // if the buffer is dirty, the modifications have to be
// before position(): before re-positioning, this.position() // before position(): before re-positioning, this.position()
// calls this function. // calls this function.
if (commitOnly || bbufIsReadable) { if (commitOnly) {
ByteBuffer dup = bbuf.duplicate(); ByteBuffer dup = bbuf.duplicate();
dup.flip(); dup.flip();
fcn.write(dup); fcn.write(dup);
//ideally, should restore fcn.position(). but don't for performance.
// fcn.position(fcn.position()-dup.position());
bbufIsDirty = false; //this fixed stas's bug, but not mine.
return; return;
} }
bbuf.flip();
fcn.write(bbuf); if (bbufIsDirty) {
bbuf.flip();
fcn.write(bbuf);
}
bbufpos += bbuf.position(); bbufpos += bbuf.position();
bbuf.clear(); bbuf.clear();
bbuf.flip(); // there's no useable data in this buffer bbuf.flip(); // there's no useable data in this buffer
bbufIsDirty = false; bbufIsDirty = false;
bbufIsReadable = false; bbufIsReadable = true;
} }
public final int read(byte[] b, int off, int len) throws IOException { public final int read(byte[] b, int off, int len) throws IOException {
...@@ -505,10 +524,7 @@ public class RandomAccessCharacterFile { ...@@ -505,10 +524,7 @@ public class RandomAccessCharacterFile {
while (pos - off < len && ! atEof) { while (pos - off < len && ! atEof) {
atEof = ! ensureReadBbuf(false); atEof = ! ensureReadBbuf(false);
int want = len - pos; int want = Math.min(off + len - pos, bbuf.remaining());
if (want > bbuf.remaining()) {
want = bbuf.remaining();
}
bbuf.get(b, pos, want); bbuf.get(b, pos, want);
pos += want; pos += want;
} }
...@@ -558,17 +574,15 @@ public class RandomAccessCharacterFile { ...@@ -558,17 +574,15 @@ public class RandomAccessCharacterFile {
final void write(byte[] b, int off, int len) throws IOException { final void write(byte[] b, int off, int len) throws IOException {
int pos = off; int pos = off;
while (pos < off + len) { while (pos < off + len) {
int want = len - pos + off;
if (want > bbuf.remaining()) {
want = bbuf.remaining();
}
bbuf.put(b, pos, want);
pos += want;
bbufIsDirty = true;
if (bbuf.remaining() == 0) { if (bbuf.remaining() == 0) {
flushBbuf(false); flushBbuf(false);
bbuf.clear(); bbuf.clear();
bbufIsReadable = false;
} }
int thisBatchLen = Math.min(off + len - pos, bbuf.remaining());
bbuf.put(b, pos, thisBatchLen);
pos += thisBatchLen;
bbufIsDirty = true;
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment