001 /* StringTokenizer -- breaks a String into tokens 002 Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package 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 */ 061 public 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