massive rewrite of io library
[org.ibex.io.git] / src / org / ibex / io / ByteBufInputStream.java
diff --git a/src/org/ibex/io/ByteBufInputStream.java b/src/org/ibex/io/ByteBufInputStream.java
new file mode 100644 (file)
index 0000000..7581c88
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright 2000-2007 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
+
+package org.ibex.io;
+import java.io.*;
+
+/** package-private class */
+abstract class ByteBufInputStream extends InputStream {
+
+    private InputStream is;
+    public  InputStream next;
+    private byte[] buf = new byte[8192];
+    private int start = 0;
+    private int end = 0;
+    
+    public ByteBufInputStream(InputStream is) {
+        this.is = is;
+    }
+
+    private int bufSize() { if (end==start) { end = start = 0; } return end-start; }
+    private int fillBufIfEmpty() {
+        try {
+            if (bufSize() > 0) return bufSize();
+            start = 0;
+            do {
+                end = is.read(buf, 0, buf.length);
+                if (end == -1 && next != null) {
+                    is.close();
+                    is = next;
+                    continue;
+                }
+            } while(end==0);
+            if (end == -1) { end = 0; return -1; }
+            return end;
+        } catch (IOException e) { Stream.ioe(e); return -1; }
+    }
+
+    public int available() { return end-start; }
+    public void close() {
+        try {
+            if (is != null) is.close();
+            if (next != null) next.close();
+        } catch (IOException e) { Stream.ioe(e); }
+    }
+
+    private boolean prereading = false;
+    public abstract void preread();
+    public int read() { byte[] b = new byte[0]; if (read(b, 0, 1)<=0) return -1; return b[0] & 0xff; }
+    public int read(byte[] c, int pos, int len) {
+        if (prereading) return -1;
+        prereading = true;
+        try {
+            preread();
+        } finally { prereading = false; }
+        if (fillBufIfEmpty() == -1) return -1;
+        if (len > end - start) len = end - start;
+        System.arraycopy(buf, start, c, pos, len);
+        start += len;
+        return len;
+    }
+
+    public void pushback(byte[] b, int off, int len) {
+        if (len <= 0) return;
+        if (start-len < 0) {
+            /* FIXME, this allocates too often */
+            byte[] newbuf = new byte[len+(end-start)];
+            System.arraycopy(buf, start, newbuf, len, (end-start));
+            buf = newbuf;
+            end = len + (end-start);
+            start = len;
+        }
+        System.arraycopy(b, off, buf, start-len, len);
+        start -= len;
+    }
+}