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

org.eclipse.sisu.space.Tokens Maven / Gradle / Ivy

There is a newer version: 3.0.0-alpha-3
Show newest version
/*******************************************************************************
 * Copyright (c) 2021-present Sonatype, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Stuart McCulloch - initial API and implementation
 *******************************************************************************/
package org.eclipse.sisu.space;

import java.util.Iterator;
import java.util.NoSuchElementException;

import static java.lang.Character.isWhitespace;

/**
 * Utility methods for dealing with tokens.
 */
public final class Tokens
{
    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    private Tokens()
    {
        // static utility class, not allowed to create instances
    }

    // ----------------------------------------------------------------------
    // Utility methods
    // ----------------------------------------------------------------------

    /**
     * Lazily splits the given string into whitespace-trimmed tokens, using comma as the token separator.
     *
     * @param text The text to split into tokens
     * @return Sequence of comma-separated tokens
     */
    public static Iterable splitByComma( final String text )
    {
        return new Iterable()
        {
            @Override
            public Iterator iterator()
            {
                return new TokenIterator( text, ',', true );
            }
        };
    }

    /**
     * Lazily splits the given string into non-trimmed tokens, using star as the token separator.
     *
     * @param text The text to split into tokens
     * @return Sequence of star-separated tokens
     */
    public static Iterable splitByStar( final String text )
    {
        return new Iterable()
        {
            @Override
            public Iterator iterator()
            {
                return new TokenIterator( text, '*', false );
            }
        };
    }

    // ----------------------------------------------------------------------
    // Implementation types
    // ----------------------------------------------------------------------

    /**
     * {@link Iterator} that lazily splits a string into tokens.
     */
    static final class TokenIterator
        implements Iterator
    {
        // ----------------------------------------------------------------------
        // Implementation fields
        // ----------------------------------------------------------------------

        private final String text;

        private final char separator;

        private final boolean trimming;

        private int tokenIndex;

        // ----------------------------------------------------------------------
        // Constructors
        // ----------------------------------------------------------------------

        TokenIterator( final String text, final char separator, final boolean trimming )
        {
            this.text = text;
            this.separator = separator;
            this.trimming = trimming;
            this.tokenIndex = nextToken( 0 );
        }

        // ----------------------------------------------------------------------
        // Public methods
        // ----------------------------------------------------------------------

        @Override
        public boolean hasNext()
        {
            return tokenIndex < text.length();
        }

        @Override
        public String next()
        {
            if ( hasNext() )
            {
                final int separatorIndex = nextSeparator( tokenIndex + 1 );
                final int tokenEnd = trimming ? trimBack( separatorIndex - 1 ) + 1 : separatorIndex;
                final String token = text.substring( tokenIndex, tokenEnd );
                tokenIndex = nextToken( separatorIndex + 1 );
                return token;
            }
            throw new NoSuchElementException();
        }

        @Override
        public void remove()
        {
            throw new UnsupportedOperationException();
        }

        // ----------------------------------------------------------------------
        // Implementation methods
        // ----------------------------------------------------------------------

        /**
         * Finds the start of the next token, i.e. not the separator or whitespace when trimming.
         */
        private int nextToken( final int from )
        {
            final int max = text.length();
            for ( int i = from; i < max; i++ )
            {
                final char c = text.charAt( i );
                if ( c != separator && false == ( trimming && isWhitespace( c ) ) )
                {
                    return i;
                }
            }
            return max; // return end-of-string if no more tokens
        }

        /**
         * Finds the position of the next separator that follows the current token.
         */
        private int nextSeparator( final int from )
        {
            final int i = text.indexOf( separator, from );
            return i >= 0 ? i : text.length();
        }

        /**
         * Backtracks to find the non-whitespace end of the current token.
         */
        private int trimBack( final int from )
        {
            final int min = tokenIndex;
            for ( int i = from; i > min; i-- )
            {
                if ( !isWhitespace( text.charAt( i ) ) )
                {
                    return i;
                }
            }
            return min; // we know the start of the current token cannot be whitespace
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy