/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.riotfamily.cachius.http.support;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.LinkedList;
/**
* Writer that scans the output for expressions.
*/
public class ScanWriter extends Writer {
private int index;
private char[] startPattern;
private char endChar;
private int p;
private int maxBlockSize = 512;
private Block block;
private LinkedList<Block> blocks = new LinkedList<Block>();
private Writer out;
public ScanWriter(Writer out, String startMarker, char endChar) {
this.out = out;
this.startPattern = startMarker.toCharArray();
this.endChar = endChar;
}
public Collection<Block> getBlocks() {
return blocks;
}
public boolean foundBlocks() {
return blocks.size() > 0;
}
@Override
public void close() throws IOException {
out.close();
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
int end = off + len;
for (int i = off; i < end; i++) {
char c = cbuf[i];
if (block != null) {
if (c == endChar) {
block.end(index);
blocks.add(block);
block = null;
}
else if (block.length() > maxBlockSize) {
block = null;
}
else {
block.append(c);
}
}
else {
if (c == startPattern[p]) {
p++;
if (p == startPattern.length) {
block = new Block(index + 1 - startPattern.length);
p = 0;
}
}
else {
p = 0;
}
}
index++;
}
out.write(cbuf, off, len);
}
public static class Block {
private int start;
private int end;
private StringBuilder sb = new StringBuilder();
private Block(int start) {
this.start = start;
}
private void append(char c) {
sb.append(c);
}
private void end(int end) {
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
private int length() {
return sb.length();
}
public String getValue() {
return sb.toString();
}
}
}