1package org.jf.dexlib2.writer.io;
2
3import javax.annotation.Nonnull;
4import java.io.IOException;
5import java.io.InputStream;
6import java.io.OutputStream;
7import java.util.Arrays;
8
9public class MemoryDataStore implements DexDataStore {
10    private byte[] buf;
11
12    public MemoryDataStore() {
13        this(1024 * 1024);
14    }
15
16    public MemoryDataStore(int initialCapacity) {
17        buf = new byte[initialCapacity];
18    }
19
20    public byte[] getData() {
21        return buf;
22    }
23
24    @Nonnull @Override public OutputStream outputAt(final int offset) {
25        return new OutputStream() {
26            private int position = offset;
27            @Override public void write(int b) throws IOException {
28                growBufferIfNeeded(position);
29                buf[position++] = (byte)b;
30            }
31
32            @Override public void write(byte[] b) throws IOException {
33                growBufferIfNeeded(position + b.length);
34                System.arraycopy(b, 0, buf, position, b.length);
35                position += b.length;
36            }
37
38            @Override public void write(byte[] b, int off, int len) throws IOException {
39                growBufferIfNeeded(position + len);
40                System.arraycopy(b, off, buf, position, len);
41                position += len;
42            }
43        };
44    }
45
46    private void growBufferIfNeeded(int index) {
47        if (index < buf.length) {
48            return;
49        }
50        buf = Arrays.copyOf(buf, (int)((index + 1) * 1.2));
51    }
52
53    @Nonnull @Override public InputStream readAt(final int offset) {
54        return new InputStream() {
55            private int position = offset;
56
57            @Override public int read() throws IOException {
58                if (position >= buf.length) {
59                    return -1;
60                }
61                return buf[position++];
62            }
63
64            @Override public int read(byte[] b) throws IOException {
65                int readLength = Math.min(b.length, buf.length - position);
66                if (readLength <= 0) {
67                    if (position >= buf.length) {
68                        return -1;
69                    }
70                    return 0;
71                }
72                System.arraycopy(buf, position, b, 0, readLength);
73                position += readLength;
74                return readLength;
75            }
76
77            @Override public int read(byte[] b, int off, int len) throws IOException {
78                int readLength = Math.min(len, buf.length - position);
79                if (readLength <= 0) {
80                    if (position >= buf.length) {
81                        return -1;
82                    }
83                    return 0;
84                }
85                System.arraycopy(buf, position, b, 0, readLength);
86                position += readLength;
87                return readLength;
88            }
89
90            @Override public long skip(long n) throws IOException {
91                int skipLength = (int)Math.min(n, buf.length - position);
92                position += skipLength;
93                return skipLength;
94            }
95
96            @Override public int available() throws IOException {
97                return buf.length - position;
98            }
99        };
100    }
101
102    @Override public void close() throws IOException {
103        // no-op
104    }
105}
106