/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.core.runtime.internal;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
public class HrefParser {
private Reader reader;
public HrefParser(Reader reader) {
this.reader = reader;
}
public String[] parse() throws IOException {
final ArrayList<String> list = new ArrayList<String>(32);
parse(new Handler() {
public void onValueSeen(String value) {
list.add(value);
}
});
return list.toArray(new String[0]);
}
public void parse(Handler handler) throws IOException {
M m = M.TEXT;
StringBuilder buffer = new StringBuilder(1024);
while (true) {
final int i = reader.read();
if (i == -1) {
break;
}
char c = (char) i;
buffer.append(Character.isWhitespace(c) ? ' ' : c);
if (m == M.TEXT) {
if (endsWith(buffer, "<!--")) {
buffer.setLength(0);
m = M.COMMENT;
} else if (endsWith(buffer, " href")) {
buffer.setLength(0);
m = M.HREF_SEEN;
} else if (c == '>') {
buffer.setLength(0);
}
} else if (m == M.COMMENT) {
if (endsWith(buffer, "-->")) {
buffer.setLength(0);
m = M.TEXT;
}
} else if (m == M.HREF_SEEN) {
if (c == '=') {
m = M.HREF_EQ_SEEN;
} else if (!Character.isWhitespace(c)) {
m = M.TEXT;
}
buffer.setLength(0);
} else if (m == M.HREF_EQ_SEEN) {
if (c == '"') {
m = M.HREF_VALUE;
} else if (c == '\'') {
m = M.HREF_VALUE;
} else if (!Character.isWhitespace(c)) {
m = M.HREF_VALUE;
} else {
buffer.setLength(0);
}
} else if (m == M.HREF_VALUE) {
if (startsWith(buffer, "\"")) {
if (c == '"') {
handler.onValueSeen(buffer.substring(1, buffer.length() - 1));
buffer.setLength(0);
m = M.TEXT;
}
} else if (startsWith(buffer, "'")) {
if (c == '\'') {
handler.onValueSeen(buffer.substring(1, buffer.length() - 1));
buffer.setLength(0);
m = M.TEXT;
}
} else {
if (Character.isWhitespace(c) || c == '>' || c == '/') {
handler.onValueSeen(buffer.substring(0, buffer.length() - 1));
buffer.setLength(0);
m = M.TEXT;
}
}
} else {
throw new IllegalStateException();
}
}
}
boolean startsWith(StringBuilder buffer, String token) {
final int n = token.length();
if (buffer.length() < n) {
return false;
}
for (int i = 0; i < n; i++) {
final char tc = token.charAt(i);
final char bc = buffer.charAt(i);
if (Character.toUpperCase(tc) !=
Character.toUpperCase(bc)) {
return false;
}
}
return true;
}
boolean endsWith(StringBuilder buffer, String token) {
final int n = token.length();
if (buffer.length() < n) {
return false;
}
for (int i = 0; i < n; i++) {
final char tc = token.charAt(i);
final char bc = buffer.charAt(buffer.length() - n + i);
if (Character.toUpperCase(tc) !=
Character.toUpperCase(bc)) {
return false;
}
}
return true;
}
private enum M {
TEXT,
COMMENT,
HREF_SEEN,
HREF_EQ_SEEN,
HREF_VALUE,
}
public static interface Handler {
void onValueSeen(String value);
}
}