Java tutorial
//package com.java2s; /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import com.google.common.annotations.VisibleForTesting; public class Main { /** * Similar to String.contains() with two main differences: * <p> * 1) Only searches token prefixes. A token is defined as any combination of letters or * numbers. * <p> * 2) Returns the starting index where the substring is found. * * @param value The string to search. * @param substring The substring to look for. * @return The starting index where the substring is found. {@literal -1} if substring is not * found in value. */ @VisibleForTesting static int contains(String value, String substring) { if (value.length() < substring.length()) { return -1; } // i18n support // Generate the code points for the substring once. // There will be a maximum of substring.length code points. But may be fewer. // Since the array length is not an accurate size, we need to keep a separate variable. final int[] substringCodePoints = new int[substring.length()]; int substringLength = 0; // may not equal substring.length()!! for (int i = 0; i < substring.length();) { final int codePoint = Character.codePointAt(substring, i); substringCodePoints[substringLength] = codePoint; substringLength++; i += Character.charCount(codePoint); } for (int i = 0; i < value.length(); i = findNextTokenStart(value, i)) { int numMatch = 0; for (int j = i; j < value.length() && numMatch < substringLength; ++numMatch) { int valueCp = Character.toLowerCase(value.codePointAt(j)); int substringCp = substringCodePoints[numMatch]; if (valueCp != substringCp) { break; } j += Character.charCount(valueCp); } if (numMatch == substringLength) { return i; } } return -1; } /** * Find the start of the next token. A token is composed of letters and numbers. Any other * character are considered delimiters. * * @param line The string to search for the next token. * @param startIndex The index to start searching. 0 based indexing. * @return The index for the start of the next token. line.length() if next token not found. */ @VisibleForTesting static int findNextTokenStart(String line, int startIndex) { int index = startIndex; // If already in token, eat remainder of token. while (index <= line.length()) { if (index == line.length()) { // No more tokens. return index; } final int codePoint = line.codePointAt(index); if (!Character.isLetterOrDigit(codePoint)) { break; } index += Character.charCount(codePoint); } // Out of token, eat all consecutive delimiters. while (index <= line.length()) { if (index == line.length()) { return index; } final int codePoint = line.codePointAt(index); if (Character.isLetterOrDigit(codePoint)) { break; } index += Character.charCount(codePoint); } return index; } }