Streams: bug fixes
[nikiroo-utils.git] / src / be / nikiroo / utils / streams / ReplaceInputStream.java
CommitLineData
8e76f6ab 1package be.nikiroo.utils.streams;
6ef54b36
NR
2
3import java.io.IOException;
4import java.io.InputStream;
6ef54b36 5
876dbf8b 6/**
c8ce09c4
NR
7 * This {@link InputStream} will change some of its content by replacing it with
8 * something else.
876dbf8b
NR
9 *
10 * @author niki
11 */
6ef54b36 12public class ReplaceInputStream extends BufferedInputStream {
627f866e
NR
13 private byte[][] froms;
14 private byte[][] tos;
15 private int maxToSize;
6ef54b36
NR
16
17 private byte[] source;
18 private int spos;
19 private int slen;
20
876dbf8b
NR
21 /**
22 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
23 * <tt>to</tt>.
24 *
25 * @param in
26 * the under-laying {@link InputStream}
27 * @param from
28 * the {@link String} to replace
29 * @param to
30 * the {@link String} to replace with
31 */
6ef54b36 32 public ReplaceInputStream(InputStream in, String from, String to) {
c8ce09c4 33 this(in, StreamUtils.bytes(from), StreamUtils.bytes(to));
6ef54b36
NR
34 }
35
876dbf8b
NR
36 /**
37 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
38 * <tt>to</tt>.
39 *
40 * @param in
41 * the under-laying {@link InputStream}
42 * @param from
43 * the value to replace
44 * @param to
45 * the value to replace with
46 */
6ef54b36 47 public ReplaceInputStream(InputStream in, byte[] from, byte[] to) {
627f866e
NR
48 this(in, new byte[][] { from }, new byte[][] { to });
49 }
50
51 /**
52 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
53 * with <tt>tos</tt>.
54 * <p>
55 * Note that they will be replaced in order, and that for each <tt>from</tt>
56 * a <tt>to</tt> must correspond.
57 *
58 * @param in
59 * the under-laying {@link InputStream}
60 * @param froms
61 * the values to replace
62 * @param tos
63 * the values to replace with
64 */
65 public ReplaceInputStream(InputStream in, String[] froms, String[] tos) {
66 this(in, StreamUtils.bytes(froms), StreamUtils.bytes(tos));
67 }
68
69 /**
70 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
71 * with <tt>tos</tt>.
72 * <p>
73 * Note that they will be replaced in order, and that for each <tt>from</tt>
74 * a <tt>to</tt> must correspond.
75 *
76 * @param in
77 * the under-laying {@link InputStream}
78 * @param froms
79 * the values to replace
80 * @param tos
81 * the values to replace with
82 */
83 public ReplaceInputStream(InputStream in, byte[][] froms, byte[][] tos) {
6ef54b36 84 super(in);
627f866e
NR
85
86 if (froms.length != tos.length) {
87 throw new IllegalArgumentException(
88 "For replacing, each FROM must have a corresponding TO");
89 }
90
91 this.froms = froms;
92 this.tos = tos;
93
94 for (int i = 0; i < tos.length; i++) {
95 maxToSize = Math.max(maxToSize, tos[i].length);
96 }
6ef54b36
NR
97
98 source = new byte[4096];
99 spos = 0;
100 slen = 0;
101 }
102
103 @Override
028ff7c2
NR
104 protected int read(InputStream in, byte[] buffer, int off, int len)
105 throws IOException {
106 if (len < maxToSize || source.length < maxToSize * 2) {
6ef54b36 107 throw new IOException(
627f866e 108 "An underlaying buffer is too small for these replace values");
6ef54b36
NR
109 }
110
111 if (spos >= slen) {
112 spos = 0;
113 slen = in.read(source);
114 }
115
116 // Note: very simple, not efficient implementation, sorry.
117 int count = 0;
028ff7c2 118 while (spos < slen && count < len - maxToSize) {
627f866e
NR
119 boolean replaced = false;
120 for (int i = 0; i < froms.length; i++) {
121 if (froms[i] != null && froms[i].length > 0
122 && StreamUtils.startsWith(froms[i], source, spos, slen)) {
123 if (tos[i] != null && tos[i].length > 0) {
028ff7c2
NR
124 System.arraycopy(tos[i], 0, buffer, off + spos,
125 tos[i].length);
627f866e
NR
126 count += tos[i].length;
127 }
128
129 spos += froms[i].length;
130 replaced = true;
131 break;
132 }
133 }
134
135 if (!replaced) {
028ff7c2 136 buffer[off + count++] = source[spos++];
6ef54b36
NR
137 }
138 }
139
140 return count;
141 }
6ef54b36 142}