diff options
author | Joe Onorato <joeo@android.com> | 2009-08-31 10:12:00 -0700 |
---|---|---|
committer | Joe Onorato <joeo@android.com> | 2009-08-31 10:12:00 -0700 |
commit | b72c5c2e5482cf10117b2b25f642f7616b2326c3 (patch) | |
tree | f02ba1bc29f4fe6853d9b7008eed37cdcfb96e81 /src/proguard/WordReader.java | |
parent | a23344a828357fe4b6596f8af5fed467d72757ab (diff) | |
download | proguard-eclair-release.tar.gz |
ProGuard 4.4android-sdk-tools_r4android-sdk-tools_r3android-sdk-2.1_r1android-sdk-2.0_r1android-sdk-2.0.1_r1android-sdk-2.0.1-docs_r1android-2.1_r2.1sandroid-2.1_r2.1p2android-2.1_r2.1pandroid-2.1_r2android-2.1_r1android-2.0_r1android-2.0.1_r1eclair-sholes-release2eclair-sholes-releaseeclair-releaseeclair-passion-release
Diffstat (limited to 'src/proguard/WordReader.java')
-rw-r--r-- | src/proguard/WordReader.java | 326 |
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 == '"'; + } +} |