summaryrefslogtreecommitdiff
path: root/src/proguard/WordReader.java
diff options
context:
space:
mode:
authorJoe Onorato <joeo@android.com>2009-08-31 10:12:00 -0700
committerJoe Onorato <joeo@android.com>2009-08-31 10:12:00 -0700
commitb72c5c2e5482cf10117b2b25f642f7616b2326c3 (patch)
treef02ba1bc29f4fe6853d9b7008eed37cdcfb96e81 /src/proguard/WordReader.java
parenta23344a828357fe4b6596f8af5fed467d72757ab (diff)
downloadproguard-eclair-release.tar.gz
Diffstat (limited to 'src/proguard/WordReader.java')
-rw-r--r--src/proguard/WordReader.java326
1 files changed, 326 insertions, 0 deletions
diff --git a/src/proguard/WordReader.java b/src/proguard/WordReader.java
new file mode 100644
index 0000000..d73505a
--- /dev/null
+++ b/src/proguard/WordReader.java
@@ -0,0 +1,326 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard;
+
+import java.io.*;
+
+
+/**
+ * An abstract reader of words, with the possibility to include other readers.
+ * Words are separated by spaces or broken off at delimiters. Words containing
+ * spaces or delimiters can be quoted with single or double quotes.
+ * Comments (everything starting with '#' on a single line) are ignored.
+ *
+ * @author Eric Lafortune
+ * @noinspection TailRecursion
+ */
+public abstract class WordReader
+{
+ private static final char COMMENT_CHARACTER = '#';
+
+
+ private File baseDir;
+ private WordReader includeWordReader;
+ private String currentLine;
+ private int currentLineLength;
+ private int currentIndex;
+ private String currentWord;
+ private String currentComments;
+
+
+ /**
+ * Creates a new WordReader with the given base directory.
+ */
+ protected WordReader(File baseDir)
+ {
+ this.baseDir = baseDir;
+ }
+
+
+ /**
+ * Sets the base directory of this reader.
+ */
+ public void setBaseDir(File baseDir)
+ {
+ if (includeWordReader != null)
+ {
+ includeWordReader.setBaseDir(baseDir);
+ }
+ else
+ {
+ this.baseDir = baseDir;
+ }
+ }
+
+
+ /**
+ * Returns the base directory of this reader, if any.
+ */
+ public File getBaseDir()
+ {
+ return includeWordReader != null ?
+ includeWordReader.getBaseDir() :
+ baseDir;
+ }
+
+
+ /**
+ * Specifies to start reading words from the given WordReader. When it is
+ * exhausted, this WordReader will continue to provide its own words.
+ *
+ * @param newIncludeWordReader the WordReader that will start reading words.
+ */
+ public void includeWordReader(WordReader newIncludeWordReader)
+ {
+ if (includeWordReader == null)
+ {
+ includeWordReader = newIncludeWordReader;
+ }
+ else
+ {
+ includeWordReader.includeWordReader(newIncludeWordReader);
+ }
+ }
+
+
+ /**
+ * Reads a word from this WordReader, or from one of its active included
+ * WordReader objects.
+ *
+ * @return the read word.
+ */
+ public String nextWord() throws IOException
+ {
+ currentWord = null;
+
+ // See if we have an included reader to produce a word.
+ if (includeWordReader != null)
+ {
+ // Does the included word reader still produce a word?
+ currentWord = includeWordReader.nextWord();
+ if (currentWord != null)
+ {
+ // Return it if so.
+ return currentWord;
+ }
+
+ // Otherwise close and ditch the word reader.
+ includeWordReader.close();
+ includeWordReader = null;
+ }
+
+ // Get a word from this reader.
+
+ // Skip leading whitespace.
+ while (currentLine != null &&
+ currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
+ {
+ currentIndex++;
+ }
+
+ // Make sure we have a non-blank line.
+ while (currentLine == null || currentIndex == currentLineLength)
+ {
+ currentLine = nextLine();
+ if (currentLine == null)
+ {
+ return null;
+ }
+
+ // Trim off any comments.
+ int comments_start = currentLine.indexOf(COMMENT_CHARACTER);
+ if (comments_start >= 0)
+ {
+ currentLineLength = comments_start;
+
+ // Remember the comments.
+ String comment = currentLine.substring(comments_start + 1);
+ currentComments = currentComments == null ?
+ comment :
+ currentComments + '\n' + comment;
+ }
+ else
+ {
+ currentLineLength = currentLine.length();
+ }
+
+ // Skip leading whitespace.
+ currentIndex = 0;
+ while (currentIndex < currentLineLength &&
+ Character.isWhitespace(currentLine.charAt(currentIndex)))
+ {
+ currentIndex++;
+ }
+ }
+
+ // Find the word starting at the current index.
+ int startIndex = currentIndex;
+ int endIndex;
+
+ char startChar = currentLine.charAt(startIndex);
+
+ if (isDelimiter(startChar))
+ {
+ // The next word is a single delimiting character.
+ endIndex = ++currentIndex;
+ }
+ else if (isQuote(startChar))
+ {
+ // The next word is starting with a quote character.
+ // Skip the opening quote.
+ startIndex++;
+
+ // The next word is a quoted character string.
+ // Find the closing quote.
+ do
+ {
+ currentIndex++;
+
+ if (currentIndex == currentLineLength)
+ {
+ currentWord = currentLine.substring(startIndex-1, currentIndex);
+ throw new IOException("Missing closing quote for "+locationDescription());
+ }
+ }
+ while (currentLine.charAt(currentIndex) != startChar);
+
+ endIndex = currentIndex++;
+ }
+ else
+ {
+ // The next word is a simple character string.
+ // Find the end of the line, the first delimiter, or the first
+ // white space.
+ while (currentIndex < currentLineLength)
+ {
+ char currentCharacter = currentLine.charAt(currentIndex);
+ if (isDelimiter(currentCharacter) ||
+ Character.isWhitespace(currentCharacter))
+ {
+ break;
+ }
+
+ currentIndex++;
+ }
+
+ endIndex = currentIndex;
+ }
+
+ // Remember and return the parsed word.
+ currentWord = currentLine.substring(startIndex, endIndex);
+
+ return currentWord;
+ }
+
+
+ /**
+ * Returns the comments collected before returning the last word.
+ * Starts collecting new comments.
+ *
+ * @return the collected comments, or <code>null</code> if there weren't any.
+ */
+ public String lastComments() throws IOException
+ {
+ if (includeWordReader == null)
+ {
+ String comments = currentComments;
+ currentComments = null;
+ return comments;
+ }
+ else
+ {
+ return includeWordReader.lastComments();
+ }
+ }
+
+
+ /**
+ * Constructs a readable description of the current position in this
+ * WordReader and its included WordReader objects.
+ *
+ * @return the description.
+ */
+ public String locationDescription()
+ {
+ return
+ (includeWordReader == null ?
+ (currentWord == null ?
+ "end of " :
+ "'" + currentWord + "' in " ) :
+ (includeWordReader.locationDescription() + ",\n" +
+ " included from ")) +
+ lineLocationDescription();
+ }
+
+
+ /**
+ * Reads a line from this WordReader, or from one of its active included
+ * WordReader objects.
+ *
+ * @return the read line.
+ */
+ protected abstract String nextLine() throws IOException;
+
+
+ /**
+ * Returns a readable description of the current WordReader position.
+ *
+ * @return the description.
+ */
+ protected abstract String lineLocationDescription();
+
+
+ /**
+ * Closes the FileWordReader.
+ */
+ public void close() throws IOException
+ {
+ // Close and ditch the included word reader, if any.
+ if (includeWordReader != null)
+ {
+ includeWordReader.close();
+ includeWordReader = null;
+ }
+ }
+
+
+ // Small utility methods.
+
+ private boolean isDelimiter(char character)
+ {
+ return character == '@' ||
+ character == '{' ||
+ character == '}' ||
+ character == '(' ||
+ character == ')' ||
+ character == ',' ||
+ character == ';' ||
+ character == File.pathSeparatorChar;
+ }
+
+
+ private boolean isQuote(char character)
+ {
+ return character == '\'' ||
+ character == '"';
+ }
+}