FileDocCategorySizeDatePackage
RandomAccessMemoryCache.javaAPI DocAndroid 1.5 API6625Wed May 06 22:41:54 BST 2009org.apache.harmony.x.imageio.stream

RandomAccessMemoryCache

public final class RandomAccessMemoryCache extends Object

Fields Summary
private static final int
BLOCK_SHIFT
private static final int
BLOCK_SIZE
private static final int
BLOCK_MASK
private long
length
private int
firstUndisposed
private ArrayList
blocks
Constructors Summary
public RandomAccessMemoryCache()


      
    
Methods Summary
public intappendData(java.io.InputStream is, int count)

        if (count <= 0) {
            return 0;
        }

        long startPos = length;
        long lastPos = length + count - 1;
        grow(lastPos); // Changes length

        int blockIdx = (int)(startPos >> BLOCK_SHIFT);
        int offset = (int) (startPos & BLOCK_MASK);

        int bytesAppended = 0;

        while (count > 0) {
            byte[] block = blocks.get(blockIdx);
            int toCopy = Math.min(BLOCK_SIZE - offset, count);
            count -= toCopy;

            while (toCopy > 0) {
                int bytesRead = is.read(block, offset, toCopy);

                if (bytesRead < 0) {
                    length -= (count - bytesAppended);
                    return bytesAppended;
                }

                toCopy -= bytesRead;
                offset += bytesRead;
            }

            blockIdx++;
            offset = 0;
        }

        return count;
    
public voidclose()

        blocks.clear();
        length = 0;
    
public voidfreeBefore(long pos)

        int blockIdx = (int)(pos >> BLOCK_SHIFT);
        if (blockIdx <= firstUndisposed) { // Nothing to do
            return;
        }

        for (int i = firstUndisposed; i < blockIdx; i++) {
            blocks.set(i, null);
        }

        firstUndisposed = blockIdx;
    
public voidgetData(java.io.OutputStream os, int count, long pos)

        if (pos + count > length) {
            throw new IndexOutOfBoundsException("Argument out of cache");
        }

        int blockIdx = (int)(pos >> BLOCK_SHIFT);
        int offset = (int) (pos & BLOCK_MASK);
        if (blockIdx < firstUndisposed) {
            throw new IndexOutOfBoundsException("The requested data are already disposed");
        }

        while (count > 0) {
            byte[] block = blocks.get(blockIdx);
            int toWrite = Math.min(BLOCK_SIZE - offset, count);
            os.write(block, offset, toWrite);

            blockIdx++;
            offset = 0;
            count -= toWrite;
        }
    
public intgetData(long pos)

        if (pos >= length) {
            return -1;
        }

        byte[] block = blocks.get((int)(pos >> BLOCK_SHIFT));
        return block[(int)(pos & BLOCK_MASK)] & 0xFF;
    
public intgetData(byte[] buffer, int offset, int count, long pos)

        if (count > buffer.length - offset || count < 0 || offset < 0) {
            throw new IndexOutOfBoundsException();
        }
        if (count == 0) {
            return 0;
        }
        if (pos >= length) {
            return -1;
        }

        if (count + pos > length) {
            count = (int) (length - pos);
        }

        byte[] block = blocks.get((int)(pos >> BLOCK_SHIFT));
        int nbytes = Math.min(count, BLOCK_SIZE - (int)(pos & BLOCK_MASK));
        System.arraycopy(block, (int)(pos & BLOCK_MASK), buffer, offset, nbytes);

        return nbytes;
    
private voidgrow(long pos)

        int blocksNeeded = (int)(pos >> BLOCK_SHIFT) - blocks.size() + 1;
        for (int i=0; i < blocksNeeded; i++) {
            blocks.add(new byte[BLOCK_SIZE]);
        }

        length = pos + 1;
    
public longlength()

        return length;
    
public voidputData(int oneByte, long pos)

        if (pos >= length) {
            grow(pos);
        }

        byte[] block = blocks.get((int)(pos >> BLOCK_SHIFT));
        block[(int)(pos & BLOCK_MASK)] = (byte) oneByte;
    
public voidputData(byte[] buffer, int offset, int count, long pos)

        if (count > buffer.length - offset || count < 0 || offset < 0) {
            throw new IndexOutOfBoundsException();
        }
        if (count == 0){
            return;
        }

        long lastPos = pos + count - 1;
        if (lastPos >= length) {
            grow(lastPos);
        }

        while (count > 0) {
            byte[] block = blocks.get((int)(pos >> BLOCK_SHIFT));
            int blockOffset = (int)(pos & BLOCK_MASK);
            int toCopy = Math.min(BLOCK_SIZE - blockOffset, count);
            System.arraycopy(buffer, offset, block, blockOffset, toCopy);
            pos += toCopy;
            count -= toCopy;
            offset += toCopy;
        }