199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverpackage org.jf.dexlib2.writer.io; 299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport com.google.common.collect.Lists; 499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport javax.annotation.Nonnull; 699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport java.io.IOException; 799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport java.io.OutputStream; 899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverimport java.util.List; 999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 1099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver/** 1199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver * A deferred output stream that is stored in memory 1299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver */ 1399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruverpublic class MemoryDeferredOutputStream extends DeferredOutputStream { 1499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; 1599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 1699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private final List<byte[]> buffers = Lists.newArrayList(); 1799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private byte[] currentBuffer; 1899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private int currentPosition; 1999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 2099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public MemoryDeferredOutputStream() { 2199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver this(DEFAULT_BUFFER_SIZE); 2299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 2399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 2499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public MemoryDeferredOutputStream(int bufferSize) { 2599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentBuffer = new byte[bufferSize]; 2699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 2799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 2899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void writeTo(OutputStream output) throws IOException { 2999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver for (byte[] buffer: buffers) { 3099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.write(buffer); 3199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 3299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver if (currentPosition > 0) { 3399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver output.write(currentBuffer, 0, currentPosition); 3499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 3599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver buffers.clear(); 3699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentPosition = 0; 3799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 3899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 3999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void write(int i) throws IOException { 4099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver if (remaining() == 0) { 4199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver buffers.add(currentBuffer); 4299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentBuffer = new byte[currentBuffer.length]; 4399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentPosition = 0; 4499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 4599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentBuffer[currentPosition++] = (byte)i; 4699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 4799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 4899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void write(byte[] bytes) throws IOException { 4999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver write(bytes, 0, bytes.length); 5099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 5199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 5299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public void write(byte[] bytes, int offset, int length) throws IOException { 5399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver int remaining = remaining(); 5499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver int written = 0; 5599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver while (length - written > 0) { 569a2de93a998958e582e9c2aa0bff7de602cc8771Ben Gruver int toWrite = Math.min(remaining, (length - written)); 5799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver System.arraycopy(bytes, offset + written, currentBuffer, currentPosition, toWrite); 5899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver written += toWrite; 5999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentPosition += toWrite; 6099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 6199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver remaining = remaining(); 6299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver if (remaining == 0) { 6399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver buffers.add(currentBuffer); 6499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentBuffer = new byte[currentBuffer.length]; 6599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver currentPosition = 0; 6699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver remaining = currentBuffer.length; 6799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 6899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 6999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 7099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 7199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver private int remaining() { 7299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return currentBuffer.length - currentPosition; 7399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 7499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 7599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Nonnull 7699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public static DeferredOutputStreamFactory getFactory() { 7799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return getFactory(DEFAULT_BUFFER_SIZE); 7899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 7999b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver 8099b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Nonnull 8199b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver public static DeferredOutputStreamFactory getFactory(final int bufferSize) { 8299b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return new DeferredOutputStreamFactory() { 8399b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver @Override public DeferredOutputStream makeDeferredOutputStream() { 8499b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver return new MemoryDeferredOutputStream(bufferSize); 8599b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 8699b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver }; 8799b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver } 8899b46173c5294d186ccf2e647b86346a22b247c8Ben Gruver} 89