ae576e25e7a4833e9ce8f4bea25616ff018eca52
1 package be
.nikiroo
.utils
.streams
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
6 import be
.nikiroo
.utils
.StringUtils
;
9 * This {@link InputStream} will change some of its content by replacing it with
14 public class ReplaceInputStream
extends BufferedInputStream
{
16 * The minimum size of the internal buffer (could be more if at least one of
17 * the 'FROM' bytes arrays is > 2048 bytes — in that case the
18 * buffer will be twice the largest size of the 'FROM' bytes arrays).
20 * This is a different buffer than the one from the inherited class.
22 static private final int MIN_BUFFER_SIZE
= 4096;
24 private byte[][] froms
;
26 private int maxFromSize
;
27 private int maxToSize
;
29 private byte[] source
;
34 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
38 * the under-laying {@link InputStream}
40 * the {@link String} to replace
42 * the {@link String} to replace with
44 public ReplaceInputStream(InputStream in
, String from
, String to
) {
45 this(in
, StringUtils
.getBytes(from
), StringUtils
.getBytes(to
));
49 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
53 * the under-laying {@link InputStream}
55 * the value to replace
57 * the value to replace with
59 public ReplaceInputStream(InputStream in
, byte[] from
, byte[] to
) {
60 this(in
, new byte[][] { from
}, new byte[][] { to
});
64 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
67 * Note that they will be replaced in order, and that for each <tt>from</tt>
68 * a <tt>to</tt> must correspond.
71 * the under-laying {@link InputStream}
73 * the values to replace
75 * the values to replace with
77 public ReplaceInputStream(InputStream in
, String
[] froms
, String
[] tos
) {
78 this(in
, StreamUtils
.getBytes(froms
), StreamUtils
.getBytes(tos
));
82 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
85 * Note that they will be replaced in order, and that for each <tt>from</tt>
86 * a <tt>to</tt> must correspond.
89 * the under-laying {@link InputStream}
91 * the values to replace
93 * the values to replace with
95 public ReplaceInputStream(InputStream in
, byte[][] froms
, byte[][] tos
) {
98 if (froms
.length
!= tos
.length
) {
99 throw new IllegalArgumentException(
100 "For replacing, each FROM must have a corresponding TO");
107 for (int i
= 0; i
< froms
.length
; i
++) {
108 maxFromSize
= Math
.max(maxFromSize
, froms
[i
].length
);
112 for (int i
= 0; i
< tos
.length
; i
++) {
113 maxToSize
= Math
.max(maxToSize
, tos
[i
].length
);
116 // We need at least maxFromSize so we can iterate and replace
117 source
= new byte[Math
.max(2 * Math
.max(maxToSize
, maxFromSize
),
124 protected int read(InputStream in
, byte[] buffer
, int off
, int len
)
126 if (len
< maxToSize
|| source
.length
< maxToSize
* 2) {
127 throw new IOException(
128 "An underlaying buffer is too small for these replace values");
131 // We need at least one byte of data to process
132 if (available() < Math
.max(maxFromSize
, 1) && !eof
) {
134 slen
= in
.read(source
);
137 // Note: very simple, not efficient implementation; sorry.
139 while (spos
< slen
&& count
< len
- maxToSize
) {
140 boolean replaced
= false;
141 for (int i
= 0; i
< froms
.length
; i
++) {
142 if (froms
[i
] != null && froms
[i
].length
> 0
143 && StreamUtils
.startsWith(froms
[i
], source
, spos
, slen
)) {
144 if (tos
[i
] != null && tos
[i
].length
> 0) {
145 System
.arraycopy(tos
[i
], 0, buffer
, off
+ count
,
147 count
+= tos
[i
].length
;
150 spos
+= froms
[i
].length
;
157 buffer
[off
+ count
++] = source
[spos
++];