/* Copyright (C) 1998, 1999 Cygnus Solutions This file is part of libgcj. This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ package java.util; /** * @author Warren Levy <warrenl@cygnus.com> * @date August 24, 1998. */ /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 * "The Java Language Specification", ISBN 0-201-63451-1 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. * Status: Believed complete and correct */ public class StringTokenizer implements Enumeration { /* String to be parsed */ private String inputString; /* String to be parsed put into a char array for efficient access */ private char[] chArray; /* Set of delimiter characters for separating tokens */ private String delimiters; /* Whether delimiters in this instance are treated as tokens themselves */ private boolean returnDelimiters; /* Index into the input string to start parsing for the next token */ private int inputStringIndex; public StringTokenizer(String str) { this(str, " \t\n\r", false); } public StringTokenizer(String str, String delims) { this(str, delims, false); } public StringTokenizer(String str, String delims, boolean retDelim) { inputString = str; delimiters = delims; returnDelimiters = retDelim; inputStringIndex = 0; // Work on a copy of the remaining string in a char array // to gain efficiency of using primitives chArray = new char[inputString.length()]; inputString.getChars(0, inputString.length(), chArray, 0); } public int countTokens() { int count = 0; int delimiterCount = 0; boolean tokenFound = false; // Set when a non-delimiter is found int offset = inputStringIndex; // Note for efficiency, we count up the delimiters rather than check // returnDelimiters every time we encounter one. That way, we can // just do the conditional once at the end of the method while (offset < chArray.length) { if (isDelimiter(chArray[offset++])) { if (tokenFound) { // Got to the end of a token count++; tokenFound = false; } delimiterCount++; // Increment for this delimiter } else { tokenFound = true; // Get to the end of the token while (offset < chArray.length && !isDelimiter(chArray[offset])) offset++; } } // Make sure to count the last token if (tokenFound) count++; // if counting delmiters add them into the token count return returnDelimiters ? count + delimiterCount : count; } public boolean hasMoreElements() { return hasMoreTokens(); } public boolean hasMoreTokens() { int offset = inputStringIndex; while (offset < chArray.length) if (!isDelimiter(chArray[offset++]) || returnDelimiters) { // update the current position with the start of the next token inputStringIndex = --offset; return true; } return false; } public Object nextElement() { return nextToken(); } public String nextToken() { int offset = inputStringIndex; int startSubstr = -1; // Make sure we have more chars left to parse // and then find the start of the next token while (offset < chArray.length && startSubstr < 0) { // Find the start of the token; skipping initial delimiters if (!isDelimiter(chArray[offset++])) startSubstr = offset - 1; else if (returnDelimiters) { // The single char delimiter is treated as a token inputStringIndex = offset; // update the current position return inputString.substring(offset - 1, inputStringIndex); } } // Now look for the end of the token while (offset < chArray.length) { if (isDelimiter(chArray[offset++])) { // Found the end of token inputStringIndex = offset - 1; // update the current position return inputString.substring(startSubstr, inputStringIndex); } } // Got to the end of the string without finding the start of a token if (startSubstr < 0) throw new NoSuchElementException(); // Got to the end of the string before a delimiter inputStringIndex = offset; // update the current position return inputString.substring(startSubstr, inputStringIndex); } public String nextToken(String delims) { // First replace with new set of delimiters delimiters = delims; return nextToken(); } // This private method could be inlined but the other methods are // more readable this way, so we'll take the hit on efficiency. private boolean isDelimiter(char ch) { return delimiters.indexOf(ch) >= 0; } }