1 11 package org.eclipse.core.internal.content; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 16 public class LazyInputStream extends InputStream implements ILazySource { 17 private int blockCapacity; 18 byte[][] blocks = {}; 19 private int bufferSize; 20 private InputStream in; 21 private int mark; 22 private int offset; 23 24 public LazyInputStream(InputStream in, int blockCapacity) { 25 this.in = in; 26 this.blockCapacity = blockCapacity; 27 } 28 29 public int available() throws IOException { 30 try { 31 return bufferSize - offset + in.available(); 32 } catch (IOException ioe) { 33 throw new LowLevelIOException(ioe); 34 } 35 } 36 37 private int computeBlockSize(int blockIndex) { 38 if (blockIndex < blocks.length - 1) 39 return blockCapacity; 40 int blockSize = bufferSize % blockCapacity; 41 return blockSize == 0 ? blockCapacity : blockSize; 42 } 43 44 private int copyFromBuffer(byte[] userBuffer, int userOffset, int needed) { 45 int copied = 0; 46 int current = offset / blockCapacity; 47 while ((needed - copied) > 0 && current < blocks.length) { 48 int blockSize = computeBlockSize(current); 49 int offsetInBlock = offset % blockCapacity; 50 int availableInBlock = blockSize - offsetInBlock; 51 int toCopy = Math.min(availableInBlock, needed - copied); 52 System.arraycopy(blocks[current], offsetInBlock, userBuffer, userOffset + copied, toCopy); 53 copied += toCopy; 54 current++; 55 offset += toCopy; 56 } 57 return copied; 58 } 59 60 private void ensureAvailable(long bytesToRead) throws IOException { 61 int loadedBlockSize = blockCapacity; 62 while (bufferSize < offset + bytesToRead && loadedBlockSize == blockCapacity) { 63 try { 64 loadedBlockSize = loadBlock(); 65 } catch (IOException e) { 66 throw new LowLevelIOException(e); 67 } 68 bufferSize += loadedBlockSize; 69 } 70 } 71 72 protected int getBlockCount() { 74 return blocks.length; 75 } 76 77 protected int getBufferSize() { 79 return bufferSize; 80 } 81 82 protected int getMark() { 84 return mark; 85 } 86 87 protected int getOffset() { 89 return offset; 90 } 91 92 public boolean isText() { 93 return false; 94 } 95 96 private int loadBlock() throws IOException { 97 byte[] newBlock = new byte[blockCapacity]; 99 int readCount = in.read(newBlock); 100 if (readCount == -1) 101 return 0; 102 byte[][] tmpBlocks = new byte[blocks.length + 1][]; 104 System.arraycopy(blocks, 0, tmpBlocks, 0, blocks.length); 105 blocks = tmpBlocks; 106 blocks[blocks.length - 1] = newBlock; 107 return readCount; 108 } 109 110 public void mark(int readlimit) { 111 mark = offset; 112 } 113 114 public boolean markSupported() { 115 return true; 116 } 117 118 public int read() throws IOException { 119 ensureAvailable(1); 120 if (bufferSize <= offset) 121 return -1; 122 int nextByte = 0xFF & blocks[offset / blockCapacity][offset % blockCapacity]; 123 offset++; 124 return nextByte; 125 } 126 127 public int read(byte[] b) throws IOException { 128 return read(b, 0, b.length); 129 } 130 131 public int read(byte[] b, int off, int len) throws IOException { 132 ensureAvailable(len); 133 int copied = copyFromBuffer(b, off, len); 134 return copied == 0 ? -1 : copied; 135 } 136 137 public void reset() { 138 offset = mark; 139 } 140 141 public void rewind() { 142 mark = 0; 143 offset = 0; 144 } 145 146 public long skip(long toSkip) throws IOException { 147 if (toSkip <= 0) 148 return 0; 149 ensureAvailable(toSkip); 150 long skipped = Math.min(toSkip, bufferSize - offset); 151 offset += skipped; 152 return skipped; 153 } 154 } 155 | Popular Tags |