All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twelvemonkeys.util.StringTokenIterator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008, Harald Kuhr
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name "TwelveMonkeys" nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.twelvemonkeys.util;

import java.util.NoSuchElementException;

/**
 * StringTokenIterator, a drop-in replacement for {@code StringTokenizer}.
 * StringTokenIterator has the following features:
 * 
    *
  • Iterates over a strings, 20-50% faster than {@code StringTokenizer} * (and magnitudes faster than {@code String.split(..)} or * {@code Pattern.split(..)})
  • *
  • Implements the {@code Iterator} interface
  • *
  • Optionally returns delimiters
  • *
  • Optionally returns empty elements
  • *
  • Optionally iterates in reverse
  • *
  • Resettable
  • *
* * @see java.util.StringTokenizer * @author Harald Kuhr * @author last modified by $Author: haku $ * @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/StringTokenIterator.java#1 $ */ public class StringTokenIterator extends AbstractTokenIterator { private final String mString; private final char[] mDelimiters; private int mPosition; private final int mMaxPosition; private String mNext; private String mNextDelimiter; private final boolean mIncludeDelimiters; private final boolean mIncludeEmpty; private final boolean mReverse; public final static int FORWARD = 1; public final static int REVERSE = -1; /** * Stores the value of the delimiter character with the highest value. * It is used to optimize the detection of delimiter characters. */ private final char mMaxDelimiter; /** * Creates a StringTokenIterator * * @param pString the string to be parsed. */ public StringTokenIterator(String pString) { this(pString, " \t\n\r\f".toCharArray(), FORWARD, false, false); } /** * Creates a StringTokenIterator * * @param pString the string to be parsed. * @param pDelimiters the delimiters. */ public StringTokenIterator(String pString, String pDelimiters) { this(pString, toCharArray(pDelimiters), FORWARD, false, false); } /** * Creates a StringTokenIterator * * @param pString the string to be parsed. * @param pDelimiters the delimiters. * @param pDirection iteration direction. */ public StringTokenIterator(String pString, String pDelimiters, int pDirection) { this(pString, toCharArray(pDelimiters), pDirection, false, false); } /** * Creates a StringTokenIterator * * @param pString the string to be parsed. * @param pDelimiters the delimiters. * @param pIncludeDelimiters flag indicating whether to return delimiters as tokens. */ public StringTokenIterator(String pString, String pDelimiters, boolean pIncludeDelimiters) { this(pString, toCharArray(pDelimiters), FORWARD, pIncludeDelimiters, false); } /** * Creates a StringTokenIterator * * @param pString the string to be parsed. * @param pDelimiters the delimiters. * @param pDirection iteration direction. * @param pIncludeDelimiters flag indicating whether to return delimiters as tokens. * @param pIncludeEmpty flag indicating whether to return empty tokens * */ public StringTokenIterator(String pString, String pDelimiters, int pDirection, boolean pIncludeDelimiters, boolean pIncludeEmpty) { this(pString, toCharArray(pDelimiters), pDirection, pIncludeDelimiters, pIncludeEmpty); } /** * Implementation. * * @param pString the string to be parsed. * @param pDelimiters the delimiters. * @param pDirection iteration direction. * @param pIncludeDelimiters flag indicating whether to return delimiters as tokens. * @param pIncludeEmpty flag indicating whether to return empty tokens */ private StringTokenIterator(String pString, char[] pDelimiters, int pDirection, boolean pIncludeDelimiters, boolean pIncludeEmpty) { if (pString == null) { throw new IllegalArgumentException("string == null"); } mString = pString; mMaxPosition = pString.length(); mDelimiters = pDelimiters; mIncludeDelimiters = pIncludeDelimiters; mReverse = (pDirection == REVERSE); mIncludeEmpty = pIncludeEmpty; mMaxDelimiter = initMaxDelimiter(pDelimiters); reset(); } private static char[] toCharArray(String pDelimiters) { if (pDelimiters == null) { throw new IllegalArgumentException("delimiters == null"); } return pDelimiters.toCharArray(); } /** * Returns the highest char in the delimiter set. * @param pDelimiters the delimiter set * @return the highest char */ private static char initMaxDelimiter(char[] pDelimiters) { if (pDelimiters == null) { return 0; } char max = 0; for (char c : pDelimiters) { if (max < c) { max = c; } } return max; } /** * Resets this iterator. * */ public void reset() { mPosition = 0; mNext = null; mNextDelimiter = null; } /** * Returns {@code true} if the iteration has more elements. (In other * words, returns {@code true} if {@code next} would return an element * rather than throwing an exception.) * * @return {@code true} if the iterator has more elements. */ public boolean hasNext() { return (mNext != null || fetchNext() != null); } private String fetchNext() { // If next is delimiter, return fast if (mNextDelimiter != null) { mNext = mNextDelimiter; mNextDelimiter = null; return mNext; } // If no more chars, return null if (mPosition >= mMaxPosition) { return null; } return mReverse ? fetchReverse() : fetchForward(); } private String fetchReverse() { // Get previous position int prevPos = scanForPrev(); // Store next string mNext = mString.substring(prevPos + 1, mMaxPosition - mPosition); if (mIncludeDelimiters && prevPos >= 0 && prevPos < mMaxPosition) { mNextDelimiter = mString.substring(prevPos, prevPos + 1); } mPosition = mMaxPosition - prevPos; // Skip empty if (mNext.length() == 0 && !mIncludeEmpty) { return fetchNext(); } return mNext; } private String fetchForward() { // Get next position int nextPos = scanForNext(); // Store next string mNext = mString.substring(mPosition, nextPos); if (mIncludeDelimiters && nextPos >= 0 && nextPos < mMaxPosition) { mNextDelimiter = mString.substring(nextPos, nextPos + 1); } mPosition = ++nextPos; // Skip empty if (mNext.length() == 0 && !mIncludeEmpty) { return fetchNext(); } return mNext; } private int scanForNext() { int position = mPosition; while (position < mMaxPosition) { // Find next match, using all delimiters char c = mString.charAt(position); if (c <= mMaxDelimiter) { // Find first delimiter match for (char delimiter : mDelimiters) { if (c == delimiter) { return position;// Return if match } } } // Next... position++; } // Return last position, if no match return position; } private int scanForPrev() { int position = (mMaxPosition - 1) - mPosition; while (position >= 0) { // Find next match, using all delimiters char c = mString.charAt(position); if (c <= mMaxDelimiter) { // Find first delimiter match for (char delimiter : mDelimiters) { if (c == delimiter) { return position;// Return if match } } } // Next... position--; } // Return first position, if no match return position; } /** * Returns the next element in the iteration. * * @return the next element in the iteration. * @exception java.util.NoSuchElementException iteration has no more elements. */ public String next() { if (!hasNext()) { throw new NoSuchElementException(); } String next = mNext; mNext = fetchNext(); return next; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy