1 11 package org.eclipse.core.internal.localstore; 12 13 import java.io.*; 14 15 18 19 public class SafeChunkyInputStream extends InputStream { 20 protected static final int BUFFER_SIZE = 8192; 21 protected byte[] buffer; 22 protected int bufferLength = 0; 23 protected byte[] chunk; 24 protected int chunkLength = 0; 25 protected boolean endOfFile = false; 26 protected InputStream input; 27 protected int nextByteInBuffer = 0; 28 protected int nextByteInChunk = 0; 29 30 public SafeChunkyInputStream(File target) throws IOException { 31 this(target, BUFFER_SIZE); 32 } 33 34 public SafeChunkyInputStream(File target, int bufferSize) throws IOException { 35 input = new FileInputStream(target); 36 buffer = new byte[bufferSize]; 37 } 38 39 protected void accumulate(byte[] data, int start, int end) { 40 byte[] result = new byte[chunk.length + end - start]; 41 System.arraycopy(chunk, 0, result, 0, chunk.length); 42 System.arraycopy(data, start, result, chunk.length, end - start); 43 chunk = result; 44 chunkLength = chunkLength + end - start; 45 } 46 47 public int available() throws IOException { 48 return chunkLength - nextByteInChunk; 49 } 50 51 protected void buildChunk() throws IOException { 52 while (true) { 54 if (nextByteInBuffer + ILocalStoreConstants.CHUNK_DELIMITER_SIZE > bufferLength) 55 shiftAndFillBuffer(); 56 int end = find(ILocalStoreConstants.END_CHUNK, nextByteInBuffer, bufferLength, true); 57 if (end != -1) { 58 accumulate(buffer, nextByteInBuffer, end); 59 nextByteInBuffer = end + ILocalStoreConstants.CHUNK_DELIMITER_SIZE; 60 return; 61 } 62 accumulate(buffer, nextByteInBuffer, bufferLength); 63 bufferLength = input.read(buffer); 64 nextByteInBuffer = 0; 65 if (bufferLength == -1) { 66 endOfFile = true; 67 return; 68 } 69 } 70 } 71 72 public void close() throws IOException { 73 input.close(); 74 } 75 76 protected boolean compare(byte[] source, byte[] target, int startIndex) { 77 for (int i = 0; i < target.length; i++) { 78 if (source[startIndex] != target[i]) 79 return false; 80 startIndex++; 81 } 82 return true; 83 } 84 85 protected int find(byte[] pattern, int startIndex, int endIndex, boolean accumulate) throws IOException { 86 int pos = findByte(pattern[0], startIndex, endIndex); 87 if (pos == -1) 88 return -1; 89 if (pos + ILocalStoreConstants.CHUNK_DELIMITER_SIZE > bufferLength) { 90 if (accumulate) 91 accumulate(buffer, nextByteInBuffer, pos); 92 nextByteInBuffer = pos; 93 pos = 0; 94 shiftAndFillBuffer(); 95 } 96 if (compare(buffer, pattern, pos)) 97 return pos; 98 return find(pattern, pos + 1, endIndex, accumulate); 99 } 100 101 protected int findByte(byte target, int startIndex, int endIndex) { 102 while (startIndex < endIndex) { 103 if (buffer[startIndex] == target) 104 return startIndex; 105 startIndex++; 106 } 107 return -1; 108 } 109 110 protected void findChunkStart() throws IOException { 111 if (nextByteInBuffer + ILocalStoreConstants.CHUNK_DELIMITER_SIZE > bufferLength) 112 shiftAndFillBuffer(); 113 int begin = find(ILocalStoreConstants.BEGIN_CHUNK, nextByteInBuffer, bufferLength, false); 114 if (begin != -1) { 115 nextByteInBuffer = begin + ILocalStoreConstants.CHUNK_DELIMITER_SIZE; 116 return; 117 } 118 bufferLength = input.read(buffer); 119 nextByteInBuffer = 0; 120 if (bufferLength == -1) { 121 resetChunk(); 122 endOfFile = true; 123 return; 124 } 125 findChunkStart(); 126 } 127 128 public int read() throws IOException { 129 if (endOfFile) 130 return -1; 131 if (nextByteInChunk < chunkLength) 133 return chunk[nextByteInChunk++] & 0xFF; 134 resetChunk(); 138 findChunkStart(); 139 if (endOfFile) 140 return -1; 141 buildChunk(); 142 refineChunk(); 143 return read(); 144 } 145 146 150 protected void refineChunk() { 151 int start = chunkLength - ILocalStoreConstants.CHUNK_DELIMITER_SIZE; 152 if (start < 0) 153 return; 154 for (int i = start; i >= 0; i--) { 155 if (compare(chunk, ILocalStoreConstants.BEGIN_CHUNK, i)) { 156 nextByteInChunk = i + ILocalStoreConstants.CHUNK_DELIMITER_SIZE; 157 return; 158 } 159 } 160 } 161 162 protected void resetChunk() { 163 chunk = new byte[0]; 164 chunkLength = 0; 165 nextByteInChunk = 0; 166 } 167 168 protected void shiftAndFillBuffer() throws IOException { 169 int length = bufferLength - nextByteInBuffer; 170 System.arraycopy(buffer, nextByteInBuffer, buffer, 0, length); 171 nextByteInBuffer = 0; 172 bufferLength = length; 173 int read = input.read(buffer, bufferLength, buffer.length - bufferLength); 174 if (read != -1) 175 bufferLength += read; 176 else { 177 resetChunk(); 178 endOfFile = true; 179 } 180 } 181 } 182 | Popular Tags |