001/* StringTokenizer -- breaks a String into tokens 002 Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package java.util; 040 041/** 042 * This class splits a string into tokens. The caller can set on which 043 * delimiters the string should be split and if the delimiters should be 044 * returned. This is much simpler than {@link java.io.StreamTokenizer}. 045 * 046 * <p>You may change the delimiter set on the fly by calling 047 * nextToken(String). But the semantic is quite difficult; it even 048 * depends on calling <code>hasMoreTokens()</code>. You should call 049 * <code>hasMoreTokens()</code> before, otherwise the old delimiters 050 * after the last token are candidates for being returned. 051 * 052 * <p>If you want to get the delimiters, you have to use the three argument 053 * constructor. The delimiters are returned as token consisting of a 054 * single character. 055 * 056 * @author Jochen Hoenicke 057 * @author Warren Levy (warrenl@cygnus.com) 058 * @see java.io.StreamTokenizer 059 * @status updated to 1.4 060 */ 061public class StringTokenizer implements Enumeration<Object> 062{ 063 // WARNING: StringTokenizer is a CORE class in the bootstrap cycle. See the 064 // comments in vm/reference/java/lang/Runtime for implications of this fact. 065 066 /** 067 * The position in the str, where we currently are. 068 */ 069 private int pos; 070 071 /** 072 * The string that should be split into tokens. 073 */ 074 private final String str; 075 076 /** 077 * The length of the string. 078 */ 079 private final int len; 080 081 /** 082 * The string containing the delimiter characters. 083 */ 084 private String delim; 085 086 /** 087 * Tells, if we should return the delimiters. 088 */ 089 private final boolean retDelims; 090 091 /** 092 * Creates a new StringTokenizer for the string <code>str</code>, 093 * that should split on the default delimiter set (space, tab, 094 * newline, return and formfeed), and which doesn't return the 095 * delimiters. 096 * 097 * @param str The string to split 098 * @throws NullPointerException if str is null 099 */ 100 public StringTokenizer(String str) 101 { 102 this(str, " \t\n\r\f", false); 103 } 104 105 /** 106 * Create a new StringTokenizer, that splits the given string on 107 * the given delimiter characters. It doesn't return the delimiter 108 * characters. 109 * 110 * @param str the string to split 111 * @param delim a string containing all delimiter characters 112 * @throws NullPointerException if either argument is null 113 */ 114 public StringTokenizer(String str, String delim) 115 { 116 this(str, delim, false); 117 } 118 119 /** 120 * Create a new StringTokenizer, that splits the given string on 121 * the given delimiter characters. If you set 122 * <code>returnDelims</code> to <code>true</code>, the delimiter 123 * characters are returned as tokens of their own. The delimiter 124 * tokens always consist of a single character. 125 * 126 * @param str the string to split 127 * @param delim a string containing all delimiter characters 128 * @param returnDelims tells, if you want to get the delimiters 129 * @throws NullPointerException if str or delim is null 130 */ 131 public StringTokenizer(String str, String delim, boolean returnDelims) 132 { 133 len = str.length(); 134 this.str = str; 135 this.delim = delim; 136 this.retDelims = returnDelims; 137 this.pos = 0; 138 } 139 140 /** 141 * Tells if there are more tokens. 142 * 143 * @return true if the next call of nextToken() will succeed 144 */ 145 public boolean hasMoreTokens() 146 { 147 if (! retDelims) 148 { 149 while (pos < len && delim.indexOf(str.charAt(pos)) >= 0) 150 pos++; 151 } 152 return pos < len; 153 } 154 155 /** 156 * Returns the nextToken, changing the delimiter set to the given 157 * <code>delim</code>. The change of the delimiter set is 158 * permanent, ie. the next call of nextToken(), uses the same 159 * delimiter set. 160 * 161 * @param delim a string containing the new delimiter characters 162 * @return the next token with respect to the new delimiter characters 163 * @throws NoSuchElementException if there are no more tokens 164 * @throws NullPointerException if delim is null 165 */ 166 public String nextToken(String delim) throws NoSuchElementException 167 { 168 this.delim = delim; 169 return nextToken(); 170 } 171 172 /** 173 * Returns the nextToken of the string. 174 * 175 * @return the next token with respect to the current delimiter characters 176 * @throws NoSuchElementException if there are no more tokens 177 */ 178 public String nextToken() throws NoSuchElementException 179 { 180 if (pos < len && delim.indexOf(str.charAt(pos)) >= 0) 181 { 182 if (retDelims) 183 return str.substring(pos, ++pos); 184 while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0) 185 ; 186 } 187 if (pos < len) 188 { 189 int start = pos; 190 while (++pos < len && delim.indexOf(str.charAt(pos)) < 0) 191 ; 192 193 return str.substring(start, pos); 194 } 195 throw new NoSuchElementException(); 196 } 197 198 /** 199 * This does the same as hasMoreTokens. This is the 200 * <code>Enumeration</code> interface method. 201 * 202 * @return true, if the next call of nextElement() will succeed 203 * @see #hasMoreTokens() 204 */ 205 public boolean hasMoreElements() 206 { 207 return hasMoreTokens(); 208 } 209 210 /** 211 * This does the same as nextTokens. This is the 212 * <code>Enumeration</code> interface method. 213 * 214 * @return the next token with respect to the current delimiter characters 215 * @throws NoSuchElementException if there are no more tokens 216 * @see #nextToken() 217 */ 218 public Object nextElement() throws NoSuchElementException 219 { 220 return nextToken(); 221 } 222 223 /** 224 * This counts the number of remaining tokens in the string, with 225 * respect to the current delimiter set. 226 * 227 * @return the number of times <code>nextTokens()</code> will succeed 228 * @see #nextToken() 229 */ 230 public int countTokens() 231 { 232 int count = 0; 233 int delimiterCount = 0; 234 boolean tokenFound = false; // Set when a non-delimiter is found 235 int tmpPos = pos; 236 237 // Note for efficiency, we count up the delimiters rather than check 238 // retDelims every time we encounter one. That way, we can 239 // just do the conditional once at the end of the method 240 while (tmpPos < len) 241 { 242 if (delim.indexOf(str.charAt(tmpPos++)) >= 0) 243 { 244 if (tokenFound) 245 { 246 // Got to the end of a token 247 count++; 248 tokenFound = false; 249 } 250 delimiterCount++; // Increment for this delimiter 251 } 252 else 253 { 254 tokenFound = true; 255 // Get to the end of the token 256 while (tmpPos < len 257 && delim.indexOf(str.charAt(tmpPos)) < 0) 258 ++tmpPos; 259 } 260 } 261 262 // Make sure to count the last token 263 if (tokenFound) 264 count++; 265 266 // if counting delmiters add them into the token count 267 return retDelims ? count + delimiterCount : count; 268 } 269} // class StringTokenizer