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

de.javagl.common.ui.text.StringUtils Maven / Gradle / Ivy

/*
 * www.javagl.de - Common - UI
 *
 * Copyright (c) 2013-2019 Marco Hutter - http://www.javagl.de
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package de.javagl.common.ui.text;

import java.util.function.IntBinaryOperator;

/**
 * Utility methods related to strings
 */
class StringUtils
{
    /**
     * A comparator for characters that returns 0 when they are equal ignoring
     * the case, and 1 otherwise.
     */
    private static final IntBinaryOperator IGNORING_CASE = (c0, c1) -> 
    {
        char u0 = Character.toUpperCase((char) c0);
        char u1 = Character.toUpperCase((char) c1);
        if (u0 == u1)
        {
            return 0;
        }
        if (Character.toLowerCase(u0) == Character.toLowerCase(u1))
        {
            return 0;
        }
        return 1;
    }; 

    /**
     * Returns the index of the first appearance of the given target in
     * the given source, starting at the given index. Returns -1 if the 
     * target string is not found.
     * 
     * @param source The source string
     * @param target The target string
     * @param startIndex The start index
     * @param ignoreCase Whether the case should be ignored
     * @return The index
     */
    static int indexOf(String source, String target, 
        int startIndex, boolean ignoreCase)
    {
        if (ignoreCase)
        {
            return indexOf(source, target, startIndex, IGNORING_CASE);
        }
        return indexOf(source, target, startIndex, 
            (c0, c1) -> Integer.compare(c0, c1));
    }
    
    /**
     * Returns the index of the first appearance of the given target in
     * the given source, starting at the given index, using the given
     * comparator for characters. Returns -1 if the target string is
     * not found.
     * 
     * @param source The source string
     * @param target The target string
     * @param startIndex The start index
     * @param comparator The comparator
     * @return The index
     */
    private static int indexOf(String source, String target, 
        int startIndex, IntBinaryOperator comparator)
    {
        return indexOf(
            source, 0, source.length(), 
            target, 0, target.length(), 
            startIndex, comparator);
    }

    /**
     * Returns the index of the first appearance of the given range of the
     * target in the given range of the source, source, starting at the 
     * given index, using the given comparator for characters. Returns -1 if 
     * the target string is not found.
     * 
     * @param source The source string
     * @param sourceOffset The source offset
     * @param sourceCount The source length
     * @param target The target string
     * @param targetOffset The target offset
     * @param targetCount The target length
     * @param startIndex The start index
     * @param comparator The comparator
     * @return The index
     */
    private static int indexOf(
        String source, int sourceOffset, int sourceCount, 
        String target, int targetOffset, int targetCount,
        int startIndex, IntBinaryOperator comparator)
    {
        int fromIndex = startIndex;
        
        // Adapted from String#indexOf
        if (fromIndex >= sourceCount)
        {
            return (targetCount == 0 ? sourceCount : -1);
        }
        if (fromIndex < 0)
        {
            fromIndex = 0;
        }
        if (targetCount == 0)
        {
            return fromIndex;
        }

        char first = target.charAt(targetOffset);
        int max = sourceOffset + (sourceCount - targetCount);

        for (int i = sourceOffset + fromIndex; i <= max; i++)
        {
            if (comparator.applyAsInt(source.charAt(i), first) != 0)
            {
                while (++i <= max && 
                    comparator.applyAsInt(source.charAt(i), first) != 0)
                    {
                        // Empty 
                    }
            }
            if (i <= max)
            {
                int j = i + 1;
                int end = j + targetCount - 1;
                for (int k = targetOffset + 1; j < end
                    && comparator.applyAsInt(source.charAt(j),
                        target.charAt(k)) == 0; j++, k++)
                {
                    // Empty 
                }
                if (j == end)
                {
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }
    
    /**
     * Returns the index of the previous appearance of the given target in
     * the given source, starting at the given index. Returns -1 if the 
     * target string is not found.
     * 
     * @param source The source string
     * @param target The target string
     * @param startIndex The start index
     * @param ignoreCase Whether the case should be ignored
     * @return The index
     */
    static int lastIndexOf(String source, String target, 
        int startIndex, boolean ignoreCase)
    {
        if (ignoreCase)
        {
            return lastIndexOf(source, target, startIndex, IGNORING_CASE);
        }
        return lastIndexOf(source, target, startIndex, 
            (c0, c1) -> Integer.compare(c0, c1));
    }
    
    /**
     * Returns the index of the previous appearance of the given target in
     * the given source, starting at the given index, using the given
     * comparator for characters. Returns -1 if the target string is
     * not found.
     * 
     * @param source The source string
     * @param target The target string
     * @param startIndex The start index
     * @param comparator The comparator
     * @return The index
     */
    private static int lastIndexOf(String source, String target, 
        int startIndex, IntBinaryOperator comparator)
    {
        return lastIndexOf(
            source, 0, source.length(), 
            target, 0, target.length(), 
            startIndex, comparator);
    }
    
    /**
     * Returns the index of the previous appearance of the given range of the
     * target in the given range of the source, source, starting at the 
     * given index, using the given comparator for characters. Returns -1 if 
     * the target string is not found.
     * 
     * @param source The source string
     * @param sourceOffset The source offset
     * @param sourceCount The source length
     * @param target The target string
     * @param targetOffset The target offset
     * @param targetCount The target length
     * @param startIndex The start index
     * @param comparator The comparator
     * @return The index
     */
    static int lastIndexOf(
        String source, int sourceOffset, int sourceCount,
        String target, int targetOffset, int targetCount, 
        int startIndex, IntBinaryOperator comparator)
    {
        int fromIndex = startIndex;
        
        // Adapted from String#lastIndexOf
        int rightIndex = sourceCount - targetCount;
        if (fromIndex < 0)
        {
            return -1;
        }
        if (fromIndex > rightIndex)
        {
            fromIndex = rightIndex;
        }
        if (targetCount == 0)
        {
            return fromIndex;
        }

        int strLastIndex = targetOffset + targetCount - 1;
        char strLastChar = target.charAt(strLastIndex);
        int min = sourceOffset + targetCount - 1;
        int i = min + fromIndex;

        startSearchForLastChar: while (true)
        {
            while (i >= min && 
                comparator.applyAsInt(source.charAt(i), strLastChar) != 0)
            {
                i--;
            }
            if (i < min)
            {
                return -1;
            }
            int j = i - 1;
            int start = j - (targetCount - 1);
            int k = strLastIndex - 1;

            while (j > start)
            {
                if (comparator.applyAsInt(
                        source.charAt(j--), target.charAt(k--)) != 0)
                {
                    i--;
                    continue startSearchForLastChar;
                }
            }
            return start - sourceOffset + 1;
        }
    }
    
    /**
     * Private constructor to prevent instantiation
     */
    private StringUtils()
    {
        // Private constructor to prevent instantiation
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy