aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/google/common/io/protocol/BoundInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/google/common/io/protocol/BoundInputStream.java')
-rw-r--r--src/com/google/common/io/protocol/BoundInputStream.java91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/com/google/common/io/protocol/BoundInputStream.java b/src/com/google/common/io/protocol/BoundInputStream.java
new file mode 100644
index 0000000..dbccca7
--- /dev/null
+++ b/src/com/google/common/io/protocol/BoundInputStream.java
@@ -0,0 +1,91 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+
+package com.google.common.io.protocol;
+
+import java.io.*;
+
+/**
+ * An input stream backed by another input stream, where reading from the
+ * underlying input stream is limited to a fixed number of bytes. Also does
+ * some buffering.
+ *
+ */
+public class BoundInputStream extends InputStream {
+
+ /** Buffer size */
+ static final int BUF_SIZE = 4096;
+
+ /** Number of bytes that may still be read from the underlying stream */
+ private int remaining;
+
+ /** Small buffer to avoid making OS calls for each byte read. */
+ private byte[] buf;
+
+ /** Current position in the buffer */
+ private int bufPos;
+
+ /** Filled size of the buffer */
+ private int bufSize;
+
+ /** Underlying stream to read from */
+ private InputStream base;
+
+ public BoundInputStream(InputStream base, int len) {
+ this.base = base;
+ this.remaining = len;
+
+ buf = new byte[Math.min(len, BUF_SIZE)];
+ }
+
+ /**
+ * Make sure there is at least one byte in the buffer. If not possible,
+ * return false.
+ */
+ private boolean checkBuf() throws IOException {
+ if (remaining <= 0) {
+ return false;
+ }
+
+ if (bufPos >= bufSize) {
+ bufSize = base.read(buf, 0, Math.min(remaining, buf.length));
+ if (bufSize <= 0) {
+ remaining = 0;
+ return false;
+ }
+ bufPos = 0;
+ }
+ return true;
+ }
+
+ public int available() {
+ return bufSize - bufPos;
+ }
+
+ public int read() throws IOException {
+ if (!checkBuf()) {
+ return -1;
+ }
+ remaining--;
+ return buf[bufPos++] & 255;
+ }
+
+ public int read(byte[] data, int start, int count) throws IOException {
+ if (!checkBuf()) {
+ return -1;
+ }
+ count = Math.min(count, bufSize - bufPos);
+ System.arraycopy(buf, bufPos, data, start, count);
+ bufPos += count;
+ remaining -= count;
+ return count;
+ }
+
+ /**
+ * How many bytes are remaining, based on the length provided to the
+ * constructor. The underlying stream may terminate earlier. Provided mainly
+ * for testing purposes.
+ */
+ public int getRemaining() {
+ return remaining;
+ }
+}