1 package org.jf.dexlib2.writer.io; 2 3 import com.google.common.collect.Lists; 4 5 import javax.annotation.Nonnull; 6 import java.io.IOException; 7 import java.io.OutputStream; 8 import java.util.List; 9 10 /** 11 * A deferred output stream that is stored in memory 12 */ 13 public class MemoryDeferredOutputStream extends DeferredOutputStream { 14 private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; 15 16 private final List<byte[]> buffers = Lists.newArrayList(); 17 private byte[] currentBuffer; 18 private int currentPosition; 19 20 public MemoryDeferredOutputStream() { 21 this(DEFAULT_BUFFER_SIZE); 22 } 23 24 public MemoryDeferredOutputStream(int bufferSize) { 25 currentBuffer = new byte[bufferSize]; 26 } 27 28 @Override public void writeTo(OutputStream output) throws IOException { 29 for (byte[] buffer: buffers) { 30 output.write(buffer); 31 } 32 if (currentPosition > 0) { 33 output.write(currentBuffer, 0, currentPosition); 34 } 35 buffers.clear(); 36 currentPosition = 0; 37 } 38 39 @Override public void write(int i) throws IOException { 40 if (remaining() == 0) { 41 buffers.add(currentBuffer); 42 currentBuffer = new byte[currentBuffer.length]; 43 currentPosition = 0; 44 } 45 currentBuffer[currentPosition++] = (byte)i; 46 } 47 48 @Override public void write(byte[] bytes) throws IOException { 49 write(bytes, 0, bytes.length); 50 } 51 52 @Override public void write(byte[] bytes, int offset, int length) throws IOException { 53 int remaining = remaining(); 54 int written = 0; 55 while (length - written > 0) { 56 int toWrite = Math.min(remaining, (length - written)); 57 System.arraycopy(bytes, offset + written, currentBuffer, currentPosition, toWrite); 58 written += toWrite; 59 currentPosition += toWrite; 60 61 remaining = remaining(); 62 if (remaining == 0) { 63 buffers.add(currentBuffer); 64 currentBuffer = new byte[currentBuffer.length]; 65 currentPosition = 0; 66 remaining = currentBuffer.length; 67 } 68 } 69 } 70 71 private int remaining() { 72 return currentBuffer.length - currentPosition; 73 } 74 75 @Nonnull 76 public static DeferredOutputStreamFactory getFactory() { 77 return getFactory(DEFAULT_BUFFER_SIZE); 78 } 79 80 @Nonnull 81 public static DeferredOutputStreamFactory getFactory(final int bufferSize) { 82 return new DeferredOutputStreamFactory() { 83 @Override public DeferredOutputStream makeDeferredOutputStream() { 84 return new MemoryDeferredOutputStream(bufferSize); 85 } 86 }; 87 } 88 } 89