1 package be
.nikiroo
.utils
.streams
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.util
.ArrayList
;
8 import be
.nikiroo
.utils
.StringUtils
;
11 * This {@link InputStream} will change some of its content by replacing it with
16 public class ReplaceInputStream
extends BufferedInputStream
{
18 * The minimum size of the internal buffer (could be more if at least one of
19 * the 'FROM' bytes arrays is > 2048 bytes — in that case the
20 * buffer will be twice the largest size of the 'FROM' bytes arrays).
22 * This is a different buffer than the one from the inherited class.
24 static private final int MIN_BUFFER_SIZE
= 4096;
26 private byte[][] froms
;
28 private int bufferSize
;
29 private int maxFromSize
;
32 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
36 * the under-laying {@link InputStream}
38 * the {@link String} to replace
40 * the {@link String} to replace with
42 public ReplaceInputStream(InputStream in
, String from
, String to
) {
43 this(in
, StringUtils
.getBytes(from
), StringUtils
.getBytes(to
));
47 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
51 * the under-laying {@link InputStream}
53 * the value to replace
55 * the value to replace with
57 public ReplaceInputStream(InputStream in
, byte[] from
, byte[] to
) {
58 this(in
, new byte[][] { from
}, new byte[][] { to
});
62 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
65 * Note that they will be replaced in order, and that for each <tt>from</tt>
66 * a <tt>to</tt> must correspond.
69 * the under-laying {@link InputStream}
71 * the values to replace
73 * the values to replace with
75 public ReplaceInputStream(InputStream in
, String
[] froms
, String
[] tos
) {
76 this(in
, StreamUtils
.getBytes(froms
), StreamUtils
.getBytes(tos
));
80 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
83 * Note that they will be replaced in order, and that for each <tt>from</tt>
84 * a <tt>to</tt> must correspond.
87 * the under-laying {@link InputStream}
89 * the values to replace
91 * the values to replace with
93 public ReplaceInputStream(InputStream in
, byte[][] froms
, byte[][] tos
) {
96 if (froms
.length
!= tos
.length
) {
97 throw new IllegalArgumentException(
98 "For replacing, each FROM must have a corresponding TO");
105 for (int i
= 0; i
< froms
.length
; i
++) {
106 maxFromSize
= Math
.max(maxFromSize
, froms
[i
].length
);
110 for (int i
= 0; i
< tos
.length
; i
++) {
111 maxToSize
= Math
.max(maxToSize
, tos
[i
].length
);
114 // We need at least maxFromSize so we can iterate and replace
115 bufferSize
= Math
.max(4 * Math
.max(maxToSize
, maxFromSize
),
120 protected boolean preRead() throws IOException
{
121 boolean rep
= super.preRead();
127 protected int read(InputStream in
, byte[] buffer
) throws IOException
{
128 buffer
= null; // do not use the buffer.
130 byte[] newBuffer
= new byte[bufferSize
];
132 while (read
< bufferSize
/ 2) {
133 int thisTime
= in
.read(newBuffer
, read
, bufferSize
/ 2 - read
);
140 List
<byte[]> bbBuffers
= new ArrayList
<byte[]>();
141 List
<Integer
> bbOffsets
= new ArrayList
<Integer
>();
142 List
<Integer
> bbLengths
= new ArrayList
<Integer
>();
145 for (int i
= 0; i
< read
; i
++) {
146 for (int fromIndex
= 0; fromIndex
< froms
.length
; fromIndex
++) {
147 byte[] from
= froms
[fromIndex
];
148 byte[] to
= tos
[fromIndex
];
151 && StreamUtils
.startsWith(from
, newBuffer
, i
, read
)) {
152 if (i
- offset
> 0) {
153 bbBuffers
.add(newBuffer
);
154 bbOffsets
.add(offset
);
155 bbLengths
.add(i
- offset
);
161 bbLengths
.add(to
.length
);
171 bbBuffers
.add(newBuffer
);
172 bbOffsets
.add(offset
);
173 bbLengths
.add(read
- offset
);
176 for (int i
= bbBuffers
.size() - 1; i
>= 0; i
--) {
177 // DEBUG("pushback", bbBuffers.get(i), bbOffsets.get(i),
178 // bbLengths.get(i));
179 pushback(bbBuffers
.get(i
), bbOffsets
.get(i
), bbLengths
.get(i
));
185 // static public void DEBUG(String title, byte[] b, int off, int len) {
186 // String str = new String(b,off,len);
187 // if(str.length()>20) {
188 // str=str.substring(0,10)+" ...
189 // "+str.substring(str.length()-10,str.length());
194 public String
toString() {
195 StringBuilder rep
= new StringBuilder();
196 rep
.append(getClass().getSimpleName()).append("\n");
198 for (int i
= 0; i
< froms
.length
; i
++) {
199 byte[] from
= froms
[i
];
203 rep
.append("bytes[").append(from
.length
).append("]");
204 if (from
.length
<= 20) {
205 rep
.append(" (").append(new String(from
)).append(")");
208 rep
.append("bytes[").append(to
.length
).append("]");
209 if (to
.length
<= 20) {
210 rep
.append(" (").append(new String(to
)).append(")");
215 return "[" + rep
+ "]";