package org.limewire.util; import java.util.NoSuchElementException; /** * Provides a string tokenizer that respects quotes. If a separator is followed * by a quote the next token will extend to the next quote even if there are * separators in between. Quote characters will not be returned. * <p> * Based on code from the XNap-Commons (http;//xnap-commons.sf.net) */ public class QuotedStringTokenizer { public static final char QUOTE_CHAR = '"'; private final boolean returnSeparators; private final String text; private final int maxIndex; private String separators; private int index; /** * Constructs a <code>QuotedStringTokenizer</code>. * * @see java.util.StringTokenizer */ public QuotedStringTokenizer(String text, String separators, boolean returnSeparators) { this.text = text; this.maxIndex = text.length() - 1; this.separators = separators; this.returnSeparators = returnSeparators; } /** * Constructs a <code>QuotedStringTokenizer</code>. * * @see java.util.StringTokenizer */ public QuotedStringTokenizer(String text, String separators) { this(text, separators, false); } /** * Constructs a <code>QuotedStringTokenizer</code>. * * @see java.util.StringTokenizer */ public QuotedStringTokenizer(String text) { this(text, " ", false); } public int countTokens() { int count = 0; int i = index; Token token; while ((token = nextToken(i)) != null) { count++; i = token.nextIndex; } return count; } public boolean hasMoreTokens() { return nextToken(index) != null; } public String nextToken(String separators) { this.separators = separators; return nextToken(); } public String nextToken() { Token token = nextToken(index); if (token != null) { index = token.nextIndex; return token.text; } throw new NoSuchElementException(); } protected Token nextToken(int index) { if (index > maxIndex) { return null; } if (returnSeparators && separators.indexOf(text.charAt(index)) != -1) { return new Token(text.substring(index, index + 1), index + 1); } // lets get started int i = index; boolean inQuotes = false; StringBuilder token = new StringBuilder(); // eat separators while (i <= maxIndex && separators.indexOf(text.charAt(i)) != -1) { i++; } if (i > maxIndex) { return null; } while (i <= maxIndex) { char c = text.charAt(i); if (separators.indexOf(c) != -1) { if (inQuotes) { token.append(c); } else { return new Token(token.toString(), i); } } else if (c == QUOTE_CHAR) { // TODO add support for escaping of quote characters inQuotes = !inQuotes; } else { token.append(c); } i++; } return new Token(token.toString(), i); } private static class Token { Token(String text, int nextIndex) { this.text = text; this.nextIndex = nextIndex; } String text; int nextIndex; } }